Merge "Keyboard scan must stop driving columns when power button is pressed."

This commit is contained in:
Gerrit
2012-05-23 23:07:09 -07:00
committed by Gerrit Code Review
7 changed files with 58 additions and 16 deletions

View File

@@ -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();
}
}

View File

@@ -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();

View File

@@ -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();

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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,

View File

@@ -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 */