summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGerrit <chrome-bot@google.com>2012-05-23 23:07:09 -0700
committerGerrit Code Review <gerrit@gerrit.golo.chromium.org>2012-05-23 23:07:09 -0700
commit0a77eea2e45f84bd009fe467ffaa3f268a29e21b (patch)
tree0ae1e04166a5bb3bd43037ca152c5ee10bfcf03b
parente5333535f4a598b891a51274241f1baa9f67473a (diff)
parent29d25d807c18330c1426425e8c53af1067be7640 (diff)
downloadchrome-ec-0a77eea2e45f84bd009fe467ffaa3f268a29e21b.tar.gz
Merge "Keyboard scan must stop driving columns when power button is pressed."
-rw-r--r--chip/lm4/keyboard_scan.c41
-rw-r--r--chip/lm4/power_button.c7
-rw-r--r--common/i8042.c2
-rw-r--r--common/keyboard.c14
-rw-r--r--include/i8042.h2
-rw-r--r--include/keyboard.h3
-rw-r--r--include/keyboard_scan.h5
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 */