diff options
author | Benjamin Tissoires <benjamin.tissoires@redhat.com> | 2015-05-01 16:22:45 -0400 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2015-05-07 04:28:11 -0400 |
commit | 181a8b911dd26cd44dc7283d7953a2e138842767 (patch) | |
tree | 88079bf0e5eb46ae0afaa57e926e6fcb093cf985 | |
parent | d92189ebbdcd0eb180317d8cd6d46c57ac9a3dc0 (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.c | 1 | ||||
-rw-r--r-- | drivers/hid/hid-ids.h | 1 | ||||
-rw-r--r-- | drivers/hid/hid-lenovo.c | 31 |
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 | ||
46 | static 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 | |||
55 | static __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 | |||
46 | static int lenovo_input_mapping_tpkbd(struct hid_device *hdev, | 75 | static 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 | }; |
801 | module_hid_driver(lenovo_driver); | 832 | module_hid_driver(lenovo_driver); |
802 | 833 | ||