diff options
author | Gerrit <chrome-bot@google.com> | 2012-05-23 23:07:09 -0700 |
---|---|---|
committer | Gerrit Code Review <gerrit@gerrit.golo.chromium.org> | 2012-05-23 23:07:09 -0700 |
commit | 0a77eea2e45f84bd009fe467ffaa3f268a29e21b (patch) | |
tree | 0ae1e04166a5bb3bd43037ca152c5ee10bfcf03b | |
parent | e5333535f4a598b891a51274241f1baa9f67473a (diff) | |
parent | 29d25d807c18330c1426425e8c53af1067be7640 (diff) | |
download | chrome-ec-0a77eea2e45f84bd009fe467ffaa3f268a29e21b.tar.gz |
Merge "Keyboard scan must stop driving columns when power button is pressed."
-rw-r--r-- | chip/lm4/keyboard_scan.c | 41 | ||||
-rw-r--r-- | chip/lm4/power_button.c | 7 | ||||
-rw-r--r-- | common/i8042.c | 2 | ||||
-rw-r--r-- | common/keyboard.c | 14 | ||||
-rw-r--r-- | include/i8042.h | 2 | ||||
-rw-r--r-- | include/keyboard.h | 3 | ||||
-rw-r--r-- | include/keyboard_scan.h | 5 |
7 files changed, 58 insertions, 16 deletions
diff --git a/chip/lm4/keyboard_scan.c b/chip/lm4/keyboard_scan.c index bb92ad2689..2faa2a88f6 100644 --- a/chip/lm4/keyboard_scan.c +++ b/chip/lm4/keyboard_scan.c @@ -63,6 +63,8 @@ enum COLUMN_INDEX { #define KB_COLS 13 + +static int enable_scanning = 1; static uint8_t raw_state[KB_COLS]; static uint8_t raw_state_at_boot[KB_COLS]; static int recovery_key_pressed; @@ -95,6 +97,8 @@ static const uint8_t actual_key_masks[4][KB_COLS] = { static void select_column(int col) { if (col == COLUMN_ASSERT_ALL) { + if (!enable_scanning) + return; LM4_GPIO_DIR(LM4_GPIO_P) = 0xff; LM4_GPIO_DIR(LM4_GPIO_Q) |= 0x1f; LM4_GPIO_DATA(LM4_GPIO_P, 0xff) = 0; @@ -102,7 +106,11 @@ static void select_column(int col) } else { LM4_GPIO_DIR(LM4_GPIO_P) = 0; LM4_GPIO_DIR(LM4_GPIO_Q) &= ~0x1f; - if (col < 8) { + /* Return after the above TRI_STATE_ALL has be run. */ + if (!enable_scanning) + return; + + if (col >= 0 && col < 8) { LM4_GPIO_DIR(LM4_GPIO_P) |= 1 << col; LM4_GPIO_DATA(LM4_GPIO_P, 1 << col) = 0; } else if (col != COLUMN_TRI_STATE_ALL) { @@ -232,7 +240,7 @@ static int check_keys_changed(void) for (i = 0; i < 8; ++i) { uint8_t prev = (raw_state[c] >> i) & 1; uint8_t now = (r >> i) & 1; - if (prev != now) { + if (prev != now && enable_scanning) { keyboard_state_changed(i, c, now); } } @@ -360,6 +368,7 @@ void keyboard_scan_task(void) /* Enable interrupts */ task_enable_irq(KB_SCAN_ROW_IRQ); + enable_scanning = 1; while (1) { wait_for_interrupt(); @@ -367,7 +376,7 @@ void keyboard_scan_task(void) enter_polling_mode(); /* Busy polling keyboard state. */ - while (1) { + while (enable_scanning) { /* sleep for debounce. */ usleep(SCAN_LOOP_DELAY); /* Check for keys down */ @@ -381,10 +390,10 @@ void keyboard_scan_task(void) } } } - /* TODO: (crosbug.com/p/7484) A race condition here. - * If a key state is changed here (before interrupt is - * enabled), it will be lost. - */ + /* Don't continue if the power button is not released yet. */ + while (!enable_scanning) { + usleep(SCAN_LOOP_DELAY); + } } } @@ -441,3 +450,21 @@ int keyboard_get_scan(uint8_t **buffp, int max_bytes) { return -1; } + + +/* The actuall implementation is controlling the enable_scanning variable, + * then that controls whether select_column() can pull-down columns or not. + */ +void keyboard_enable_scanning(int enable) +{ + enable_scanning = enable; + if (enable) { + /* A power button press had tri-stated all columns (see the + * 'else' statement below), we need a wake-up to unlock + * the task_wait_event() loop after wait_for_interrupt(). */ + task_wake(TASK_ID_KEYSCAN); + } else { + select_column(COLUMN_TRI_STATE_ALL); + keyboard_clear_underlying_buffer(); + } +} diff --git a/chip/lm4/power_button.c b/chip/lm4/power_button.c index 66505d3e59..66fc7b7589 100644 --- a/chip/lm4/power_button.c +++ b/chip/lm4/power_button.c @@ -200,6 +200,7 @@ static void power_button_released(uint64_t tnow) tnext_state = tnow; *memmap_switches &= ~EC_SWITCH_POWER_BUTTON_PRESSED; keyboard_set_power_button(0); + keyboard_enable_scanning(1); } @@ -528,6 +529,12 @@ void power_button_interrupt(enum gpio_signal signal) case GPIO_POWER_BUTTONn: /* Reset power button debounce time */ tdebounce_pwr = get_time().val + PWRBTN_DEBOUNCE_US; + if (get_power_button_pressed()) { + /* We want to disable the matrix scan as soon as + * possible to reduce the risk of false-reboot triggered + * by those keys on the same column with ESC key. */ + keyboard_enable_scanning(0); + } break; case GPIO_PCH_BKLTEN: update_backlight(); diff --git a/common/i8042.c b/common/i8042.c index 35e1f2b094..54eb668f3c 100644 --- a/common/i8042.c +++ b/common/i8042.c @@ -46,7 +46,7 @@ static int i8042_irq_enabled = 0; /* Reset all i8042 buffer */ -void i8042_init() +void i8042_flush_buffer() { head_to_buffer = tail_to_buffer = 0; keyboard_clear_buffer(); diff --git a/common/keyboard.c b/common/keyboard.c index 2d69dba438..6b2dc48088 100644 --- a/common/keyboard.c +++ b/common/keyboard.c @@ -255,9 +255,9 @@ static void reset_rate_and_delay(void) } -static void clear_underlying_buffer(void) +void keyboard_clear_underlying_buffer(void) { - i8042_init(); + i8042_flush_buffer(); } @@ -482,25 +482,25 @@ int handle_keyboard_data(uint8_t data, uint8_t *output) case I8042_CMD_ENABLE: output[out_len++] = I8042_RET_ACK; keyboard_enable(1); - clear_underlying_buffer(); + keyboard_clear_underlying_buffer(); break; case I8042_CMD_RESET_DIS: output[out_len++] = I8042_RET_ACK; keyboard_enable(0); reset_rate_and_delay(); - clear_underlying_buffer(); + keyboard_clear_underlying_buffer(); break; case I8042_CMD_RESET_DEF: output[out_len++] = I8042_RET_ACK; reset_rate_and_delay(); - clear_underlying_buffer(); + keyboard_clear_underlying_buffer(); break; case I8042_CMD_RESET_BAT: reset_rate_and_delay(); - clear_underlying_buffer(); + keyboard_clear_underlying_buffer(); output[out_len++] = I8042_RET_ACK; output[out_len++] = I8042_RET_BAT; output[out_len++] = I8042_RET_BAT; @@ -613,7 +613,7 @@ int handle_keyboard_command(uint8_t command, uint8_t *output) } else { CPRINTF("[Unsupported cmd: 0x%02x]\n", command); reset_rate_and_delay(); - clear_underlying_buffer(); + keyboard_clear_underlying_buffer(); output[out_len++] = I8042_RET_NAK; data_port_state = STATE_NORMAL; } diff --git a/include/i8042.h b/include/i8042.h index c3d858bee1..d88e3acb1f 100644 --- a/include/i8042.h +++ b/include/i8042.h @@ -90,7 +90,7 @@ #define I8042_ENIRQ1 (1 << 0) -void i8042_init(void); +void i8042_flush_buffer(void); /* common/i8042.c implements this function, which is called by lpc.c diff --git a/include/keyboard.h b/include/keyboard.h index 78884c1053..775135f1b7 100644 --- a/include/keyboard.h +++ b/include/keyboard.h @@ -53,6 +53,9 @@ void kblog_put(char type, uint8_t byte); #define MAX_KEYBOARD_MATRIX_ROWS 8 #define MAX_KEYBOARD_MATRIX_COLS 16 +/* Clear the keyboard buffer to host. */ +void keyboard_clear_underlying_buffer(void); + /* Asks the underlayer EC lib what keys are pressed right now. * * Sets bit_array to a debounced array of which keys are currently pressed, diff --git a/include/keyboard_scan.h b/include/keyboard_scan.h index 684885c82a..67e09e0312 100644 --- a/include/keyboard_scan.h +++ b/include/keyboard_scan.h @@ -19,4 +19,9 @@ int keyboard_scan_recovery_pressed(void); /* clear any saved keyboard state (empty FIFO, etc) */ void keyboard_clear_state(void); + +/* Enables/disables keyboard matrix scan. */ +void keyboard_enable_scanning(int enable); + + #endif /* __CROS_KEYBOARD_SCAN_H */ |