diff options
-rw-r--r-- | board/board.c | 61 | ||||
-rw-r--r-- | cros_ec/chip_stub/keyboard.c | 5 | ||||
-rw-r--r-- | cros_ec/include/ec_keyboard.h | 13 | ||||
-rw-r--r-- | cros_ec/lib/ec_keyboard.c | 45 | ||||
-rw-r--r-- | cros_ec/test/ec_keyboard_test.c | 80 | ||||
-rw-r--r-- | host_interface/i8042.h | 27 |
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. |