Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

HID: lenovo: fixup Lenovo Yoga Slim 7x Keyboard rdesc

The keyboard of this device has the following in its report description
for Usage (Keyboard) in Collection (Application):

# 0x15, 0x00, // Logical Minimum (0) 52
# 0x25, 0x65, // Logical Maximum (101) 54
# 0x05, 0x07, // Usage Page (Keyboard) 56
# 0x19, 0x00, // Usage Minimum (0) 58
# 0x29, 0xdd, // Usage Maximum (221) 60
# 0x81, 0x00, // Input (Data,Arr,Abs) 62

Since the Usage Min/Max range exceeds the Logical Min/Max range,
keypresses outside the Logical range are not recognized. This includes,
for example, the Japanese language keyboard variant's keys for |, _ and
\.

Fixup the report description to make the Logical range match the Usage
range, fixing the interpretation of keypresses above 101 on this device.

Signed-off-by: Lauri Tirkkonen <lauri@hacktheplanet.fi>
Signed-off-by: Jiri Kosina <jkosina@suse.com>

authored by

Lauri Tirkkonen and committed by
Jiri Kosina
a45f1580 beab067d

+18
+1
drivers/hid/hid-ids.h
··· 718 718 #define USB_DEVICE_ID_ITE_LENOVO_YOGA2 0x8350 719 719 #define I2C_DEVICE_ID_ITE_LENOVO_LEGION_Y720 0x837a 720 720 #define USB_DEVICE_ID_ITE_LENOVO_YOGA900 0x8396 721 + #define I2C_DEVICE_ID_ITE_LENOVO_YOGA_SLIM_7X_KEYBOARD 0x8987 721 722 #define USB_DEVICE_ID_ITE8595 0x8595 722 723 #define USB_DEVICE_ID_ITE_MEDION_E1239T 0xce50 723 724
+17
drivers/hid/hid-lenovo.c
··· 148 148 0x81, 0x01, /* Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) */ 149 149 }; 150 150 151 + static const __u8 lenovo_yoga7x_kbd_need_fixup_collection[] = { 152 + 0x15, 0x00, // Logical Minimum (0) 153 + 0x25, 0x65, // Logical Maximum (101) 154 + 0x05, 0x07, // Usage Page (Keyboard) 155 + 0x19, 0x00, // Usage Minimum (0) 156 + 0x29, 0xDD, // Usage Maximum (221) 157 + }; 158 + 151 159 static const __u8 *lenovo_report_fixup(struct hid_device *hdev, __u8 *rdesc, 152 160 unsigned int *rsize) 153 161 { ··· 183 175 rdesc[256] = 0x01; /* report count = 0x01 */ 184 176 rdesc[258] = 0x00; /* input = 0x00 */ 185 177 rdesc[260] = 0x01; /* report count (2) = 0x01 */ 178 + } 179 + break; 180 + case I2C_DEVICE_ID_ITE_LENOVO_YOGA_SLIM_7X_KEYBOARD: 181 + if (*rsize == 176 && 182 + memcmp(&rdesc[52], lenovo_yoga7x_kbd_need_fixup_collection, 183 + sizeof(lenovo_yoga7x_kbd_need_fixup_collection)) == 0) { 184 + rdesc[55] = rdesc[61]; // logical maximum = usage maximum 186 185 } 187 186 break; 188 187 } ··· 1553 1538 USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_X12_TAB) }, 1554 1539 { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, 1555 1540 USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_X12_TAB2) }, 1541 + { HID_DEVICE(BUS_I2C, HID_GROUP_GENERIC, 1542 + USB_VENDOR_ID_ITE, I2C_DEVICE_ID_ITE_LENOVO_YOGA_SLIM_7X_KEYBOARD) }, 1556 1543 { } 1557 1544 }; 1558 1545