diff options
author | Randall Spangler <rspangler@chromium.org> | 2013-03-28 12:42:44 -0700 |
---|---|---|
committer | ChromeBot <chrome-bot@google.com> | 2013-03-29 11:40:35 -0700 |
commit | 19ff62cbb05eb0f8bb6ef1707bc208f11ea22589 (patch) | |
tree | 914014cd6a31ca50fecacae615c76407ff4a6a0e | |
parent | 95a3a4107ae9c9013dbf3fb51ca3e98346cb82bb (diff) | |
download | chrome-ec-19ff62cbb05eb0f8bb6ef1707bc208f11ea22589.tar.gz |
Convert typematic task from countdown to deadline-based
This is in preparation for merging the typematic and i8042cmd tasks.
It also reduces the overhead of the typematic task during key-repeat;
previously, it woke up every millisecond to tick down.
BUG=chrome-os-partner:18360
BRANCH=none
TEST=boot link and hold a key down; see it repeat as expected
Change-Id: If6aee44ce7c746c8c1e68ed5cffced59fc575e4b
Signed-off-by: Randall Spangler <rspangler@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/46806
Reviewed-by: Bill Richardson <wfrichar@chromium.org>
-rw-r--r-- | common/keyboard_8042.c | 108 |
1 files changed, 56 insertions, 52 deletions
diff --git a/common/keyboard_8042.c b/common/keyboard_8042.c index 66de33f4a2..48bc49d4c8 100644 --- a/common/keyboard_8042.c +++ b/common/keyboard_8042.c @@ -123,16 +123,13 @@ static enum scancode_set_list scancode_set = SCANCODE_SET_2; * the inter-char delay = (2 ** B) * (D + 8) / 240 (sec) * Default: 500ms delay, 10.9 chars/sec. */ -#define DEFAULT_TYPEMATIC_VALUE ((1 << 5) || (1 << 3) || (3 << 0)) -#define DEFAULT_FIRST_DELAY 500 -#define DEFAULT_INTER_DELAY 91 -#define TYPEMATIC_DELAY_UNIT MSEC -static uint8_t typematic_value_from_host = DEFAULT_TYPEMATIC_VALUE; -static int refill_first_delay = DEFAULT_FIRST_DELAY; /* unit: ms */ -static int refill_inter_delay = DEFAULT_INTER_DELAY; /* unit: ms */ -static int typematic_delay; /* unit: us */ +#define DEFAULT_TYPEMATIC_VALUE ((1 << 5) | (1 << 3) | (3 << 0)) +static uint8_t typematic_value_from_host; +static int typematic_first_delay; +static int typematic_inter_delay; static int typematic_len; /* length of typematic_scan_code */ static uint8_t typematic_scan_code[MAX_SCAN_CODE_LEN]; +static timestamp_t typematic_deadline; #define KB_SYSJUMP_TAG 0x4b42 /* "KB" */ #define KB_HOOK_VERSION 1 @@ -222,17 +219,6 @@ static void kblog_put(char type, uint8_t byte) /*****************************************************************************/ -/** - * Flush and reset all i8042 keyboard buffers. - */ -static void i8042_flush_buffer(void) -{ - mutex_lock(&to_host_mutex); - queue_reset(&to_host); - mutex_unlock(&to_host_mutex); - lpc_keyboard_clear_buffer(); -} - void keyboard_host_write(int data, int is_cmd) { struct host_byte h; @@ -287,11 +273,10 @@ static void i8042_send_to_host(int len, const uint8_t *bytes) /* Change to set 1 if the I8042_XLATE flag is set. */ static enum scancode_set_list acting_code_set(enum scancode_set_list set) { - if (controller_ram[0] & I8042_XLATE) { - /* If the keyboard translation is enabled, then always - * generates set 1. */ + /* Always generate set 1 if keyboard translation is enabled */ + if (controller_ram[0] & I8042_XLATE) return SCANCODE_SET_1; - } + return set; } @@ -372,16 +357,30 @@ static enum ec_error_list matrix_callback(int8_t row, int8_t col, return EC_SUCCESS; } +/** + * Set typematic delays based on host data byte. + */ +static void set_typematic_delays(uint8_t data) +{ + typematic_value_from_host = data; + typematic_first_delay = MSEC * + (((typematic_value_from_host & 0x60) >> 5) + 1) * 250; + typematic_inter_delay = SECOND * + (1 << ((typematic_value_from_host & 0x18) >> 3)) * + ((typematic_value_from_host & 0x7) + 8) / 240; +} + static void reset_rate_and_delay(void) { - typematic_value_from_host = DEFAULT_TYPEMATIC_VALUE; - refill_first_delay = DEFAULT_FIRST_DELAY; - refill_inter_delay = DEFAULT_INTER_DELAY; + set_typematic_delays(DEFAULT_TYPEMATIC_VALUE); } void keyboard_clear_buffer(void) { - i8042_flush_buffer(); + mutex_lock(&to_host_mutex); + queue_reset(&to_host); + mutex_unlock(&to_host_mutex); + lpc_keyboard_clear_buffer(); } static void keyboard_wakeup(void) @@ -408,7 +407,8 @@ void keyboard_state_changed(int row, int col, int is_pressed) if (is_pressed) { keyboard_wakeup(); - typematic_delay = refill_first_delay * MSEC; + typematic_deadline.val = get_time().val + typematic_first_delay; + memcpy(typematic_scan_code, scan_code, len); typematic_len = len; task_wake(TASK_ID_TYPEMATIC); @@ -551,13 +551,7 @@ static int handle_keyboard_data(uint8_t data, uint8_t *output) case STATE_SETREP: CPRINTF5("[%T KB eaten by STATE_SETREP: 0x%02x]\n", data); - typematic_value_from_host = data; - refill_first_delay = - (((typematic_value_from_host & 0x60) >> 5) + 1) * 250; - refill_inter_delay = MSEC * - (1 << ((typematic_value_from_host & 0x18) >> 3)) * - ((typematic_value_from_host & 0x7) + 8) / - 240; + set_typematic_delays(data); output[out_len++] = I8042_RET_ACK; data_port_state = STATE_NORMAL; @@ -898,20 +892,29 @@ void i8042_command_task(void) void keyboard_typematic_task(void) { - while (1) { - task_wait_event(-1); + timestamp_t t; + int wait = -1; - while (typematic_len) { - usleep(TYPEMATIC_DELAY_UNIT); - typematic_delay -= TYPEMATIC_DELAY_UNIT; + reset_rate_and_delay(); - if (typematic_delay <= 0) { - /* re-send to host */ - if (keystroke_enabled) - i8042_send_to_host(typematic_len, - typematic_scan_code); - typematic_delay = refill_inter_delay * MSEC; - } + while (1) { + task_wait_event(wait); + + t = get_time(); + + if (!typematic_len) { + /* Typematic disabled; wait for enable */ + wait = -1; + } else if (timestamp_expired(typematic_deadline, &t)) { + /* Ready for next typematic keystroke */ + if (keystroke_enabled) + i8042_send_to_host(typematic_len, + typematic_scan_code); + typematic_deadline.val = t.val + typematic_inter_delay; + wait = typematic_inter_delay; + } else { + /* Woke up too soon; wait for remaining interval */ + wait = typematic_deadline.val - t.val; } } } @@ -924,14 +927,15 @@ static int command_typematic(int argc, char **argv) int i; if (argc == 3) { - refill_first_delay = strtoi(argv[1], NULL, 0); - refill_inter_delay = strtoi(argv[2], NULL, 0); + typematic_first_delay = strtoi(argv[1], NULL, 0) * MSEC; + typematic_inter_delay = strtoi(argv[2], NULL, 0) * MSEC; } ccprintf("From host: 0x%02x\n", typematic_value_from_host); - ccprintf("First delay: %d ms\n", refill_first_delay); - ccprintf("Inter delay: %d ms\n", refill_inter_delay); - ccprintf("Current: %d ms\n", typematic_delay / 1000); + ccprintf("First delay: %d ms\n", typematic_first_delay / 1000); + ccprintf("Inter delay: %d ms\n", typematic_inter_delay / 1000); + ccprintf("Now: %.6ld\n", get_time().val); + ccprintf("Deadline: %.6ld\n", typematic_deadline.val); ccputs("Repeat scan code:"); for (i = 0; i < typematic_len; ++i) |