summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordavid huang <david.huang@quantatw.com>2018-06-04 13:12:30 +0800
committerHung-Te Lin <hungte@chromium.org>2018-08-07 13:08:43 +0000
commitd7850824797ce72b95265c0cf5b9b97856cbdb8d (patch)
treec94d1584c23285eff07ac9961747da9cf1d821f3
parentd2eb4fc9c9bb404d85cfc5db4df2250cc757c131 (diff)
downloadchrome-ec-d7850824797ce72b95265c0cf5b9b97856cbdb8d.tar.gz
ec: Allow setting keyboard mapping dynamically
A new CONFIG_KEYBOARD_DYNAMIC_MAPPING allows AP firmware to select different keyboard mappings. This is different from SCANCODE_MUTABLE and is very helpful if the system has to boot in different mode and map keyboards in different ways, for example only enabling Fn keys in AP legacy mode. SCANCODE_MUTABLE is more for "difference that won't change once EC boots" while DYNAMIC_MAPPING is for "difference changes per each AP reboot". In AP firmware, to select mapping it should invoke the ACPI EC_ACPI_MEM_KB_MAPPING_TYPE (0x0a) with expected mapping type. A board that wants to enable dynamic mapping should provide implementations of following functions: void keyboard_board_mapping_changed(int mapping); And when using 8042 protocol, the new mapping can be implemented by providing a board specific translation function: uint16_t keyboard_board_translate(...); BUG=b:72200093 BRANCH=eve TEST=Builds and boot properly. Change-Id: If512931066aab6efa1467b038de46c6982af8bec Signed-off-by: David Huang <David.Huang@quantatw.com> Signed-off-by: Hung-Te Lin <hungte@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/1084368
-rw-r--r--common/acpi.c6
-rw-r--r--common/keyboard_8042.c34
-rw-r--r--common/switch.c4
-rw-r--r--include/config.h6
-rw-r--r--include/ec_commands.h6
-rw-r--r--include/keyboard_8042.h26
-rw-r--r--include/keyboard_protocol.h25
7 files changed, 98 insertions, 9 deletions
diff --git a/common/acpi.c b/common/acpi.c
index d9815100e1..27e8abd19b 100644
--- a/common/acpi.c
+++ b/common/acpi.c
@@ -9,6 +9,7 @@
#include "dptf.h"
#include "hooks.h"
#include "host_command.h"
+#include "keyboard_protocol.h"
#include "lpc.h"
#include "ec_commands.h"
#include "tablet_mode.h"
@@ -233,6 +234,11 @@ int acpi_ap_to_ec(int is_cmd, uint8_t value, uint8_t *resultptr)
}
break;
#endif
+#ifdef CONFIG_KEYBOARD_DYNAMIC_MAPPING
+ case EC_ACPI_MEM_KB_MAPPING_TYPE:
+ keyboard_select_mapping(data);
+ break;
+#endif
default:
CPRINTS("ACPI write 0x%02x = 0x%02x (ignored)",
acpi_addr, data);
diff --git a/common/keyboard_8042.c b/common/keyboard_8042.c
index f1fe330c6c..5f160cb28d 100644
--- a/common/keyboard_8042.c
+++ b/common/keyboard_8042.c
@@ -50,13 +50,6 @@ static enum {
STATE_SEND_TO_MOUSE,
} data_port_state = STATE_NORMAL;
-enum scancode_set_list {
- SCANCODE_GET_SET = 0,
- SCANCODE_SET_1,
- SCANCODE_SET_2,
- SCANCODE_SET_3,
- SCANCODE_MAX = SCANCODE_SET_3,
-};
#define MAX_SCAN_CODE_LEN 4
@@ -192,6 +185,24 @@ static void kblog_put(char type, uint8_t byte)
/*****************************************************************************/
+#ifdef CONFIG_KEYBOARD_DYNAMIC_MAPPING
+static uint8_t *memmap_kb_mapping_type;
+
+void keyboard_select_mapping(enum keyboard_mapping_type mapping)
+{
+ if (mapping < 0 || mapping >= KEYBOARD_MAPPING_INVALID)
+ return;
+ if (!memmap_kb_mapping_type)
+ memmap_kb_mapping_type = host_get_memmap(
+ EC_MEMMAP_KB_MAPPING_TYPE);
+ assert(memmap_kb_mapping_type);
+ *memmap_kb_mapping_type = mapping;
+
+ /* Notify board-specific handler. */
+ keyboard_board_mapping_changed(mapping);
+}
+#endif
+
void keyboard_host_write(int data, int is_cmd)
{
struct host_byte h;
@@ -338,6 +349,15 @@ static enum ec_error_list matrix_callback(int8_t row, int8_t col,
return EC_ERROR_UNIMPLEMENTED;
}
+#ifdef CONFIG_KEYBOARD_DYNAMIC_MAPPING
+ /**
+ * Currently it only makes sense to apply board translation in dynamic
+ * mapping. If we find more boards need special processing, then this
+ * can changed to weak linking or a specific config.
+ */
+ make_code = keyboard_board_translate(make_code, pressed, code_set);
+#endif
+
if (!make_code) {
CPRINTS("KB scancode %d:%d missing", row, col);
return EC_ERROR_UNIMPLEMENTED;
diff --git a/common/switch.c b/common/switch.c
index 93650c2629..3ee99d076b 100644
--- a/common/switch.c
+++ b/common/switch.c
@@ -111,6 +111,9 @@ static int command_mmapinfo(int argc, char **argv)
{
uint8_t *memmap_switches = host_get_memmap(EC_MEMMAP_SWITCHES);
uint8_t val = *memmap_switches;
+ uint8_t *memmap_kb_mapping_type = host_get_memmap(
+ EC_MEMMAP_KB_MAPPING_TYPE);
+ uint8_t mapping = *memmap_kb_mapping_type;
int i;
const char *explanation[] = {
"lid_open",
@@ -121,6 +124,7 @@ static int command_mmapinfo(int argc, char **argv)
"fake_dev",
};
ccprintf("memmap switches = 0x%x\n", val);
+ ccprintf("memmap kb mapping type = 0x%x\n", mapping);
for (i = 0; i < ARRAY_SIZE(explanation); i++)
if (val & (1 << i))
ccprintf(" %s\n", explanation[i]);
diff --git a/include/config.h b/include/config.h
index 83472a7c5a..743684e5e7 100644
--- a/include/config.h
+++ b/include/config.h
@@ -1598,6 +1598,12 @@
#undef CONFIG_KEYBOARD_SCANCODE_MUTABLE
/*
+ * Allow changing keyboard mapping dynamically (for example to provide Fn keys
+ * in AP firmware legacy mode).
+ */
+#undef CONFIG_KEYBOARD_DYNAMIC_MAPPING
+
+/*
* Call board-supplied keyboard_suppress_noise() function when the debounced
* keyboard state changes. Some boards use this to send a signal to the audio
* codec to suppress typing noise picked up by the microphone.
diff --git a/include/ec_commands.h b/include/ec_commands.h
index ef280abf9a..123ca1ea48 100644
--- a/include/ec_commands.h
+++ b/include/ec_commands.h
@@ -108,7 +108,8 @@
/* 0x94 - 0x99: 1st Accelerometer */
/* 0x9a - 0x9f: 2nd Accelerometer */
#define EC_MEMMAP_GYRO_DATA 0xa0 /* Gyroscope data 0xa0 - 0xa5 */
-/* Unused 0xa6 - 0xdf */
+#define EC_MEMMAP_KB_MAPPING_TYPE 0xa6 /* Current KB mapping type */
+/* Unused 0xa7 - 0xdf */
/*
* ACPI is unable to access memory mapped data at or above this offset due to
@@ -325,6 +326,9 @@
#define EC_ACPI_MEM_DEVICE_ORIENTATION 0x09
#define EC_ACPI_MEM_DEVICE_TABLET_MODE 0x01
+/* For AP to specify which keyboard mapping (Chrome or legacy) to use */
+#define EC_ACPI_MEM_KB_MAPPING_TYPE 0x0a
+
/*
* ACPI addresses 0x20 - 0xff map to EC_MEMMAP offset 0x00 - 0xdf. This data
* is read-only from the AP. Added in EC_ACPI_MEM_VERSION 2.
diff --git a/include/keyboard_8042.h b/include/keyboard_8042.h
index 00fdc9901b..d18a81562a 100644
--- a/include/keyboard_8042.h
+++ b/include/keyboard_8042.h
@@ -8,8 +8,10 @@
#ifndef __CROS_EC_KEYBOARD_8042_H
#define __CROS_EC_KEYBOARD_8042_H
-#include "common.h"
+#include <stddef.h>
+
#include "button.h"
+#include "common.h"
/**
* Called by power button handler and button interrupt handler.
@@ -28,4 +30,26 @@ void button_state_changed(enum keyboard_button_type button, int is_pressed);
*/
void keyboard_host_write(int data, int is_cmd);
+
+/* Utilities for scan code and make code. */
+
+enum scancode_set_list {
+ SCANCODE_GET_SET = 0,
+ SCANCODE_SET_1,
+ SCANCODE_SET_2,
+ SCANCODE_SET_3,
+ SCANCODE_MAX = SCANCODE_SET_3,
+};
+
+/**
+ * Returns a board-specific translated make code.
+ *
+ * @param make_code 8042 make code
+ * @param pressed Whether the key was pressed
+ * @param code_set 8042 scan code set
+ */
+uint16_t keyboard_board_translate(
+ uint16_t make_code, int8_t pressed,
+ enum scancode_set_list code_set);
+
#endif /* __CROS_EC_KEYBOARD_8042_H */
diff --git a/include/keyboard_protocol.h b/include/keyboard_protocol.h
index 45d852da98..a0684a1647 100644
--- a/include/keyboard_protocol.h
+++ b/include/keyboard_protocol.h
@@ -32,6 +32,31 @@ void keyboard_update_button(enum keyboard_button_type button, int is_pressed);
*/
uint32_t keyboard_get_button_state(void);
+#ifdef CONFIG_KEYBOARD_DYNAMIC_MAPPING
+/* Values to select scancode mapping (need CONFIG_KEYBOARD_DYNAMIC_MAPPING) */
+enum keyboard_mapping_type {
+ KEYBOARD_MAPPING_CHROMEOS = 0,
+ KEYBOARD_MAPPING_LEGACY,
+ KEYBOARD_MAPPING_INVALID,
+
+ KEYBOARD_MAPPING_DEFAULT = KEYBOARD_MAPPING_CHROMEOS
+};
+
+/**
+ * Select and change keyboard mapping.
+ *
+ * @param mapping The type of mapping (keyboard_mapping_type).
+ */
+void keyboard_select_mapping(enum keyboard_mapping_type mapping);
+
+/**
+ * Board-specific callback when keyboard mapping is changed.
+ *
+ * @param new_mapping The type of mapping to apply (keyboard_mapping_type).
+ */
+void keyboard_board_mapping_changed(enum keyboard_mapping_type new_mapping);
+#endif
+
/* Protocol-specific includes */
#ifdef CONFIG_KEYBOARD_PROTOCOL_8042