diff options
author | Furquan Shaikh <furquan@chromium.org> | 2016-11-03 23:39:19 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2016-11-08 20:30:07 -0800 |
commit | 2fc7ba9df19d941fcd7b858d5ea6f3eb2b2398bd (patch) | |
tree | 01eb2aa25245695df6d37aa17c286d719e10fbfd /common/keyboard_scan.c | |
parent | bf4e1db093d7051491001e59195d30a915785066 (diff) | |
download | chrome-ec-2fc7ba9df19d941fcd7b858d5ea6f3eb2b2398bd.tar.gz |
common: Add new recovery mode button combination
This adds new key combination (Left_Shift+Esc+Refresh+Power) that triggers
recovery mode by setting a new host event
EC_HOST_EVENT_KEYBOARD_RECOVERY_HW_REINIT. This host event can be used
whenever user wants to request entry into recovery mode by
reinitializing all the hardware state (e.g. memory retraining).
BUG=chrome-os-partner:56643,chrome-os-partner:59352
BRANCH=None
TEST=Verified that device retrains memory in recovery mode
with (Left_Shift+Esc+Refresh+Power) on reef.
Change-Id: I2e08997acfd9e22270b8ce7a5b589cd5630645f8
Signed-off-by: Furquan Shaikh <furquan@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/407827
Reviewed-by: Randall Spangler <rspangler@chromium.org>
Diffstat (limited to 'common/keyboard_scan.c')
-rw-r--r-- | common/keyboard_scan.c | 81 |
1 files changed, 45 insertions, 36 deletions
diff --git a/common/keyboard_scan.c b/common/keyboard_scan.c index a364917b33..e7f42d47a7 100644 --- a/common/keyboard_scan.c +++ b/common/keyboard_scan.c @@ -70,12 +70,13 @@ struct boot_key_entry { uint8_t mask_index; uint8_t mask_value; }; + static const struct boot_key_entry boot_key_list[] = { - {0, 0x00}, /* (none) */ {KEYBOARD_COL_ESC, KEYBOARD_MASK_ESC}, /* Esc */ {KEYBOARD_COL_DOWN, KEYBOARD_MASK_DOWN}, /* Down-arrow */ + {KEYBOARD_COL_LEFT_SHIFT, KEYBOARD_MASK_LEFT_SHIFT}, /* Left-Shift */ }; -static enum boot_key boot_key_value = BOOT_KEY_OTHER; +static uint32_t boot_key_value = BOOT_KEY_NONE; /* Debounced key matrix */ static uint8_t __bss_slow debounced_state[KEYBOARD_COLS]; @@ -516,21 +517,18 @@ static int check_keys_changed(uint8_t *state) } /* - * Return non-zero if the specified key is pressed, with at most the keys used + * Returns mask of the boot keys that are pressed, with at most the keys used * for keyboard-controlled reset also pressed. */ -static int check_key(const uint8_t *state, int index, int mask) +static uint32_t check_key_list(const uint8_t *state) { - uint8_t allowed_mask[KEYBOARD_COLS] = {0}; + uint8_t curr_state[KEYBOARD_COLS]; int c; + uint32_t boot_key_mask = BOOT_KEY_NONE; + const struct boot_key_entry *k; - /* Check for the key */ - if (mask && !(state[index] & mask)) - return 0; - - /* Check for other allowed keys */ - allowed_mask[index] |= mask; - allowed_mask[KEYBOARD_COL_REFRESH] |= KEYBOARD_MASK_REFRESH; + /* Make copy of current debounced state. */ + memcpy(curr_state, state, sizeof(curr_state)); #ifdef CONFIG_KEYBOARD_PWRBTN_ASSERTS_KSI2 /* @@ -539,19 +537,31 @@ static int check_key(const uint8_t *state, int index, int mask) */ for (c = 0; c < KEYBOARD_COLS; c++) if ((keyscan_config.actual_key_mask[c] & KEYBOARD_MASK_KSI2) && - !(state[c] & KEYBOARD_MASK_KSI2)) + !(curr_state[c] & KEYBOARD_MASK_KSI2)) break; if (c == KEYBOARD_COLS) for (c = 0; c < KEYBOARD_COLS; c++) - allowed_mask[c] |= KEYBOARD_MASK_KSI2; + curr_state[c] &= ~KEYBOARD_MASK_KSI2; #endif + /* Update mask with all boot keys that were pressed. */ + k = boot_key_list; + for (c = 0; c < ARRAY_SIZE(boot_key_list); c++, k++) { + if (curr_state[k->mask_index] & k->mask_value) { + boot_key_mask |= (1 << c); + curr_state[k->mask_index] &= ~k->mask_value; + } + } + + /* If any other key was pressed, ignore all boot keys. */ for (c = 0; c < KEYBOARD_COLS; c++) { - if (state[c] & ~allowed_mask[c]) - return 0; /* Disallowed key pressed */ + if (curr_state[c]) + return BOOT_KEY_NONE; } - return 1; + + CPRINTS("KB boot key mask %x", boot_key_mask); + return boot_key_mask; } /** @@ -559,37 +569,26 @@ static int check_key(const uint8_t *state, int index, int mask) * * @param state Keyboard state at boot. * - * @return the key which is down, or BOOT_KEY_OTHER if an unrecognized + * @return the key which is down, or BOOT_KEY_NONE if an unrecognized * key combination is down or this isn't the right type of boot to look at * boot keys. */ -static enum boot_key check_boot_key(const uint8_t *state) +static uint32_t check_boot_key(const uint8_t *state) { - const struct boot_key_entry *k = boot_key_list; - int i; - /* * If we jumped to this image, ignore boot keys. This prevents * re-triggering events in RW firmware that were already processed by * RO firmware. */ if (system_jumped_to_this_image()) - return BOOT_KEY_OTHER; + return BOOT_KEY_NONE; /* If reset was not caused by reset pin, refresh must be held down */ if (!(system_get_reset_flags() & RESET_FLAG_RESET_PIN) && !(state[KEYBOARD_COL_REFRESH] & KEYBOARD_MASK_REFRESH)) - return BOOT_KEY_OTHER; + return BOOT_KEY_NONE; - /* Check what single key is down */ - for (i = 0; i < ARRAY_SIZE(boot_key_list); i++, k++) { - if (check_key(state, k->mask_index, k->mask_value)) { - CPRINTS("KB boot key %d", i); - return i; - } - } - - return BOOT_KEY_OTHER; + return check_key_list(state); } static void keyboard_freq_change(void) @@ -607,7 +606,7 @@ struct keyboard_scan_config *keyboard_scan_get_config(void) return &keyscan_config; } -enum boot_key keyboard_scan_get_boot_key(void) +uint32_t keyboard_scan_get_boot_keys(void) { return boot_key_value; } @@ -632,9 +631,19 @@ void keyboard_scan_init(void) /* Check for keys held down at boot */ boot_key_value = check_boot_key(debounced_state); - /* Trigger event if recovery key was pressed */ - if (boot_key_value == BOOT_KEY_ESC) + /* + * If any key other than Esc or Left_Shift was pressed, do not trigger + * recovery. + */ + if (boot_key_value & ~(BOOT_KEY_ESC | BOOT_KEY_LEFT_SHIFT)) + return; + + if (boot_key_value & BOOT_KEY_ESC) { host_set_single_event(EC_HOST_EVENT_KEYBOARD_RECOVERY); + if (boot_key_value & BOOT_KEY_LEFT_SHIFT) + host_set_single_event( + EC_HOST_EVENT_KEYBOARD_RECOVERY_HW_REINIT); + } } void keyboard_scan_task(void) |