From c4383ca93f5d2aeb0c03e0b7ae623cf2d1b50ab0 Mon Sep 17 00:00:00 2001 From: Randall Spangler Date: Wed, 29 Jan 2014 09:40:22 -0800 Subject: Fix watchdog in keyboard scan if key outside mask pressed If a key is pressed which is not in actual_key_mask, this triggers the keyboard scan interrupt. But read_matrix() would use the key mask to decide that no *real* keys were pressed. So it would immediately drop out of scan mode back to interrupt mode. Which would again be triggered. Lather, rinse, repeat, watchdog. The fix is to use the unmasked key matrix to decide whether to stay in scan mode. This way, the keyboard task sleeps between scans, and the watchdog isn't triggered. (Note that the only way you can hit this bug in real life is to have a keyboard attached which can trigger keys not in actual_key_mask. Which is hard to do, unless you've got a new prototype keyboard with extra keys, or you've spilled lemon juice on your Chromebook...) BUG=chrome-os-partner:25333 BRANCH=rambi TEST=Zero out actual_key_mask in keyboard_scan.c. Press a key. Should not trigger a watchdog. Change-Id: I8c2fbc3e06fa12dfae5c06614814af8f04e24a8a Signed-off-by: Randall Spangler Reviewed-on: https://chromium-review.googlesource.com/184323 Reviewed-by: Dave Parker Tested-by: Dave Parker --- common/keyboard_scan.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/common/keyboard_scan.c b/common/keyboard_scan.c index e5627ba22f..8af50de209 100644 --- a/common/keyboard_scan.c +++ b/common/keyboard_scan.c @@ -213,18 +213,27 @@ static int read_matrix(uint8_t *state) /* Read the row state */ r = keyboard_raw_read_rows(); - /* Mask off keys that don't exist on the actual keyboard */ - r &= keyscan_config.actual_key_mask[c]; + /* Add in simulated keypresses */ r |= simulated_key[c]; + /* + * Keep track of what keys appear to be pressed. Even if they + * don't exist in the matrix, they'll keep triggering + * interrupts, so we can't leave scanning mode. + */ + pressed |= r; + + /* Mask off keys that don't exist on the actual keyboard */ + r &= keyscan_config.actual_key_mask[c]; + #ifdef CONFIG_KEYBOARD_TEST /* Use simulated keyscan sequence instead if testing active */ r = keyscan_seq_get_scan(c, r); #endif + /* Store the masked state */ state[c] = r; - pressed |= r; } keyboard_raw_drive_column(KEYBOARD_COLUMN_NONE); -- cgit v1.2.1