diff options
-rw-r--r-- | common/keyboard_scan.c | 64 | ||||
-rw-r--r-- | test/kb_scan.c | 8 |
2 files changed, 64 insertions, 8 deletions
diff --git a/common/keyboard_scan.c b/common/keyboard_scan.c index d1e90c72c7..a22c43b7c7 100644 --- a/common/keyboard_scan.c +++ b/common/keyboard_scan.c @@ -28,6 +28,9 @@ #define SCAN_TIME_COUNT 32 /* Number of last scan times to track */ +/* If we're waiting for a scan to happen, we'll give it this long */ +#define SCAN_TASK_TIMEOUT_US (100 * MSEC) + #ifndef CONFIG_KEYBOARD_POST_SCAN_CLOCKS /* * Default delay in clocks; this was experimentally determined to be long @@ -87,6 +90,9 @@ static int print_state_changes; static int enable_scanning = 1; /* Must init to 1 for scanning at boot */ +/* Constantly incrementing counter of the number of times we polled */ +static volatile int kbd_polls; + static int is_scanning_enabled(void) { #ifdef CONFIG_LID_SWITCH @@ -119,6 +125,30 @@ static void print_state(const uint8_t *state, const char *msg) } /** + * Ensure that the keyboard has been scanned. + * + * Makes sure that we've fully gone through the keyboard scanning loop at + * least once. + */ +static void ensure_keyboard_scanned(int old_polls) +{ + uint64_t start_time; + + start_time = get_time().val; + + /* + * Ensure we see the poll task run. + * + * Note that the poll task is higher priority than ours so we know that + * while we're running it's not partway through a poll. That means that + * if kbd_polls changes we've gone through a whole cycle. + */ + while ((kbd_polls == old_polls) && + (get_time().val - start_time < SCAN_TASK_TIMEOUT_US)) + usleep(keyscan_config.scan_period_us); +} + +/** * Simulate a keypress. * * @param row Row of key @@ -127,15 +157,29 @@ static void print_state(const uint8_t *state, const char *msg) */ static void simulate_key(int row, int col, int pressed) { + int old_polls; + if ((simulated_key[col] & (1 << row)) == ((pressed ? 1 : 0) << row)) return; /* No change */ simulated_key[col] ^= (1 << row); + /* Keep track of polls now that we've got keys simulated */ + old_polls = kbd_polls; + print_state(simulated_key, "simulated "); /* Wake the task to handle changes in simulated keys */ task_wake(TASK_ID_KEYSCAN); + + /* + * Make sure that the keyboard task sees the key for long enough. + * That means it needs to have run and for enough time. + */ + ensure_keyboard_scanned(old_polls); + usleep(pressed ? + keyscan_config.debounce_down_us : keyscan_config.debounce_up_us); + ensure_keyboard_scanned(kbd_polls); } /** @@ -387,6 +431,8 @@ static int check_keys_changed(uint8_t *state) #endif } + kbd_polls++; + return any_pressed; } @@ -647,7 +693,7 @@ static int command_keyboard_press(int argc, char **argv) ccprintf("\t%d %d\n", i, j); } - } else if (argc == 4) { + } else if (argc == 3 || argc == 4) { int r, c, p; char *e; @@ -659,16 +705,22 @@ static int command_keyboard_press(int argc, char **argv) if (*e || r < 0 || r >= KEYBOARD_ROWS) return EC_ERROR_PARAM2; - p = strtoi(argv[3], &e, 0); - if (*e || p < 0 || p > 1) - return EC_ERROR_PARAM3; + if (argc == 3) { + /* Simulate a press and release */ + simulate_key(r, c, 1); + simulate_key(r, c, 0); + } else { + p = strtoi(argv[3], &e, 0); + if (*e || p < 0 || p > 1) + return EC_ERROR_PARAM3; - simulate_key(r, c, p); + simulate_key(r, c, p); + } } return EC_SUCCESS; } DECLARE_CONSOLE_COMMAND(kbpress, command_keyboard_press, - "[col] [row] [0 | 1]", + "[col row [0 | 1]]", "Simulate keypress", NULL); diff --git a/test/kb_scan.c b/test/kb_scan.c index a273a20466..e0e73d17f5 100644 --- a/test/kb_scan.c +++ b/test/kb_scan.c @@ -253,10 +253,14 @@ static int debounce_test(void) static int simulate_key_test(void) { + int old_count; + + old_count = fifo_add_count; host_command_simulate(1, 1, 1); - TEST_ASSERT(expect_keychange() == EC_SUCCESS); + TEST_ASSERT(fifo_add_count > old_count); + old_count = fifo_add_count; host_command_simulate(1, 1, 0); - TEST_ASSERT(expect_keychange() == EC_SUCCESS); + TEST_ASSERT(fifo_add_count > old_count); return EC_SUCCESS; } |