summaryrefslogtreecommitdiff
path: root/common/keyboard_8042.c
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2013-03-28 12:42:44 -0700
committerChromeBot <chrome-bot@google.com>2013-03-29 11:40:35 -0700
commit19ff62cbb05eb0f8bb6ef1707bc208f11ea22589 (patch)
tree914014cd6a31ca50fecacae615c76407ff4a6a0e /common/keyboard_8042.c
parent95a3a4107ae9c9013dbf3fb51ca3e98346cb82bb (diff)
downloadchrome-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>
Diffstat (limited to 'common/keyboard_8042.c')
-rw-r--r--common/keyboard_8042.c108
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)