From 83a1f53cfae1fb65bd85dfda3f5b0dd3774262e4 Mon Sep 17 00:00:00 2001 From: SuperTurboZ <42510238+SuperTurboZ@users.noreply.github.com> Date: Thu, 8 Dec 2022 00:27:42 +0900 Subject: [PATCH] input: keyboard: fix key scan and support more events --- drivers/input/keyboard/brain-kbd-i2c.c | 74 +++++++++++++++++++++----- 1 file changed, 61 insertions(+), 13 deletions(-) diff --git a/drivers/input/keyboard/brain-kbd-i2c.c b/drivers/input/keyboard/brain-kbd-i2c.c index e7cd36b6ec7d..4bd1d844337e 100644 --- a/drivers/input/keyboard/brain-kbd-i2c.c +++ b/drivers/input/keyboard/brain-kbd-i2c.c @@ -24,6 +24,16 @@ #define BK_IS_PRESSED(val) ((~val & 0x40) >> 6) +#define BK_IS_SWITCH(val) (((val)&0x80) != 0) +#define BK_SW_CODE(val) (((val) >> 1) & 0x1F) +#define BK_SWITCH_ON(val) (((val)&1) == 0) + +enum { BK_SW_LCD_TRANSFORMING_TO_TABLET = 3, + BK_SW_UNKNOWN4, + BK_SW_USB_VBUS, + BK_SW_LCD_FULLY_TRANSFORMED, + BK_SW_LCD_TRANSFORMING_TO_CLOSED }; + struct keymap_def { u8 brain_keycode; unsigned int kernel_keycode; @@ -39,11 +49,41 @@ struct bk_i2c_data { bool symbol; u32 symbol_keycode; + bool closing; }; static bool detect_key(struct bk_i2c_data *kbd, u8 keycode) { int i; + if (BK_IS_SWITCH(keycode)) { + bool sw_on = BK_SWITCH_ON(keycode); + unsigned int sw_code; + switch (BK_SW_CODE(keycode)) { + case BK_SW_LCD_TRANSFORMING_TO_TABLET: + if (!sw_on) { + kbd->closing = false; + } + return true; + case BK_SW_LCD_TRANSFORMING_TO_CLOSED: + if (sw_on) { + kbd->closing = true; + } + return true; + + case BK_SW_LCD_FULLY_TRANSFORMED: + sw_code = (kbd->closing) ? SW_LID : SW_TABLET_MODE; + input_report_switch(kbd->idev, sw_code, sw_on); + return true; + + case BK_SW_USB_VBUS: + input_report_switch(kbd->idev, SW_DOCK, sw_on); + return true; + default: + dev_dbg(&kbd->cli->dev, "Unknown switch event %0x02X", + keycode); + } + return false; + } if ((keycode & 0x3f) == (u8)(kbd->symbol_keycode)) { if (BK_IS_PRESSED(keycode)) { @@ -101,20 +141,23 @@ static irqreturn_t bk_i2c_irq_handler(int irq, void *devid) n = raw >> 8; k1 = raw & 0xff; + dev_dbg(&kbd->cli->dev, "N=%d, Raw key event: %02X\n", n, k1); if (k1 == 0x00) { dev_dbg(&kbd->cli->dev, "interrupted but no key press was found\n"); goto err; } - if (n == 1) { - if (detect_key(kbd, k1)) { - goto done; - } else { - dev_dbg(&kbd->cli->dev, - "unknown key was pressed: %02x\n", (k1 & 0x3f)); - goto err; - } + if (n < 1) { + goto done; + } + if (!detect_key(kbd, k1)) { + dev_dbg(&kbd->cli->dev, "unknown key was pressed: %02x\n", + (k1 & 0x3f)); + goto err; + } + if (n < 2) { + goto done; } raw = i2c_smbus_read_word_swapped(kbd->cli, BK_CMD_KEYCODE); @@ -127,12 +170,13 @@ static irqreturn_t bk_i2c_irq_handler(int irq, void *devid) k2 = (raw & 0xff00) >> 8; k3 = raw & 0xff; + dev_dbg(&kbd->cli->dev, "Raw key event 2 and 3: %02X,%02X\n", k2, k3); detect_key(kbd, k2); - if (n == 3) { - detect_key(kbd, k3); + if (n < 3) { + goto done; } - + detect_key(kbd, k3); done: input_sync(kbd->idev); err: @@ -155,8 +199,8 @@ static int bk_i2c_probe(struct i2c_client *cli, const struct i2c_device_id *id) return -ENOMEM; } - if (of_property_read_u32(cli->dev.of_node, - "symbol-keycode", &kbd->symbol_keycode)) { + if (of_property_read_u32(cli->dev.of_node, "symbol-keycode", + &kbd->symbol_keycode)) { kbd->symbol_keycode = 0x19; } @@ -254,6 +298,10 @@ static int bk_i2c_probe(struct i2c_client *cli, const struct i2c_device_id *id) input_set_capability(kbd->idev, EV_KEY, kbd->km_symbol[i].kernel_keycode); } + kbd->closing = false; + input_set_capability(kbd->idev, EV_SW, SW_LID); + input_set_capability(kbd->idev, EV_SW, SW_TABLET_MODE); + input_set_capability(kbd->idev, EV_SW, SW_DOCK); err = input_register_device(kbd->idev); if (err) {