summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLouis Yung-Chieh Lo <yjlou@chromium.org>2011-12-07 18:57:21 +0000
committerVincent Palatin <vpalatin@chromium.org>2011-12-07 19:10:02 +0000
commit6396911897e4cd40f52636d710cee2865acf15e3 (patch)
treea7aa03f7716bd30edaf820afad3a1e36f79c426a
parentbdf7da5b082f6d18dd27f1e5d8cca0b12154a28c (diff)
downloadchrome-ec-6396911897e4cd40f52636d710cee2865acf15e3.tar.gz
Initial sources import 2/3
source files mainly done by Louis. Signed-off-by: Louis Yung-Chieh Lo <yjlou@chromium.org> Change-Id: I93fa38126e208cf3e525828b37bb407099686c6e
-rw-r--r--common/keyboard.c489
-rw-r--r--common/memory_commands.c70
-rw-r--r--include/i8042.h112
-rw-r--r--include/keyboard.h94
-rw-r--r--include/memory_commands.h16
5 files changed, 781 insertions, 0 deletions
diff --git a/common/keyboard.c b/common/keyboard.c
new file mode 100644
index 0000000000..bf155f22c2
--- /dev/null
+++ b/common/keyboard.c
@@ -0,0 +1,489 @@
+/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * Chrome OS EC keyboard common code.
+ */
+
+#include "common.h"
+#include "console.h"
+#include "keyboard.h"
+#include "i8042.h"
+#include "registers.h"
+#include "timer.h"
+#include "uart.h"
+#include "util.h"
+
+#define KEYBOARD_DEBUG 1
+
+#undef ASSERT
+#define ASSERT(expr) do { \
+ if (!(expr)) { \
+ uart_printf("ASSERT(%s) failed at %s:%d.\n", #expr, __FUNCTION__, __LINE__); \
+ while (1) usleep(1000000); \
+ } \
+ } while (0)
+
+/*
+ * i8042 global settings.
+ */
+static int i8042_enabled = 0; /* default the keyboard is disabled. */
+static uint8_t resend_command[MAX_SCAN_CODE_LEN];
+static uint8_t resend_command_len = 0;
+static uint8_t controller_ram_address;
+static uint8_t controller_ram[0x20] = {
+ I8042_AUX_DIS, /* the so called "command byte" */
+ /* 0x01 - 0x1f are controller RAM */
+};
+
+/*
+ * Scancode settings
+ */
+static enum scancode_set_list scancode_set = SCANCODE_SET_2;
+
+/*
+ * Typematic delay, rate and counter variables.
+ *
+ * 7 6 5 4 3 2 1 0
+ * +-----+-----+-----+-----+-----+-----+-----+-----+
+ * |un- | delay | B | D |
+ * | used| 0 1 | 0 1 | 0 1 1 |
+ * +-----+-----+-----+-----+-----+-----+-----+-----+
+ * Formula:
+ * the inter-char delay = (2 ** B) * (D + 8) / 240 (sec)
+ * Default: 500ms delay, 10.9 chars/sec.
+ */
+#define DEFAULT_TYPEMATIC_VALUE ((1 << 5) || (1 << 3) || (3 << 0))
+#define DEFAULT_FIRST_DELAY 500
+#define DEFAULT_INTER_DELAY 91
+static uint8_t typematic_value_from_host = DEFAULT_TYPEMATIC_VALUE;
+static int refill_first_delay = DEFAULT_FIRST_DELAY; /* unit: ms */
+static int counter_first_delay;
+static int refill_inter_delay = DEFAULT_INTER_DELAY; /* unit: ms */
+static int counter_inter_delay;
+
+
+/* The standard Chrome OS keyboard matrix table. */
+#define CROS_ROW_NUM 8 /* TODO: +1 for power button. */
+#define CROS_COL_NUM 13
+static uint16_t scancode_set1[CROS_ROW_NUM][CROS_COL_NUM] = {
+ {0x0000, 0x003A, 0x0005, 0x0030, 0x0009, 0x0073, 0x0031, 0x0000, 0x000d,
+ 0x0000, 0xe038, 0x0000, 0x0000},
+ {0x0000, 0x0001, 0x000c, 0x0022, 0x0083, 0x0000, 0x0023, 0x0000, 0x0028,
+ 0x0001, 0x0000, 0x000e, 0x0078},
+ {0x001d, 0x000f, 0x0004, 0x0014, 0x000b, 0x001b, 0x0015, 0x0056, 0x001a,
+ 0x000a, 0x0073, 0x0000, 0x0000},
+ {0x0000, 0x0029, 0x0006, 0x0006, 0x0003, 0x0000, 0x0007, 0x0000, 0x000c,
+ 0x0000, 0x0000, 0x002b, 0x0079},
+ {0xe01d, 0x001e, 0x0020, 0x0021, 0x001f, 0x0025, 0x0024, 0x0000, 0x0027,
+ 0x0026, 0x002b, 0x001c, 0x0000},
+ {0x0000, 0x002c, 0x002e, 0x002f, 0x002d, 0x0033, 0x0032, 0x002a, 0x0035,
+ 0x0034, 0x0000, 0x0039, 0x0000},
+ {0x0000, 0x0002, 0x0004, 0x0005, 0x0003, 0x0009, 0x0008, 0x0000, 0x000b,
+ 0x000a, 0x0038, 0xe072, 0xe074},
+ {0x0000, 0x0010, 0x0012, 0x0013, 0x0011, 0x0017, 0x0016, 0x0036, 0x0019,
+ 0x0018, 0x0000, 0xe075, 0xe06b},
+};
+
+static uint16_t scancode_set2[CROS_ROW_NUM][CROS_COL_NUM] = {
+ {0x0000, 0xe01f, 0x003b, 0x0032, 0x0044, 0x0051, 0x0031, 0x0000, 0x0055,
+ 0x0000, 0xe011, 0x0000, 0x0000},
+ {0x0000, 0x0076, 0x003e, 0x0034, 0x0083, 0x0000, 0x0033, 0x0000, 0x0052,
+ 0x0043, 0x0000, 0x0066, 0x0067},
+ {0x0014, 0x000d, 0x003d, 0x002c, 0x0040, 0x005b, 0x0035, 0x0061, 0x0054,
+ 0x0042, 0x0051, 0x0000, 0x0000},
+ {0x0000, 0x000e, 0x003c, 0x002e, 0x003f, 0x0000, 0x0036, 0x0000, 0x004e,
+ 0x0000, 0x0000, 0x005d, 0x0064},
+ {0xe014, 0x001c, 0x0023, 0x002b, 0x001b, 0x0042, 0x003b, 0x0000, 0x004c,
+ 0x004b, 0x005d, 0x005a, 0x0000},
+ {0x0000, 0x001a, 0x0021, 0x002a, 0x0022, 0x0041, 0x003a, 0x0012, 0x004a,
+ 0x0049, 0x0000, 0x0029, 0x0000},
+ {0x0000, 0x0016, 0x0026, 0x0025, 0x001e, 0x003e, 0x003d, 0x0000, 0x0045,
+ 0x0046, 0x0011, 0xe050, 0xe04d},
+ {0x0000, 0x0015, 0x0024, 0x002d, 0x001d, 0x0043, 0x003c, 0x0059, 0x004d,
+ 0x0044, 0x0000, 0xe048, 0xe04b},
+};
+
+
+static enum ec_error_list matrix_callback(
+ int8_t row, int8_t col, int8_t pressed,
+ enum scancode_set_list code_set, uint8_t *scan_code, int32_t* len) {
+
+ uint16_t make_code;
+
+ ASSERT(scan_code);
+ ASSERT(len);
+
+ if (row > CROS_ROW_NUM ||
+ col > CROS_COL_NUM) {
+ return EC_ERROR_INVAL;
+ }
+
+ *len = 0;
+
+ switch (code_set) {
+ case SCANCODE_SET_1:
+ make_code = scancode_set1[row][col];
+ break;
+
+ case SCANCODE_SET_2:
+ make_code = scancode_set2[row][col];
+ break;
+
+ default:
+#if KEYBOARD_DEBUG >= 1
+ uart_printf("Not supported scan code set: %d\n", code_set);
+#endif
+ return EC_ERROR_UNIMPLEMENTED;
+ }
+ if (!make_code) {
+#if KEYBOARD_DEBUG >= 1
+ uart_printf("No scancode for [row:col]=[%d:%d].\n", row, col);
+#endif
+ return EC_ERROR_UNIMPLEMENTED;
+ }
+
+ /* Output the make code (from table) */
+ if (make_code >= 0x0100) {
+ *len += 2;
+ scan_code[0] = make_code >> 8;
+ scan_code[1] = make_code & 0xff;
+ } else {
+ *len += 1;
+ scan_code[0] = make_code & 0xff;
+ }
+
+ switch (code_set) {
+ case SCANCODE_SET_1:
+ /* OR 0x80 for the last byte. */
+ if (!pressed) {
+ ASSERT(*len >= 1);
+ scan_code[*len - 1] |= 0x80;
+ }
+ break;
+
+ case SCANCODE_SET_2:
+ /* insert the break byte, move back the last byte and insert a 0xf0 byte
+ * before that. */
+ if (!pressed) {
+ ASSERT(*len >= 1);
+ scan_code[*len] = scan_code[*len - 1];
+ scan_code[*len - 1] = 0xF0;
+ *len += 1;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return EC_SUCCESS;
+}
+
+
+static void reset_rate_and_delay(void) {
+ typematic_value_from_host = DEFAULT_TYPEMATIC_VALUE;
+ refill_first_delay = DEFAULT_FIRST_DELAY;
+ refill_inter_delay = DEFAULT_INTER_DELAY;
+}
+
+
+static void clean_underlying_buffer(void) {
+ i8042_init();
+}
+
+
+void keyboard_state_changed(int row, int col, int is_pressed) {
+ uint8_t scan_code[MAX_SCAN_CODE_LEN];
+ int32_t len;
+ enum ec_error_list ret;
+
+#if KEYBOARD_DEBUG >= 5
+ uart_printf("File %s:%s(): row=%d col=%d is_pressed=%d\n",
+ __FILE__, __FUNCTION__, row, col, is_pressed);
+#endif
+
+ ret = matrix_callback(row, col, is_pressed, scancode_set, scan_code, &len);
+ if (ret == EC_SUCCESS) {
+ ASSERT(len > 0);
+
+ i8042_send_to_host(len, scan_code);
+ } else {
+ /* FIXME: long-term solution is to ignore this key. However, keep
+ * assertion in the debug stage. */
+ ASSERT(ret == EC_SUCCESS);
+ }
+}
+
+
+enum {
+ STATE_NORMAL = 0,
+ STATE_SCANCODE,
+ STATE_SETLEDS,
+ STATE_WRITE_CMD_BYTE,
+ STATE_ECHO_MOUSE,
+ STATE_SEND_TO_MOUSE,
+} data_port_state = STATE_NORMAL;
+
+
+int handle_keyboard_data(uint8_t data, uint8_t *output) {
+ int out_len = 0;
+ int save_for_resend = 1;
+ int i;
+
+#if KEYBOARD_DEBUG >= 5
+ uart_printf("[%d] Recv data:[0x%02x]\n", get_time().le.lo, data);
+#endif
+
+ switch (data_port_state) {
+ case STATE_SCANCODE:
+#if KEYBOARD_DEBUG >= 5
+ uart_printf("Eaten by STATE_SCANCODE\n");
+#endif
+ if (data == SCANCODE_GET_SET) {
+ output[out_len++] = I8042_RET_ACK;
+ output[out_len++] = scancode_set;
+ } else {
+ scancode_set = data;
+#if KEYBOARD_DEBUG >= 1
+ uart_printf("Scancode set to %d\n", scancode_set);
+#endif
+ output[out_len++] = I8042_RET_ACK;
+ }
+ data_port_state = STATE_NORMAL;
+ break;
+
+ case STATE_SETLEDS:
+#if KEYBOARD_DEBUG >= 5
+ uart_printf("Eaten by STATE_SETLEDS\n");
+#endif
+ output[out_len++] = I8042_RET_ACK;
+ data_port_state = STATE_NORMAL;
+ break;
+
+ case STATE_WRITE_CMD_BYTE:
+ controller_ram[controller_ram_address] = data;
+#if KEYBOARD_DEBUG >= 5
+ uart_printf("Set command_bytes[0x%02x]=0x%02x\n",
+ controller_ram_address,
+ controller_ram[controller_ram_address]);
+#endif
+ output[out_len++] = I8042_RET_ACK;
+ data_port_state = STATE_NORMAL;
+ break;
+
+ case STATE_ECHO_MOUSE:
+ output[out_len++] = data;
+ data_port_state = STATE_NORMAL;
+ break;
+
+ case STATE_SEND_TO_MOUSE:
+ data_port_state = STATE_NORMAL;
+ break;
+
+ default: /* STATE_NORMAL */
+ switch (data) {
+ case I8042_CMD_GSCANSET: /* also I8042_CMD_SSCANSET */
+ output[out_len++] = I8042_RET_ACK;
+ data_port_state = STATE_SCANCODE;
+ break;
+
+ case I8042_CMD_SETLEDS: /* fall-thru */
+ case I8042_CMD_EX_SETLEDS:
+ /* We use screen indicator. Do thing in keyboard controller. */
+ output[out_len++] = I8042_RET_ACK;
+ data_port_state = STATE_SETLEDS;
+ break;
+
+ case I8042_CMD_GETID: /* fall-thru */
+ case I8042_CMD_OK_GETID:
+ output[out_len++] = I8042_RET_ACK;
+ output[out_len++] = 0xab; /* Regular keyboards */
+ output[out_len++] = 0x83;
+ break;
+
+ case I8042_CMD_SETREP:
+ output[out_len++] = I8042_RET_ACK;
+ typematic_value_from_host = data;
+ refill_first_delay = counter_first_delay + counter_inter_delay;
+ refill_first_delay = ((typematic_value_from_host & 0x60) >> 5) * 250;
+ refill_inter_delay = 1000 * /* ms */
+ (1 << ((typematic_value_from_host & 0x18) >> 3)) *
+ ((typematic_value_from_host & 0x7) + 8) /
+ 240;
+ break;
+
+ case I8042_CMD_ENABLE:
+ output[out_len++] = I8042_RET_ACK;
+ i8042_enabled = 1;
+ clean_underlying_buffer();
+ break;
+
+ case I8042_CMD_RESET_DIS:
+ output[out_len++] = I8042_RET_ACK;
+ i8042_enabled = 0;
+ reset_rate_and_delay();
+ clean_underlying_buffer();
+ break;
+
+ case I8042_CMD_RESET_DEF:
+ output[out_len++] = I8042_RET_ACK;
+ reset_rate_and_delay();
+ clean_underlying_buffer();
+ break;
+
+ case I8042_CMD_RESET_BAT:
+ output[out_len++] = I8042_RET_ACK;
+ i8042_enabled = 0;
+ output[out_len++] = I8042_RET_BAT;
+ output[out_len++] = I8042_RET_BAT;
+ break;
+
+ case I8042_CMD_RESEND:
+ output[out_len++] = I8042_RET_ACK;
+ save_for_resend = 0;
+ for (i = 0; i < resend_command_len; ++i) {
+ output[out_len++] = resend_command[i];
+ }
+ break;
+
+ /* u-boot hack */
+ case 0x60: /* see CONFIG_USE_CPCIDVI in */
+ case 0x45: /* third_party/u-boot/files/drivers/input/i8042.c */
+ /* just ignore, don't reply anything. */
+ break;
+
+ case I8042_CMD_SETALL_MB: /* fall-thru below */
+ case I8042_CMD_SETALL_MBR:
+ case I8042_CMD_EX_ENABLE:
+ default:
+ output[out_len++] = I8042_RET_NAK;
+ i8042_enabled = 0;
+ reset_rate_and_delay();
+ clean_underlying_buffer();
+#if KEYBOARD_DEBUG >= 1
+ uart_printf("Unsupported i8042 data 0x%02x.\n", data);
+#endif
+ break;
+ }
+ }
+
+ /* For resend, keep output before leaving. */
+ if (out_len && save_for_resend) {
+ ASSERT(out_len <= MAX_SCAN_CODE_LEN);
+ for (i = 0; i < out_len; ++i) {
+ resend_command[i] = output[i];
+ }
+ resend_command_len = out_len;
+ }
+
+ ASSERT(out_len <= MAX_SCAN_CODE_LEN);
+ return out_len;
+}
+
+
+int handle_keyboard_command(uint8_t command, uint8_t *output) {
+ int out_len = 0;
+
+#if KEYBOARD_DEBUG >= 5
+ uart_printf("[%d] Recv cmd:[0x%02x]\n", get_time().le.lo, command);
+#endif
+ switch (command) {
+ case I8042_READ_CMD_BYTE:
+ output[out_len++] = controller_ram[0];
+ break;
+
+ case I8042_WRITE_CMD_BYTE:
+ data_port_state = STATE_WRITE_CMD_BYTE;
+ controller_ram_address = command - 0x60;
+ break;
+
+ case I8042_DIS_KB:
+ i8042_enabled = 0;
+ break;
+
+ case I8042_ENA_KB:
+ i8042_enabled = 1;
+ break;
+
+ case I8042_DIS_MOUSE:
+ controller_ram[0] |= I8042_AUX_DIS;
+ break;
+
+ case I8042_ENA_MOUSE:
+ controller_ram[0] &= ~I8042_AUX_DIS;
+ break;
+
+ case I8042_ECHO_MOUSE:
+ data_port_state = STATE_ECHO_MOUSE;
+ break;
+
+ case I8042_SEND_TO_MOUSE:
+ data_port_state = STATE_SEND_TO_MOUSE;
+ break;
+
+ default:
+ if (command >= I8042_READ_CTL_RAM &&
+ command <= I8042_READ_CTL_RAM_END) {
+ output[out_len++] = controller_ram[command - 0x20];
+ } else if (command >= I8042_WRITE_CTL_RAM &&
+ command <= I8042_WRITE_CTL_RAM_END) {
+ data_port_state = STATE_WRITE_CMD_BYTE;
+ controller_ram_address = command - 0x60;
+ } else {
+#if KEYBOARD_DEBUG >= 1
+ uart_printf("Unsupported cmd:[0x%02x]\n", command);
+#endif
+ i8042_enabled = 0;
+ reset_rate_and_delay();
+ clean_underlying_buffer();
+ output[out_len++] = I8042_RET_NAK;
+ }
+ break;
+ }
+
+ return out_len;
+}
+
+
+static int command_codeset(int argc, char **argv)
+{
+ int set;
+
+ if (argc == 1) {
+ uart_printf("Current scancode set: %d\n", scancode_set);
+ } else if (argc == 2) {
+ set = strtoi(argv[1], NULL, 0);
+ switch (set) {
+ case SCANCODE_SET_1: /* fall-thru */
+ case SCANCODE_SET_2: /* fall-thru */
+ scancode_set = set;
+ uart_printf("Set scancode set to %d\n", scancode_set);
+ break;
+ default:
+ uart_printf("Scancode %d is NOT supported.\n", set);
+ return EC_ERROR_UNKNOWN;
+ break;
+ }
+ } else {
+ uart_puts("Usage: codeset [<set>]\n");
+ return EC_ERROR_UNKNOWN;
+ }
+
+ uart_flush_output();
+
+ return EC_SUCCESS;
+}
+
+
+static const struct console_command console_commands[] = {
+ {"codeset", command_codeset},
+};
+static const struct console_group command_group = {
+ "Keyboard", console_commands, ARRAY_SIZE(console_commands)
+};
+
+
+enum ec_error_list keyboard_init(void) {
+
+ return console_register_commands(&command_group);
+}
diff --git a/common/memory_commands.c b/common/memory_commands.c
new file mode 100644
index 0000000000..e54d567080
--- /dev/null
+++ b/common/memory_commands.c
@@ -0,0 +1,70 @@
+/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* System module for Chrome EC */
+
+#include "console.h"
+#include "registers.h"
+#include "uart.h"
+#include "util.h"
+#include "version.h"
+
+
+static int command_write_word(int argc, char **argv)
+{
+ volatile uint32_t *address;
+ uint32_t value;
+
+ if (argc != 3) {
+ uart_puts("Usage: ww <address> <value>\n");
+ return EC_ERROR_UNKNOWN;
+ }
+ address = (uint32_t*)strtoi(argv[1], NULL, 0);
+ value = strtoi(argv[2], NULL, 0);
+
+ uart_printf("write word 0x%p = 0x%08x\n", address, value);
+ uart_flush_output();
+
+ *address = value;
+
+ return EC_SUCCESS;
+}
+
+
+static int command_read_word(int argc, char **argv)
+{
+ volatile uint32_t *address;
+ uint32_t value;
+
+ if (argc != 2) {
+ uart_puts("Usage: rw <address>\n");
+ return EC_ERROR_UNKNOWN;
+ }
+ address = (uint32_t*)strtoi(argv[1], NULL, 0);
+ value = *address;
+
+ uart_printf("read word 0x%p = 0x%08x\n", address, value);
+ uart_flush_output();
+
+ return EC_SUCCESS;
+}
+
+
+static const struct console_command console_commands[] = {
+ {"rw", command_read_word},
+ {"ww", command_write_word},
+ {"readword", command_read_word},
+ {"writeword", command_write_word},
+};
+static const struct console_group command_group = {
+ "Memory", console_commands, ARRAY_SIZE(console_commands)
+};
+
+
+int memory_commands_init(void)
+{
+ /* Register our internal commands */
+ return console_register_commands(&command_group);
+}
diff --git a/include/i8042.h b/include/i8042.h
new file mode 100644
index 0000000000..440b19ad70
--- /dev/null
+++ b/include/i8042.h
@@ -0,0 +1,112 @@
+/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * i8042.h -- defines the interface between EC core and the EC lib, which
+ * talks to the LPC driver (on the EC side) peering to the keyboard driver
+ * (on the host side).
+ *
+ * The EC lib implements this interface.
+ */
+
+#ifndef __INTERFACE_I8042_H
+#define __INTERFACE_I8042_H
+
+#include "common.h"
+
+
+/* Keyboard command definition. Modified from Linux kernel atkbd.c file. */
+/* port 0x60 */
+#define I8042_CMD_MOUSE_1_1 0xe6
+#define I8042_CMD_MOUSE_2_1 0xe7
+#define I8042_CMD_MOUSE_RES 0xe8 /* dup to I8042_CMD_OK_GETID */
+#define I8042_CMD_GET_MOUSE 0xe9
+#define I8042_CMD_SETLEDS 0xed
+#define I8042_CMD_DIAG_ECHO 0xee
+#define I8042_CMD_GSCANSET 0xf0
+#define I8042_CMD_SSCANSET 0xf0
+#define I8042_CMD_GETID 0xf2
+#define I8042_CMD_SETREP 0xf3
+#define I8042_CMD_ENABLE 0xf4
+#define I8042_CMD_RESET_DIS 0xf5
+#define I8042_CMD_RESET_DEF 0xf6
+#define I8042_CMD_ALL_TYPEM 0xf7
+#define I8042_CMD_SETALL_MB 0xf8
+#define I8042_CMD_SETALL_MBR 0xfa
+#define I8042_CMD_SET_A_KEY_T 0xfb
+#define I8042_CMD_SET_A_KEY_MR 0xfc
+#define I8042_CMD_SET_A_KEY_M 0xfd
+#define I8042_CMD_RESET_BAT 0xff
+#define I8042_CMD_RESEND 0xfe
+#define I8042_CMD_EX_ENABLE 0xea
+#define I8042_CMD_EX_SETLEDS 0xeb
+#define I8042_CMD_OK_GETID 0xe8
+
+/* port 0x64 */
+#define I8042_READ_CMD_BYTE 0x20
+#define I8042_READ_CTL_RAM 0x21
+#define I8042_READ_CTL_RAM_END 0x3f
+#define I8042_WRITE_CMD_BYTE 0x60 /* expect a byte on port 0x60 */
+#define I8042_WRITE_CTL_RAM 0x61
+#define I8042_WRITE_CTL_RAM_END 0x7f
+#define I8042_ROUTE_AUX0 0x90
+#define I8042_ROUTE_AUX1 0x91
+#define I8042_ROUTE_AUX2 0x92
+#define I8042_ROUTE_AUX3 0x93
+#define I8042_ENA_PASSWORD 0xa6
+#define I8042_DIS_MOUSE 0xa7
+#define I8042_ENA_MOUSE 0xa8
+#define I8042_TEST_MOUSE 0xa9
+#define I8042_RESET_SELF_TEST 0xaa
+#define I8042_TEST_KB_PORT 0xab
+#define I8042_DIS_KB 0xad
+#define I8042_ENA_KB 0xae
+#define I8042_ECHO_MOUSE 0xd3 /* expect a byte on port 0x60 */
+#define I8042_SEND_TO_MOUSE 0xd4 /* expect a byte on port 0x60 */
+
+/* port 0x60 return value */
+#define I8042_RET_BAT 0xaa
+#define I8042_RET_EMUL0 0xe0
+#define I8042_RET_EMUL1 0xe1
+#define I8042_RET_ECHO 0xee
+#define I8042_RET_RELEASE 0xf0
+#define I8042_RET_HANJA 0xf1
+#define I8042_RET_HANGEUL 0xf2
+#define I8042_RET_ACK 0xfa
+#define I8042_RET_TEST_FAIL 0xfc
+#define I8042_RET_INTERNAL_FAIL 0xfd
+#define I8042_RET_NAK 0xfe
+#define I8042_RET_ERR 0xff
+
+/* port 64 - command byte bits */
+#define I8042_AUX_DIS (1 << 5)
+#define I8042_SYS_FLAG (1 << 2)
+#define I8042_ENIRQ12 (1 << 1)
+
+
+void i8042_init(void);
+
+
+/* common/i8042.c implements this function, which is called by lpc.c
+ * when an i8042 command/data from host side appears.
+ *
+ * Actually the a pair of data/command write would trigger 2 LPc interrupts.
+ * So, we will queue the data byte first, then call keyboard routine after
+ * receiving the command byte.
+ */
+void i8042_receives_data(int data);
+void i8042_receives_command(int cmd);
+
+
+/* Send the scan code to the host. The EC lib will push the scan code bytes
+ * to host via port 0x60 and assert the IBF flag to trigger an interrupt.
+ * The EC lib must queue them if the host cannot read the previous byte away
+ * in time.
+ *
+ * Return:
+ * EC_ERROR_BUFFER_FULL -- the queue to host is full. Try again?
+ */
+enum ec_error_list i8042_send_to_host(int len, uint8_t *to_host);
+
+
+#endif /* __INTERFACE_I8042_H */
diff --git a/include/keyboard.h b/include/keyboard.h
new file mode 100644
index 0000000000..98394e63c7
--- /dev/null
+++ b/include/keyboard.h
@@ -0,0 +1,94 @@
+/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * The functions implemented by keyboard component of EC core.
+ */
+
+#ifndef __INCLUDE_KEYBOARD_H
+#define __INCLUDE_KEYBOARD_H
+
+#include "common.h"
+
+/***************************************************************************/
+/* Functions exported by common/keyboard.c.
+ */
+
+#define MAX_SCAN_CODE_LEN 4
+
+enum scancode_set_list {
+ SCANCODE_GET_SET = 0,
+ SCANCODE_SET_1,
+ SCANCODE_SET_2,
+ SCANCODE_SET_3,
+ SCANCODE_MAX = SCANCODE_SET_3,
+};
+
+
+/* The initialize code of keyboard lib. Called by core main. */
+enum ec_error_list keyboard_init(void);
+
+
+/* Called by keyboard scan code once any key state change (after de-bounce),
+ *
+ * This function will look up matrix table and convert scancode host.
+ */
+void keyboard_state_changed(int row, int col, int is_pressed);
+
+
+/* Handle the port 0x60 writes from host.
+ *
+ * This functions returns the number of bytes stored in *output buffer.
+ */
+int handle_keyboard_data(uint8_t data, uint8_t *output);
+
+/* Handle the port 0x64 writes from host.
+ *
+ * This functions returns the number of bytes stored in *output buffer.
+ * BUT theose bytes will appear at port 0x60.
+ */
+int handle_keyboard_command(uint8_t command, uint8_t *output);
+
+
+/* Register the board-specific keyboard matrix translation function.
+ * The callback function accepts col/row and returns the scan code.
+ *
+ * Note that *scan_code must be at least 4 bytes long to store maximum
+ * possible sequence.
+ */
+typedef enum ec_error_list (*keyboard_matrix_callback)(
+ int8_t row, int8_t col, int8_t pressed,
+ enum scancode_set_list code_set, uint8_t *scan_code, int32_t* len);
+
+enum ec_error_list keyboard_matrix_register_callback(
+ int8_t row_num, int8_t col_num,
+ keyboard_matrix_callback callback);
+
+
+/***************************************************************************/
+/* Below is the interface with the underlying chip-dependent code.
+ */
+#define MAX_KEYBOARD_MATRIX_ROWS 8
+#define MAX_KEYBOARD_MATRIX_COLS 16
+
+typedef void (*keyboard_callback)(int row, int col, int is_pressed);
+
+/* Registers a callback function to underlayer EC lib. So that any key state
+ * change would notify the upper EC main code.
+ *
+ * Note that passing NULL removes any previously registered callback.
+ */
+enum ec_error_list keyboard_register_callback(keyboard_callback cb);
+
+/* Asks the underlayer EC lib what keys are pressed right now.
+ *
+ * Sets bit_array to a debounced array of which keys are currently pressed,
+ * where a 1-bit means the key is pressed. For example, if only row=2 col=3
+ * is pressed, it would set bit_array to {0, 0, 0x08, 0, ...}
+ *
+ * bit_array must be at least MAX_KEYBOARD_MATRIX_COLS bytes long.
+ */
+enum ec_error_list keyboard_get_state(uint8_t *bit_array);
+
+
+#endif /* __INCLUDE_KEYBOARD_H */
diff --git a/include/memory_commands.h b/include/memory_commands.h
new file mode 100644
index 0000000000..7967a63800
--- /dev/null
+++ b/include/memory_commands.h
@@ -0,0 +1,16 @@
+/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* Memory commands for Chrome EC */
+
+#ifndef __CROS_EC_MEMORY_COMMANDS_H
+#define __CROS_EC_MEMORY_COMMANDS_H
+
+#include "common.h"
+
+/* Initializes the module. */
+int memory_commands_init(void);
+
+#endif /* __CROS_EC_MEMORY_COMMANDS_H */