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>
This commit is contained in:
Nicolas Boichat
2018-05-30 15:55:57 +08:00
committed by chrome-bot
parent 8290d879da
commit 65d87bf9f0
6 changed files with 98 additions and 37 deletions

View File

@@ -15,7 +15,6 @@
#include "i2c.h"
#include "keyboard_raw.h"
#include "keyboard_scan.h"
#include "lid_switch.h"
#include "printf.h"
#include "pwm.h"
#include "pwm_chip.h"
@@ -25,6 +24,7 @@
#include "rollback.h"
#include "spi.h"
#include "system.h"
#include "tablet_mode.h"
#include "task.h"
#include "touchpad.h"
#include "timer.h"
@@ -253,18 +253,6 @@ void board_touchpad_reset(void)
#endif
}
#if defined(SECTION_IS_RW) && defined(BOARD_WHISKERS)
static void lid_change(void)
{
if (lid_is_open())
usb_connect();
else
usb_disconnect();
}
DECLARE_HOOK(HOOK_LID_CHANGE, lid_change, HOOK_PRIO_DEFAULT);
DECLARE_HOOK(HOOK_INIT, lid_change, HOOK_PRIO_DEFAULT + 1);
#endif
/*
* Get entropy based on Clock Recovery System, which is enabled on hammer to
* synchronize USB SOF with internal oscillator.

View File

@@ -231,8 +231,10 @@
#ifdef BOARD_WHISKERS
#define CONFIG_LED_DRIVER_LM3630A
#define CONFIG_LID_SWITCH
#define CONFIG_USB_INHIBIT_CONNECT
#define CONFIG_TABLET_MODE
#define CONFIG_TABLET_SWITCH
#define TABLET_MODE_GPIO_L GPIO_TABLET_MODE_L
#define CONFIG_KEYBOARD_TABLET_MODE_SWITCH
/* Enable control of SPI over USB */
#define CONFIG_USB_SPI
#define CONFIG_SPI_MASTER

View File

@@ -11,7 +11,7 @@
#ifdef SECTION_IS_RW
GPIO_INT(TOUCHPAD_INT, PIN(B, 8), GPIO_INT_FALLING, touchpad_interrupt)
#ifdef BOARD_WHISKERS
GPIO_INT(LID_OPEN, PIN(B, 11), GPIO_PULL_UP | GPIO_INT_BOTH, lid_interrupt)
GPIO_INT(TABLET_MODE_L, PIN(B, 11), GPIO_PULL_UP | GPIO_INT_BOTH, tablet_mode_isr)
#endif /* BOARD_WHISKERS */
#endif /* SECTION_IS_RW */

View File

@@ -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)
{ }

View File

@@ -41,6 +41,7 @@ static void tablet_mode_debounce(void)
/* We won't reach here on boards without a dedicated tablet switch */
tablet_set_mode(!gpio_get_level(TABLET_MODE_GPIO_L));
#ifdef CONFIG_LID_ANGLE_UPDATE
/* Then, we disable peripherals only when the lid reaches 360 position.
* (It's probably already disabled by motion_sense_task.)
* We deliberately do not enable peripherals when the lid is leaving
@@ -48,6 +49,7 @@ static void tablet_mode_debounce(void)
* reaches laptop zone (180 or less). */
if (tablet_mode)
lid_angle_peripheral_enable(0);
#endif /* CONFIG_LID_ANGLE_UPDATE */
}
DECLARE_DEFERRED(tablet_mode_debounce);

View File

@@ -1931,6 +1931,9 @@
/* Add support for the assistant key. */
#undef CONFIG_KEYBOARD_ASSISTANT_KEY
/* Add support for a switch that indicates if the device is in tablet mode. */
#undef CONFIG_KEYBOARD_TABLET_MODE_SWITCH
/*
* Minimum CPU clocks between scans. This ensures that keyboard scanning
* doesn't starve the other EC tasks of CPU when running at a decreased system