summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLouis Yung-Chieh Lo <yjlou@chromium.org>2011-10-29 00:15:56 +0800
committerLouis Yung-Chieh Lo <yjlou@chromium.org>2011-10-29 00:15:56 +0800
commitfd5d4b6e9e0a6833cd8685f068599117f5ab7ea8 (patch)
treeeb72b7aa09daa87df70bc322ce7e3ca2e746a893
parent79a661d00c31937bff2018afef1ebb41c8b5ec14 (diff)
downloadchrome-ec-fd5d4b6e9e0a6833cd8685f068599117f5ab7ea8.tar.gz
Implement scancode set 2.
Also add the framework to handle i8042 command from host. BUG=None TEST=cd cros_ec/test; make && make runtests Change-Id: I47c5dfec47fb0e439be923f08dcd2cbc873baba6
-rw-r--r--board/board.c61
-rw-r--r--cros_ec/chip_stub/keyboard.c5
-rw-r--r--cros_ec/include/ec_keyboard.h13
-rw-r--r--cros_ec/lib/ec_keyboard.c45
-rw-r--r--cros_ec/test/ec_keyboard_test.c80
-rw-r--r--host_interface/i8042.h27
6 files changed, 208 insertions, 23 deletions
diff --git a/board/board.c b/board/board.c
index 16b10b3a42..2e5e9cc49c 100644
--- a/board/board.c
+++ b/board/board.c
@@ -17,12 +17,33 @@ static uint8_t maxtri_table[CROS_ROW_NUM][CROS_COL_NUM] = {
/* FIXME: waiting for approval to open-source this table. */
};
+static uint16_t scancode_set2[128] = {
+ /* 0 */ 0x0000, 0x000E, 0x0016, 0x001E, 0x0026, 0x0025, 0x002E, 0x0036,
+ /* 8 */ 0x003d, 0x003e, 0x0046, 0x0045, 0x004E, 0x0055, 0x0000, 0x0066,
+ /* 16 */ 0x000d, 0x0015, 0x001d, 0x0024, 0x002d, 0x002c, 0x0035, 0x003c,
+ /* 24 */ 0x0043, 0x0044, 0x004D, 0x0054, 0x005b, 0x005d, 0xE01F, 0x001c,
+ /* 32 */ 0x001b, 0x0023, 0x002b, 0x0034, 0x0033, 0x003B, 0x0042, 0x004B,
+ /* 40 */ 0x004C, 0x0052, 0x0000, 0x005A, 0x0012, 0x0000, 0x001A, 0x0022,
+ /* 48 */ 0x0021, 0x002A, 0x0032, 0x0031, 0x003A, 0x0041, 0x0049, 0x004A,
+ /* 56 */ 0x0000, 0x0059, 0x0014, 0xE037, 0x0011, 0x0029, 0xE011, 0x0000,
+ /* 64 */ 0xE014, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* 72 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xe06B,
+ /* 80 */ 0x0000, 0x0000, 0x0000, 0xE075, 0xE072, 0x0000, 0x0000, 0x0000,
+ /* 88 */ 0x0000, 0xE074, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* 96 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ /* 104 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0076, 0x0000,
+ /* 112 */ 0x0005, 0x0006, 0x0004, 0x000c, 0x0003, 0x000b, 0x0083, 0x0009,
+ /* 120 */ 0x0000, 0x000a, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+};
+
static EcError MatrixCallback(
int8_t row, int8_t col, int8_t pressed,
- uint8_t *scan_code, int32_t* len) {
+ enum EcScancodeSet code_set, uint8_t *scan_code, int32_t* len) {
- uint8_t make_code;
+ int key_index; /* the index og scancode_set */
+ uint16_t make_code;
+ EC_ASSERT(code_set == EC_SCANCODE_SET_2); /* TODO: support other sets? */
EC_ASSERT(scan_code);
EC_ASSERT(len);
@@ -31,16 +52,36 @@ static EcError MatrixCallback(
return EC_ERROR_INVALID_PARAMETER;
}
- make_code = maxtri_table[row][col];
- make_code = row * 13 + col; /* FIXME: remove this after we can open-source
- * the matrix table. */
+ *len = 0;
+
+#if 1 /* FIXME: remove #if after we can opensource the matrix table. */
+ /* fake */
+ maxtri_table[0][0] = scancode_set2[0]; // FIXME: to make compiler happy
+ make_code = scancode_set2[key_index = row * 8 + col];
+#else
+ key_index = maxtri_table[row][col];
+ EC_ASSERT(key_index < (sizeof(scancode_set2) / sizeof(scancode_set2[0])));
+ make_code = scancode_set2[key_index];
+#endif
- if (pressed) {
- *scan_code = make_code;
- *len = 1;
+ /* Output the make code (from table) */
+ EC_ASSERT(make_code); /* there must be a make code mapping to a key */
+ if (make_code >= 0x0100) {
+ *len += 2;
+ scan_code[0] = make_code >> 8;
+ scan_code[1] = make_code & 0xff;
} else {
- *scan_code = make_code | 0x80;
- *len = 1;
+ *len += 1;
+ scan_code[0] = make_code & 0xff;
+ }
+
+ /* insert the break byte, move back the last byte and insert a 0xf0 byte
+ * before that. */
+ if (!pressed) {
+ EC_ASSERT(*len >= 1);
+ scan_code[*len] = scan_code[*len - 1];
+ scan_code[*len - 1] = 0xF0;
+ *len += 1;
}
return EC_SUCCESS;
diff --git a/cros_ec/chip_stub/keyboard.c b/cros_ec/chip_stub/keyboard.c
index 6f59d11bd5..6586202290 100644
--- a/cros_ec/chip_stub/keyboard.c
+++ b/cros_ec/chip_stub/keyboard.c
@@ -8,7 +8,9 @@
#include <stdint.h>
#include "chip_interface/keyboard.h"
+
static EcKeyboardCallback core_keyboard_callback;
+/* each byte presents one column in 8 rows. 1 = pressed. */
static uint8_t virtual_matrix[MAX_KEYBOARD_MATRIX_COLS];
EcError EcKeyboardRegisterCallback(EcKeyboardCallback cb) {
@@ -17,9 +19,10 @@ EcError EcKeyboardRegisterCallback(EcKeyboardCallback cb) {
}
+/* Returns bit array of every key press stage. */
EcError EcKeyboardGetState(uint8_t *bit_array) {
/* TODO: implement later */
- return EC_SUCCESS;
+ return EC_ERROR_UNIMPLEMENTED;
}
diff --git a/cros_ec/include/ec_keyboard.h b/cros_ec/include/ec_keyboard.h
index 2c8290fa0b..9f552f5ac1 100644
--- a/cros_ec/include/ec_keyboard.h
+++ b/cros_ec/include/ec_keyboard.h
@@ -10,6 +10,16 @@
#include "cros_ec/include/ec_common.h"
+
+enum EcScancodeSet {
+ EC_SCANCODE_GET_SET = 0,
+ EC_SCANCODE_SET_1,
+ EC_SCANCODE_SET_2,
+ EC_SCANCODE_SET_3,
+ EC_SCANCODE_MAX = EC_SCANCODE_SET_3,
+};
+
+
/* The initialize code of keyboard lib. Called by core main. */
EcError EcKeyboardInit();
@@ -22,7 +32,7 @@ EcError EcKeyboardInit();
*/
typedef EcError (*EcKeyboardMatrixCallback)(
int8_t row, int8_t col, int8_t pressed,
- uint8_t *scan_code, int32_t* len);
+ enum EcScancodeSet code_set, uint8_t *scan_code, int32_t* len);
EcError EcKeyboardMatrixRegisterCallback(
int8_t row_num, int8_t col_num,
@@ -31,4 +41,5 @@ EcError EcKeyboardMatrixRegisterCallback(
#define MAX_SCAN_CODE_LEN 4
+
#endif /* __CROS_INCLUDE_EC_KEYBOARD_H */
diff --git a/cros_ec/lib/ec_keyboard.c b/cros_ec/lib/ec_keyboard.c
index 4e4b9d91e4..7a5c43e0ef 100644
--- a/cros_ec/lib/ec_keyboard.c
+++ b/cros_ec/lib/ec_keyboard.c
@@ -12,6 +12,7 @@
static EcKeyboardMatrixCallback matrix_callback;
+static enum EcScancodeSet scancode_set = EC_SCANCODE_SET_2;
static void KeyboardStateChanged(int row, int col, int is_pressed) {
uint8_t scan_code[MAX_SCAN_CODE_LEN];
@@ -23,7 +24,7 @@ static void KeyboardStateChanged(int row, int col, int is_pressed) {
EC_ASSERT(matrix_callback);
- ret = matrix_callback(row, col, is_pressed, scan_code, &len);
+ ret = matrix_callback(row, col, is_pressed, scancode_set, scan_code, &len);
if (ret == EC_SUCCESS) {
EC_ASSERT(len > 0);
@@ -36,6 +37,45 @@ static void KeyboardStateChanged(int row, int col, int is_pressed) {
}
+static int HandleHostCommand(
+ uint8_t command,
+ uint8_t data,
+ uint8_t *output) {
+ int out_len = 0;
+
+ switch (command) {
+ case EC_I8042_CMD_GSCANSET: /* also EC_I8042_CMD_SSCANSET */
+ if (data == EC_SCANCODE_GET_SET) {
+ output[out_len++] = scancode_set;
+ } else if (data == EC_SCANCODE_SET_2) {
+ scancode_set = data;
+ } else {
+ output[out_len++] = EC_I8042_RET_ERR;
+ }
+ break;
+
+ case EC_I8042_CMD_SETREP:
+ case EC_I8042_CMD_ENABLE:
+ case EC_I8042_CMD_RESET_DIS:
+ case EC_I8042_CMD_RESET_DEF:
+ case EC_I8042_CMD_SETALL_MB:
+ case EC_I8042_CMD_SETALL_MBR:
+ case EC_I8042_CMD_RESET_BAT:
+ case EC_I8042_CMD_RESEND:
+ case EC_I8042_CMD_EX_ENABLE:
+ case EC_I8042_CMD_EX_SETLEDS:
+ case EC_I8042_CMD_OK_GETID:
+ case EC_I8042_CMD_GETID:
+ case EC_I8042_CMD_SETLEDS:
+ default:
+ output[out_len++] = EC_I8042_RET_ERR;
+ break;
+ }
+
+ return out_len;
+}
+
+
EcError EcKeyboardMatrixRegisterCallback(
int8_t row_num, int8_t col_num,
EcKeyboardMatrixCallback callback) {
@@ -52,5 +92,8 @@ EcError EcKeyboardInit() {
ret = EcKeyboardRegisterCallback(KeyboardStateChanged);
if (ret != EC_SUCCESS) return ret;
+ ret = EcI8042RegisterCallback(HandleHostCommand);
+ if (ret != EC_SUCCESS) return ret;
+
return EC_SUCCESS;
}
diff --git a/cros_ec/test/ec_keyboard_test.c b/cros_ec/test/ec_keyboard_test.c
index a425c0781a..b84e179ece 100644
--- a/cros_ec/test/ec_keyboard_test.c
+++ b/cros_ec/test/ec_keyboard_test.c
@@ -7,8 +7,10 @@
#include "cros_ec/include/ec_common.h"
#include "chip_interface/ec_uart.h"
#include "cros_ec/include/core.h"
+#include "cros_ec/include/ec_keyboard.h"
#include "cros_ec/chip_stub/include/host.h"
#include "cros_ec/chip_stub/include/keyboard.h"
+#include "host_interface/i8042.h"
#define RUN_TEST(func) do { \
int ret; \
@@ -20,42 +22,100 @@
} while (0)
-EcError testKeyMade() {
+EcError TestKeyMade() {
uint8_t buf;
+ /* Fake a key press */
SimulateKeyStateChange(2, 3, 1);
EC_ASSERT(EC_SUCCESS == PullI8042ScanCode(&buf));
- EC_ASSERT(buf == 2 * 13 + 3);
+ EC_ASSERT(buf == 0x24);
+ EC_ASSERT(EC_ERROR_BUFFER_EMPTY == PullI8042ScanCode(&buf));
/* The duplicate press event will be ignored. */
SimulateKeyStateChange(2, 3, 1);
EC_ASSERT(EC_ERROR_BUFFER_EMPTY == PullI8042ScanCode(&buf));
+ /* Test 2-byte scan code */
+ SimulateKeyStateChange(3, 6, 1);
+ EC_ASSERT(EC_SUCCESS == PullI8042ScanCode(&buf));
+ EC_ASSERT(buf == 0xE0);
+ EC_ASSERT(EC_SUCCESS == PullI8042ScanCode(&buf));
+ EC_ASSERT(buf == 0x1f);
+ EC_ASSERT(EC_ERROR_BUFFER_EMPTY == PullI8042ScanCode(&buf));
+
return EC_SUCCESS;
}
-EcError testKeyReleased() {
+EcError TestKeyReleased() {
uint8_t buf;
/* The key is not pressed yet. A release event doesn't send out a code. */
- SimulateKeyStateChange(7, 12, 0);
+ SimulateKeyStateChange(0, 1, 0);
EC_ASSERT(EC_ERROR_BUFFER_EMPTY == PullI8042ScanCode(&buf));
/* Press and release it. Expect a release code. */
- SimulateKeyStateChange(7, 12, 1);
- SimulateKeyStateChange(7, 12, 0);
+ SimulateKeyStateChange(0, 1, 1);
+ EC_ASSERT(EC_SUCCESS == PullI8042ScanCode(&buf));
+ EC_ASSERT(buf == 0x0E);
+ EC_ASSERT(EC_ERROR_BUFFER_EMPTY == PullI8042ScanCode(&buf));
+ SimulateKeyStateChange(0, 1, 0); /* release */
+ EC_ASSERT(EC_SUCCESS == PullI8042ScanCode(&buf));
+ EC_ASSERT(buf == 0xF0);
+ EC_ASSERT(EC_SUCCESS == PullI8042ScanCode(&buf));
+ EC_ASSERT(buf == 0x0E);
+ EC_ASSERT(EC_ERROR_BUFFER_EMPTY == PullI8042ScanCode(&buf));
+
+ /* Test 3-byte break code */
+ SimulateKeyStateChange(7, 3, 1);
+ EC_ASSERT(EC_SUCCESS == PullI8042ScanCode(&buf));
+ EC_ASSERT(buf == 0xE0);
EC_ASSERT(EC_SUCCESS == PullI8042ScanCode(&buf));
- EC_ASSERT(buf == 7 * 13 + 12);
+ EC_ASSERT(buf == 0x37);
+ EC_ASSERT(EC_ERROR_BUFFER_EMPTY == PullI8042ScanCode(&buf));
+ SimulateKeyStateChange(7, 3, 0); /* release */
+ EC_ASSERT(EC_SUCCESS == PullI8042ScanCode(&buf));
+ EC_ASSERT(buf == 0xE0);
+ EC_ASSERT(EC_SUCCESS == PullI8042ScanCode(&buf));
+ EC_ASSERT(buf == 0xF0);
EC_ASSERT(EC_SUCCESS == PullI8042ScanCode(&buf));
- EC_ASSERT(buf == 7 * 13 + 12 + 0x80);
+ EC_ASSERT(buf == 0x37);
+ EC_ASSERT(EC_ERROR_BUFFER_EMPTY == PullI8042ScanCode(&buf));
return EC_SUCCESS;
}
+EcError TestScancodeSet() {
+ int len;
+ uint8_t output[MAX_I8042_OUTPUT_LEN];
+
+ /* Get Scancode Set */
+ len = SimulateI8042Command(EC_I8042_CMD_GSCANSET, EC_SCANCODE_GET_SET,
+ output);
+ EC_ASSERT(len == 1);
+ EC_ASSERT(output[0] == EC_SCANCODE_SET_2);
+
+ /* Set as set 1. Expect failed */
+ len = SimulateI8042Command(EC_I8042_CMD_GSCANSET, EC_SCANCODE_SET_1, output);
+ EC_ASSERT(len == 1);
+ EC_ASSERT(output[0] == EC_I8042_RET_ERR);
+
+ /* Set as set 2. Expect success */
+ len = SimulateI8042Command(EC_I8042_CMD_GSCANSET, EC_SCANCODE_SET_2, output);
+ EC_ASSERT(len == 0);
+
+ /* Set as set 3. Expect failed */
+ len = SimulateI8042Command(EC_I8042_CMD_GSCANSET, EC_SCANCODE_SET_3, output);
+ EC_ASSERT(len == 1);
+ EC_ASSERT(output[0] == EC_I8042_RET_ERR);
+
+ return EC_SUCCESS;
+}
+
int run_test_cases() {
- RUN_TEST(testKeyMade);
- RUN_TEST(testKeyReleased);
+ RUN_TEST(TestKeyMade);
+ RUN_TEST(TestKeyReleased);
+ RUN_TEST(TestScancodeSet);
return EC_SUCCESS;
}
diff --git a/host_interface/i8042.h b/host_interface/i8042.h
index a3b2475785..3c3684dc22 100644
--- a/host_interface/i8042.h
+++ b/host_interface/i8042.h
@@ -15,6 +15,33 @@
#include "cros_ec/include/ec_common.h"
+/* Keyboard command definition. Modified from Linux kernel atkbd.c file. */
+#define EC_I8042_CMD_SETLEDS 0xed
+#define EC_I8042_CMD_GSCANSET 0xf0
+#define EC_I8042_CMD_SSCANSET 0xf0
+#define EC_I8042_CMD_GETID 0xf2
+#define EC_I8042_CMD_SETREP 0xf3
+#define EC_I8042_CMD_ENABLE 0xf4
+#define EC_I8042_CMD_RESET_DIS 0xf5
+#define EC_I8042_CMD_RESET_DEF 0xf6
+#define EC_I8042_CMD_SETALL_MB 0xf8
+#define EC_I8042_CMD_SETALL_MBR 0xfa
+#define EC_I8042_CMD_RESET_BAT 0xff
+#define EC_I8042_CMD_RESEND 0xfe
+#define EC_I8042_CMD_EX_ENABLE 0xea
+#define EC_I8042_CMD_EX_SETLEDS 0xeb
+#define EC_I8042_CMD_OK_GETID 0xe8
+
+#define EC_I8042_RET_ACK 0xfa
+#define EC_I8042_RET_NAK 0xfe
+#define EC_I8042_RET_BAT 0xaa
+#define EC_I8042_RET_EMUL0 0xe0
+#define EC_I8042_RET_EMUL1 0xe1
+#define EC_I8042_RET_RELEASE 0xf0
+#define EC_I8042_RET_HANJA 0xf1
+#define EC_I8042_RET_HANGEUL 0xf2
+#define EC_I8042_RET_ERR 0xff
+
/*
* Register the i8042 callback to EC lib.