summaryrefslogtreecommitdiff
path: root/chip
diff options
context:
space:
mode:
authorNicolas Boichat <drinkcat@chromium.org>2018-05-30 15:55:57 +0800
committerchrome-bot <chrome-bot@chromium.org>2018-06-06 05:00:49 -0700
commit65d87bf9f0ef9b084d91ed44eda58b7463c82b48 (patch)
tree64bcafd6797a3a60bc9c5a7e2164688ad9bb7a38 /chip
parent8290d879dab1fbba805cfcdb4f2409bdee803dc6 (diff)
downloadchrome-ec-65d87bf9f0ef9b084d91ed44eda58b7463c82b48.tar.gz
whiskers: Expose a switch for tablet mode
With this, whiskers exposes a tablet mode switch to inform the lid when the base is flipped around. We take this opportunity to clean up a bit whiskers/keyboard code: - Use tablet mode switch instead of lid switch - Refactor usb_hid_keyboard.c to accept either assistant key or tablet mode switch, or both. - Remove bit-field usage in HID report struct, and instead, generalize with an "extra" field that can be used for additional key/switches. BRANCH=none BUG=b:73133611 TEST=Flash whiskers, see that tablet mode events are sent when a magnet approaches the hall sensor. Change-Id: Ibf43bb04fdc867d18d9f318388d1ebd17b49d47f Signed-off-by: Nicolas Boichat <drinkcat@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/1077915 Reviewed-by: Wei-Han Chen <stimim@chromium.org>
Diffstat (limited to 'chip')
-rw-r--r--chip/stm32/usb_hid_keyboard.c108
1 files changed, 87 insertions, 21 deletions
diff --git a/chip/stm32/usb_hid_keyboard.c b/chip/stm32/usb_hid_keyboard.c
index e7c63b3fa6..566be2440f 100644
--- a/chip/stm32/usb_hid_keyboard.c
+++ b/chip/stm32/usb_hid_keyboard.c
@@ -17,6 +17,7 @@
#include "pwm.h"
#include "queue.h"
#include "registers.h"
+#include "tablet_mode.h"
#include "task.h"
#include "timer.h"
#include "util.h"
@@ -49,6 +50,11 @@ enum hid_protocol {
/* Current protocol, behaviour is identical in both modes. */
static enum hid_protocol protocol = HID_REPORT_PROTOCOL;
+#if defined(CONFIG_KEYBOARD_ASSISTANT_KEY) || \
+ defined(CONFIG_KEYBOARD_TABLET_MODE_SWITCH)
+#define HID_KEYBOARD_EXTRA_FIELD
+#endif
+
/*
* Note: This first 8 bytes of this report format cannot be changed, as that
* would break HID Boot protocol compatibility (see HID 1.11 "Appendix B: Boot
@@ -59,9 +65,9 @@ struct usb_hid_keyboard_report {
uint8_t reserved; /* 0x0 */
uint8_t keys[6];
/* Non-boot protocol fields below */
-#ifdef CONFIG_KEYBOARD_ASSISTANT_KEY
- uint8_t assistant:1;
- uint8_t reserved2:7;
+#ifdef HID_KEYBOARD_EXTRA_FIELD
+ /* Assistant/tablet mode switch bitmask */
+ uint8_t extra;
#endif
} __packed;
@@ -99,7 +105,11 @@ struct usb_hid_keyboard_output_report {
#define HID_KEYBOARD_MODIFIER_LOW 0xe0
#define HID_KEYBOARD_MODIFIER_HIGH 0xe7
+/* Special keys/switches */
+#define HID_KEYBOARD_EXTRA_LOW 0xf0
#define HID_KEYBOARD_ASSISTANT_KEY 0xf0
+#define HID_KEYBOARD_TABLET_MODE_SWITCH 0xf1
+#define HID_KEYBOARD_EXTRA_HIGH 0xf1
/* The standard Chrome OS keyboard matrix table. See HUT 1.12v2 Table 12 and
* https://www.w3.org/TR/DOM-Level-3-Events-code .
@@ -191,19 +201,56 @@ const struct usb_endpoint_descriptor USB_EP_DESC(USB_IFACE_HID_KEYBOARD, 02) = {
0x29, 0xa4, /* Usage Maximum (164) */ \
0x81, 0x00, /* Input (Data, Array), ;Key arrays (6 bytes) */
+/*
+ * Vendor-defined Usage Page 0xffd1:
+ * - 0x18: Assistant key
+ * - 0x19: Tablet mode switch
+ */
+#ifdef HID_KEYBOARD_EXTRA_FIELD
+#ifdef CONFIG_KEYBOARD_ASSISTANT_KEY
#define KEYBOARD_ASSISTANT_KEY_DESC \
- 0x06, 0xd1, 0xff, /* Usage Page (Vendor-defined 0xffd1) */ \
0x19, 0x18, /* Usage Minimum */ \
0x29, 0x18, /* Usage Maximum */ \
0x15, 0x00, /* Logical Minimum (0) */ \
0x25, 0x01, /* Logical Maximum (1) */ \
0x75, 0x01, /* Report Size (1) */ \
0x95, 0x01, /* Report Count (1) */ \
- 0x81, 0x02, /* Input (Data, Variable, Absolute), ;Modifier byte */ \
+ 0x81, 0x02, /* Input (Data, Variable, Absolute), ;Modifier byte */
+#else
+/* No assistant key: just pad 1 bit. */
+#define KEYBOARD_ASSISTANT_KEY_DESC \
+ 0x95, 0x01, /* Report Count (1) */ \
+ 0x75, 0x01, /* Report Size (1) */ \
+ 0x81, 0x01, /* Input (Constant), ;1-bit padding */
+#endif /* !CONFIG_KEYBOARD_ASSISTANT_KEY */
+
+#ifdef CONFIG_KEYBOARD_TABLET_MODE_SWITCH
+#define KEYBOARD_TABLET_MODE_SWITCH_DESC \
+ 0x19, 0x19, /* Usage Minimum */ \
+ 0x29, 0x19, /* Usage Maximum */ \
+ 0x15, 0x00, /* Logical Minimum (0) */ \
+ 0x25, 0x01, /* Logical Maximum (1) */ \
+ 0x75, 0x01, /* Report Size (1) */ \
+ 0x95, 0x01, /* Report Count (1) */ \
+ 0x81, 0x02, /* Input (Data, Variable, Absolute), ;Modifier byte */
+#else
+/* No tablet mode swtch: just pad 1 bit. */
+#define KEYBOARD_TABLET_MODE_SWITCH_DESC \
+ 0x95, 0x01, /* Report Count (1) */ \
+ 0x75, 0x01, /* Report Size (1) */ \
+ 0x81, 0x01, /* Input (Constant), ;1-bit padding */
+#endif /* CONFIG_KEYBOARD_TABLET_MODE_SWITCH */
+
+#define KEYBOARD_VENDOR_DESC \
+ 0x06, 0xd1, 0xff, /* Usage Page (Vendor-defined 0xffd1) */ \
+ \
+ KEYBOARD_ASSISTANT_KEY_DESC \
+ KEYBOARD_TABLET_MODE_SWITCH_DESC \
\
0x95, 0x01, /* Report Count (1) */ \
- 0x75, 0x07, /* Report Size (7) */ \
- 0x81, 0x01, /* Input (Constant), ;7-bit padding */
+ 0x75, 0x06, /* Report Size (6) */ \
+ 0x81, 0x01, /* Input (Constant), ;6-bit padding */
+#endif /* HID_KEYBOARD_EXTRA_FIELD */
#define KEYBOARD_BACKLIGHT_DESC \
0xA1, 0x02, /* Collection (Logical) */ \
@@ -226,8 +273,8 @@ static const uint8_t report_desc[] = {
KEYBOARD_BASE_DESC
-#ifdef CONFIG_KEYBOARD_ASSISTANT_KEY
- KEYBOARD_ASSISTANT_KEY_DESC
+#ifdef KEYBOARD_VENDOR_DESC
+ KEYBOARD_VENDOR_DESC
#endif
0xC0 /* End Collection */
@@ -241,8 +288,8 @@ static const uint8_t report_desc_with_backlight[] = {
KEYBOARD_BASE_DESC
-#ifdef CONFIG_KEYBOARD_ASSISTANT_KEY
- KEYBOARD_ASSISTANT_KEY_DESC
+#ifdef KEYBOARD_VENDOR_DESC
+ KEYBOARD_VENDOR_DESC
#endif
KEYBOARD_BACKLIGHT_DESC
@@ -501,9 +548,14 @@ static void keyboard_process_queue(void)
queue_advance_head(&key_queue, 1);
- if (ev.keycode == HID_KEYBOARD_ASSISTANT_KEY) {
-#ifdef CONFIG_KEYBOARD_ASSISTANT_KEY
- report.assistant = ev.pressed ? 1 : 0;
+ if (ev.keycode >= HID_KEYBOARD_EXTRA_LOW &&
+ ev.keycode <= HID_KEYBOARD_EXTRA_HIGH) {
+#ifdef HID_KEYBOARD_EXTRA_FIELD
+ mask = 0x01 << (ev.keycode - HID_KEYBOARD_EXTRA_LOW);
+ if (ev.pressed)
+ report.extra |= mask;
+ else
+ report.extra &= ~mask;
valid = 1;
#endif
} else if (ev.keycode >= HID_KEYBOARD_MODIFIER_LOW &&
@@ -550,20 +602,14 @@ static void keyboard_process_queue(void)
write_keyboard_report();
}
-void keyboard_state_changed(int row, int col, int is_pressed)
+static void queue_keycode_event(uint8_t keycode, int is_pressed)
{
- uint8_t keycode = keycodes[row][col];
struct key_event ev = {
.time = __hw_clock_source_read(),
.keycode = keycode,
.pressed = is_pressed,
};
- if (!keycode) {
- CPRINTF("Unknown key at %d/%d\n", row, col);
- return;
- }
-
mutex_lock(&key_queue_mutex);
queue_add_unit(&key_queue, &ev);
mutex_unlock(&key_queue_mutex);
@@ -571,6 +617,26 @@ void keyboard_state_changed(int row, int col, int is_pressed)
keyboard_process_queue();
}
+#ifdef CONFIG_KEYBOARD_TABLET_MODE_SWITCH
+static void tablet_mode_change(void)
+{
+ queue_keycode_event(HID_KEYBOARD_TABLET_MODE_SWITCH, tablet_get_mode());
+}
+DECLARE_HOOK(HOOK_TABLET_MODE_CHANGE, tablet_mode_change, HOOK_PRIO_DEFAULT);
+#endif
+
+void keyboard_state_changed(int row, int col, int is_pressed)
+{
+ uint8_t keycode = keycodes[row][col];
+
+ if (!keycode) {
+ CPRINTF("Unknown key at %d/%d\n", row, col);
+ return;
+ }
+
+ queue_keycode_event(keycode, is_pressed);
+}
+
void clear_typematic_key(void)
{ }