summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChromeOS Developer <dparker@chromium.org>2014-01-10 14:15:34 -0800
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2014-02-07 04:13:14 +0000
commit4015172ed1b8a93350e433deb3399693ff4e00ed (patch)
tree866a15514a901fc2e0d8a0ee90609d11bba97932
parent798df2a6d077cb973cb60c5401d0ec037006fe9a (diff)
downloadchrome-ec-4015172ed1b8a93350e433deb3399693ff4e00ed.tar.gz
8042: Add interface for handling off-matrix button changes
BUG=chrome-os-partner:24370 BRANCH=tot TEST=Power key and keyboard work normally. Signed-off-by: Dave Parker <dparker@chromium.org> Orig-Change-Id: I291ff384ae2fc3e074132330713f0b0c2cc36a76 Reviewed-on: https://chromium-review.googlesource.com/184543 (cherry picked from commit c65f82a5b02cdecf5b62f71ef2e916795f808389) Change-Id: I1cd02e824c97eb5909e7bff68c8ecefc89f52df0 Reviewed-on: https://chromium-review.googlesource.com/185242 Tested-by: Randall Spangler <rspangler@chromium.org> Reviewed-by: Bill Richardson <wfrichar@chromium.org> Commit-Queue: Randall Spangler <rspangler@chromium.org>
-rw-r--r--common/keyboard_8042.c156
-rw-r--r--include/button.h24
-rw-r--r--include/keyboard_protocol.h10
3 files changed, 129 insertions, 61 deletions
diff --git a/common/keyboard_8042.c b/common/keyboard_8042.c
index dff695fbdb..bf3cc3fdd9 100644
--- a/common/keyboard_8042.c
+++ b/common/keyboard_8042.c
@@ -6,6 +6,7 @@
*/
#include "chipset.h"
+#include "button.h"
#include "common.h"
#include "console.h"
#include "hooks.h"
@@ -113,7 +114,6 @@ static uint8_t controller_ram[0x20] = {
/* 0x01 - 0x1f are controller RAM */
};
static uint8_t A20_status;
-static int power_button_pressed;
static void keyboard_special(uint16_t k);
/*
@@ -189,6 +189,15 @@ static const uint16_t scancode_set2[KEYBOARD_ROWS][KEYBOARD_COLS] = {
0x0044, 0x0000, 0xe075, 0xe06b},
};
+/* Button scancodes. Must be in the same order as defined in button_type */
+static const uint16_t button_scancodes[2][KEYBOARD_BUTTON_COUNT] = {
+ /* Set 1 */
+ {0xe05e, 0xe02e, 0xe030},
+ /* Set 2 */
+ {0xe037, 0xe021, 0xe033},
+};
+BUILD_ASSERT(ARRAY_SIZE(button_scancodes[0]) == KEYBOARD_BUTTON_COUNT);
+
/*****************************************************************************/
/* Keyboard event log */
@@ -290,45 +299,21 @@ static enum scancode_set_list acting_code_set(enum scancode_set_list set)
return set;
}
-static enum ec_error_list matrix_callback(int8_t row, int8_t col,
- int8_t pressed,
- enum scancode_set_list code_set,
- uint8_t *scan_code, int32_t *len)
+/**
+ * Return the make or break code bytes for the active scancode set.
+ *
+ * @param make_code The make code to generate the make or break code from
+ * @param pressed Whether the key or button was pressed
+ * @param code_set The scancode set being used
+ * @param scan_code An array of bytes to store the make or break code in
+ * @param len The number of valid bytes to send in scan_code
+ */
+static void scancode_bytes(uint16_t make_code, int8_t pressed,
+ enum scancode_set_list code_set, uint8_t *scan_code,
+ int32_t *len)
{
- uint16_t make_code;
-
- ASSERT(scan_code);
- ASSERT(len);
-
- if (row > KEYBOARD_ROWS || col > KEYBOARD_COLS)
- return EC_ERROR_INVAL;
-
- if (pressed)
- keyboard_special(scancode_set1[row][col]);
-
*len = 0;
- code_set = acting_code_set(code_set);
-
- switch (code_set) {
- case SCANCODE_SET_1:
- make_code = scancode_set1[row][col];
- break;
-
- case SCANCODE_SET_2:
- make_code = scancode_set2[row][col];
- break;
-
- default:
- CPRINTF("[%T KB scancode set %d unsupported]\n", code_set);
- return EC_ERROR_UNIMPLEMENTED;
- }
-
- if (!make_code) {
- CPRINTF("[%T KB scancode %d:%d missing]\n", row, col);
- return EC_ERROR_UNIMPLEMENTED;
- }
-
/* Output the make code (from table) */
if (make_code >= 0x0100) {
*len += 2;
@@ -363,7 +348,46 @@ static enum ec_error_list matrix_callback(int8_t row, int8_t col,
default:
break;
}
+}
+
+static enum ec_error_list matrix_callback(int8_t row, int8_t col,
+ int8_t pressed,
+ enum scancode_set_list code_set,
+ uint8_t *scan_code, int32_t *len)
+{
+ uint16_t make_code;
+
+ ASSERT(scan_code);
+ ASSERT(len);
+
+ if (row > KEYBOARD_ROWS || col > KEYBOARD_COLS)
+ return EC_ERROR_INVAL;
+
+ if (pressed)
+ keyboard_special(scancode_set1[row][col]);
+
+ code_set = acting_code_set(code_set);
+
+ switch (code_set) {
+ case SCANCODE_SET_1:
+ make_code = scancode_set1[row][col];
+ break;
+
+ case SCANCODE_SET_2:
+ make_code = scancode_set2[row][col];
+ break;
+
+ default:
+ CPRINTF("[%T KB scancode set %d unsupported]\n", code_set);
+ return EC_ERROR_UNIMPLEMENTED;
+ }
+
+ if (!make_code) {
+ CPRINTF("[%T KB scancode %d:%d missing]\n", row, col);
+ return EC_ERROR_UNIMPLEMENTED;
+ }
+ scancode_bytes(make_code, pressed, code_set, scan_code, len);
return EC_SUCCESS;
}
@@ -899,6 +923,38 @@ void keyboard_protocol_task(void)
}
}
+/**
+ * Handle button changing state.
+ *
+ * @param button Type of button that changed
+ * @param is_pressed Whether the button was pressed or released
+ */
+void keyboard_update_button(enum keyboard_button_type button, int is_pressed)
+{
+ /* TODO(crosbug.com/p/24956): Add typematic repeat support. */
+
+ uint8_t scan_code[MAX_SCAN_CODE_LEN];
+ uint16_t make_code;
+ uint32_t len;
+ enum scancode_set_list code_set;
+
+ /*
+ * Only send the scan code if main chipset is fully awake and
+ * keystrokes are enabled.
+ */
+ if (!chipset_in_state(CHIPSET_STATE_ON) || !keystroke_enabled)
+ return;
+
+ code_set = acting_code_set(scancode_set);
+ make_code = button_scancodes[code_set - SCANCODE_SET_1][button];
+ scancode_bytes(make_code, is_pressed, code_set, scan_code, &len);
+ ASSERT(len > 0);
+ if (keystroke_enabled) {
+ i8042_send_to_host(len, scan_code);
+ task_wake(TASK_ID_KEYPROTO);
+ }
+}
+
/*****************************************************************************/
/* Console commands */
@@ -1092,30 +1148,8 @@ DECLARE_HOOK(HOOK_INIT, keyboard_restore_state, HOOK_PRIO_DEFAULT);
*/
static void keyboard_power_button(void)
{
- enum scancode_set_list code_set;
- uint8_t code[2][2][3] = {
- { /* set 1 */
- {0xe0, 0xde}, /* break */
- {0xe0, 0x5e}, /* make */
- }, { /* set 2 */
- {0xe0, 0xf0, 0x37}, /* break */
- {0xe0, 0x37}, /* make */
- }
- };
-
- power_button_pressed = power_button_is_pressed();
-
- /*
- * Only send the scan code if main chipset is fully awake and
- * keystrokes are enabled.
- */
- if (!chipset_in_state(CHIPSET_STATE_ON) || !keystroke_enabled)
- return;
-
- code_set = acting_code_set(scancode_set);
- i8042_send_to_host(
- (code_set == SCANCODE_SET_2 && !power_button_pressed) ? 3 : 2,
- code[code_set - SCANCODE_SET_1][power_button_pressed]);
+ keyboard_update_button(KEYBOARD_BUTTON_POWER,
+ power_button_is_pressed());
}
DECLARE_HOOK(HOOK_POWER_BUTTON_CHANGE, keyboard_power_button,
HOOK_PRIO_DEFAULT);
diff --git a/include/button.h b/include/button.h
new file mode 100644
index 0000000000..e8344b308f
--- /dev/null
+++ b/include/button.h
@@ -0,0 +1,24 @@
+/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* Button API for Chrome EC */
+
+#ifndef __CROS_EC_BUTTON_H
+#define __CROS_EC_BUTTON_H
+
+#include "common.h"
+#include "gpio.h"
+
+#define BUTTON_FLAG_ACTIVE_HIGH (1 << 0)
+
+enum keyboard_button_type {
+ KEYBOARD_BUTTON_POWER = 0,
+ KEYBOARD_BUTTON_VOLUME_DOWN,
+ KEYBOARD_BUTTON_VOLUME_UP,
+
+ KEYBOARD_BUTTON_COUNT
+};
+
+#endif /* __CROS_EC_BUTTON_H */
diff --git a/include/keyboard_protocol.h b/include/keyboard_protocol.h
index 866c58807b..6fc0a06f7c 100644
--- a/include/keyboard_protocol.h
+++ b/include/keyboard_protocol.h
@@ -9,6 +9,7 @@
#define __CROS_EC_KEYBOARD_PROTOCOL_H
#include "common.h"
+#include "button.h"
/* Routines common to all protocols */
@@ -17,6 +18,15 @@
*/
void keyboard_clear_buffer(void);
+/*
+ * Respond to button changes. Implemented by a host-specific
+ * handler.
+ *
+ * @param button The button that changed.
+ * @param is_pressed Whether the button is now pressed.
+ */
+void keyboard_update_button(enum keyboard_button_type button, int is_pressed);
+
/* Protocol-specific includes */
#ifdef CONFIG_KEYBOARD_PROTOCOL_8042