aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Tissoires <benjamin.tissoires@redhat.com>2015-05-01 16:22:45 -0400
committerJiri Kosina <jkosina@suse.cz>2015-05-07 04:28:11 -0400
commit181a8b911dd26cd44dc7283d7953a2e138842767 (patch)
tree88079bf0e5eb46ae0afaa57e926e6fcb093cf985
parentd92189ebbdcd0eb180317d8cd6d46c57ac9a3dc0 (diff)
HID: lenovo: add support for Lenovo ThinkPad Keyboard Pro unit
This dock is used with the Thinkpad Helix 2 but suffers from an error in the report descriptor where an usage max is 65535. Add a report fixup for it and make the keyboard working. Tested-by: Jonathan Oppenheim <lejono@gmail.com> Tested-by: John Reid <owlman.lists@gmail.com> Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r--drivers/hid/hid-core.c1
-rw-r--r--drivers/hid/hid-ids.h1
-rw-r--r--drivers/hid/hid-lenovo.c31
3 files changed, 33 insertions, 0 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 722a925795a2..c2baf8c7c6bb 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1851,6 +1851,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
1851 { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) }, 1851 { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) },
1852 { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CUSBKBD) }, 1852 { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CUSBKBD) },
1853 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CBTKBD) }, 1853 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CBTKBD) },
1854 { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPPRODOCK) },
1854#endif 1855#endif
1855 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) }, 1856 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) },
1856 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) }, 1857 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) },
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 41f167e4d75f..1649436b9694 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -585,6 +585,7 @@
585#define USB_DEVICE_ID_LENOVO_TPKBD 0x6009 585#define USB_DEVICE_ID_LENOVO_TPKBD 0x6009
586#define USB_DEVICE_ID_LENOVO_CUSBKBD 0x6047 586#define USB_DEVICE_ID_LENOVO_CUSBKBD 0x6047
587#define USB_DEVICE_ID_LENOVO_CBTKBD 0x6048 587#define USB_DEVICE_ID_LENOVO_CBTKBD 0x6048
588#define USB_DEVICE_ID_LENOVO_TPPRODOCK 0x6067
588 589
589#define USB_VENDOR_ID_LG 0x1fd2 590#define USB_VENDOR_ID_LG 0x1fd2
590#define USB_DEVICE_ID_LG_MULTITOUCH 0x0064 591#define USB_DEVICE_ID_LG_MULTITOUCH 0x0064
diff --git a/drivers/hid/hid-lenovo.c b/drivers/hid/hid-lenovo.c
index 78608d646007..4e291d5ad645 100644
--- a/drivers/hid/hid-lenovo.c
+++ b/drivers/hid/hid-lenovo.c
@@ -43,6 +43,35 @@ struct lenovo_drvdata_cptkbd {
43 43
44#define map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c)) 44#define map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c))
45 45
46static const __u8 lenovo_pro_dock_need_fixup_collection[] = {
47 0x05, 0x88, /* Usage Page (Vendor Usage Page 0x88) */
48 0x09, 0x01, /* Usage (Vendor Usage 0x01) */
49 0xa1, 0x01, /* Collection (Application) */
50 0x85, 0x04, /* Report ID (4) */
51 0x19, 0x00, /* Usage Minimum (0) */
52 0x2a, 0xff, 0xff, /* Usage Maximum (65535) */
53};
54
55static __u8 *lenovo_report_fixup(struct hid_device *hdev, __u8 *rdesc,
56 unsigned int *rsize)
57{
58 switch (hdev->product) {
59 case USB_DEVICE_ID_LENOVO_TPPRODOCK:
60 /* the fixups that need to be done:
61 * - get a reasonable usage max for the vendor collection
62 * 0x8801 from the report ID 4
63 */
64 if (*rsize >= 153 &&
65 memcmp(&rdesc[140], lenovo_pro_dock_need_fixup_collection,
66 sizeof(lenovo_pro_dock_need_fixup_collection)) == 0) {
67 rdesc[151] = 0x01;
68 rdesc[152] = 0x00;
69 }
70 break;
71 }
72 return rdesc;
73}
74
46static int lenovo_input_mapping_tpkbd(struct hid_device *hdev, 75static int lenovo_input_mapping_tpkbd(struct hid_device *hdev,
47 struct hid_input *hi, struct hid_field *field, 76 struct hid_input *hi, struct hid_field *field,
48 struct hid_usage *usage, unsigned long **bit, int *max) 77 struct hid_usage *usage, unsigned long **bit, int *max)
@@ -784,6 +813,7 @@ static const struct hid_device_id lenovo_devices[] = {
784 { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) }, 813 { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) },
785 { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CUSBKBD) }, 814 { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CUSBKBD) },
786 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CBTKBD) }, 815 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CBTKBD) },
816 { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPPRODOCK) },
787 { } 817 { }
788}; 818};
789 819
@@ -797,6 +827,7 @@ static struct hid_driver lenovo_driver = {
797 .probe = lenovo_probe, 827 .probe = lenovo_probe,
798 .remove = lenovo_remove, 828 .remove = lenovo_remove,
799 .raw_event = lenovo_raw_event, 829 .raw_event = lenovo_raw_event,
830 .report_fixup = lenovo_report_fixup,
800}; 831};
801module_hid_driver(lenovo_driver); 832module_hid_driver(lenovo_driver);
802 833