diff options
Diffstat (limited to 'common/keyboard_scan.c')
-rw-r--r-- | common/keyboard_scan.c | 49 |
1 files changed, 39 insertions, 10 deletions
diff --git a/common/keyboard_scan.c b/common/keyboard_scan.c index 3e7e1c1d87..a1e17bc61d 100644 --- a/common/keyboard_scan.c +++ b/common/keyboard_scan.c @@ -496,6 +496,16 @@ static int has_ghosting(const uint8_t *state) return 0; } +/* Inform keyboard module if scanning is enabled */ +static void key_state_changed(int row, int col, uint8_t state) +{ + if (!keyboard_scan_is_enabled()) + return; + + /* No-op for protocols that require full keyboard matrix (e.g. MKBP). */ + keyboard_state_changed(row, col, !!(state & BIT(row))); +} + /** * Update keyboard state using low-level interface to read keyboard. * @@ -525,7 +535,7 @@ static int check_keys_changed(uint8_t *state) /* Check for changes between previous scan and this one */ for (c = 0; c < keyboard_cols; c++) { - int diff; + int diff = new_state[c] ^ state[c]; /* Clear debouncing flag, if sufficient time has elapsed. */ for (i = 0; i < KEYBOARD_ROWS && debouncing[c]; i++) { @@ -536,6 +546,20 @@ static int check_keys_changed(uint8_t *state) keyscan_config.debounce_up_us)) continue; /* Not done debouncing */ debouncing[c] &= ~BIT(i); + + if (!IS_ENABLED(CONFIG_KEYBOARD_STRICT_DEBOUNCE)) + continue; + if (!(diff & BIT(i))) + /* Debounced but no difference. */ + continue; + any_change = 1; + key_state_changed(i, c, new_state[c]); + /* + * This makes state[c] == new_state[c] for row i. + * Thus, when diff is calculated below, it won't + * be asserted (for row i). + */ + state[c] ^= diff & BIT(i); } /* Recognize change in state, unless debounce in effect. */ @@ -546,15 +570,10 @@ static int check_keys_changed(uint8_t *state) if (!(diff & BIT(i))) continue; scan_edge_index[c][i] = scan_time_index; - any_change = 1; - /* Inform keyboard module if scanning is enabled */ - if (keyboard_scan_is_enabled()) { - /* This is no-op for protocols that require a - * full keyboard matrix (e.g., MKBP). - */ - keyboard_state_changed( - i, c, !!(new_state[c] & BIT(i))); + if (!IS_ENABLED(CONFIG_KEYBOARD_STRICT_DEBOUNCE)) { + any_change = 1; + key_state_changed(i, c, new_state[c]); } } @@ -565,7 +584,8 @@ static int check_keys_changed(uint8_t *state) * (up or down), the state bits are only updated if the * edge was not suppressed due to debouncing. */ - state[c] ^= diff; + if (!IS_ENABLED(CONFIG_KEYBOARD_STRICT_DEBOUNCE)) + state[c] ^= diff; } if (any_change) { @@ -723,6 +743,15 @@ const uint8_t *keyboard_scan_get_state(void) void keyboard_scan_init(void) { + if (IS_ENABLED(CONFIG_KEYBOARD_STRICT_DEBOUNCE) && + keyscan_config.debounce_down_us != keyscan_config.debounce_up_us) { + /* + * Strict debouncer is prone to keypress reordering if debounce + * durations for down and up are not equal. crbug.com/547131 + */ + CPRINTS("KB WARN: Debounce durations not equal"); + } + /* Configure refresh key matrix */ keyboard_mask_refresh = KEYBOARD_ROW_TO_MASK( board_keyboard_row_refresh()); |