diff options
author | Jiri Kosina <jkosina@suse.cz> | 2017-09-05 05:05:28 -0400 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2017-09-05 05:05:28 -0400 |
commit | d3c7ad2432115b0b53fb838c14b8ad9ad72f7254 (patch) | |
tree | 014d9ae6c1bd9aaae54f2d99e362fc4eec576465 | |
parent | d487bb6ef121357bd4cd42fe2b08a6857ed26525 (diff) | |
parent | 73c75d395857960ea135913da7bb9537248a11e6 (diff) |
Merge branch 'for-4.14/asus' into for-linus
- T100 touchpad support from Hans de Goede
-rw-r--r-- | drivers/hid/hid-asus.c | 218 | ||||
-rw-r--r-- | drivers/hid/hid-core.c | 1 | ||||
-rw-r--r-- | drivers/hid/hid-ids.h | 1 |
3 files changed, 175 insertions, 45 deletions
diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c index a4a3c38bc145..50c294be8324 100644 --- a/drivers/hid/hid-asus.c +++ b/drivers/hid/hid-asus.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/hid.h> | 29 | #include <linux/hid.h> |
30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
31 | #include <linux/input/mt.h> | 31 | #include <linux/input/mt.h> |
32 | #include <linux/usb.h> /* For to_usb_interface for T100 touchpad intf check */ | ||
32 | 33 | ||
33 | #include "hid-ids.h" | 34 | #include "hid-ids.h" |
34 | 35 | ||
@@ -38,24 +39,19 @@ MODULE_AUTHOR("Victor Vlasenko <victor.vlasenko@sysgears.com>"); | |||
38 | MODULE_AUTHOR("Frederik Wenigwieser <frederik.wenigwieser@gmail.com>"); | 39 | MODULE_AUTHOR("Frederik Wenigwieser <frederik.wenigwieser@gmail.com>"); |
39 | MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad"); | 40 | MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad"); |
40 | 41 | ||
42 | #define T100_TPAD_INTF 2 | ||
43 | |||
44 | #define T100CHI_MOUSE_REPORT_ID 0x06 | ||
41 | #define FEATURE_REPORT_ID 0x0d | 45 | #define FEATURE_REPORT_ID 0x0d |
42 | #define INPUT_REPORT_ID 0x5d | 46 | #define INPUT_REPORT_ID 0x5d |
43 | #define FEATURE_KBD_REPORT_ID 0x5a | 47 | #define FEATURE_KBD_REPORT_ID 0x5a |
44 | |||
45 | #define INPUT_REPORT_SIZE 28 | ||
46 | #define FEATURE_KBD_REPORT_SIZE 16 | 48 | #define FEATURE_KBD_REPORT_SIZE 16 |
47 | 49 | ||
48 | #define SUPPORT_KBD_BACKLIGHT BIT(0) | 50 | #define SUPPORT_KBD_BACKLIGHT BIT(0) |
49 | 51 | ||
50 | #define MAX_CONTACTS 5 | ||
51 | |||
52 | #define MAX_X 2794 | ||
53 | #define MAX_Y 1758 | ||
54 | #define MAX_TOUCH_MAJOR 8 | 52 | #define MAX_TOUCH_MAJOR 8 |
55 | #define MAX_PRESSURE 128 | 53 | #define MAX_PRESSURE 128 |
56 | 54 | ||
57 | #define CONTACT_DATA_SIZE 5 | ||
58 | |||
59 | #define BTN_LEFT_MASK 0x01 | 55 | #define BTN_LEFT_MASK 0x01 |
60 | #define CONTACT_TOOL_TYPE_MASK 0x80 | 56 | #define CONTACT_TOOL_TYPE_MASK 0x80 |
61 | #define CONTACT_X_MSB_MASK 0xf0 | 57 | #define CONTACT_X_MSB_MASK 0xf0 |
@@ -70,6 +66,7 @@ MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad"); | |||
70 | #define QUIRK_NO_CONSUMER_USAGES BIT(4) | 66 | #define QUIRK_NO_CONSUMER_USAGES BIT(4) |
71 | #define QUIRK_USE_KBD_BACKLIGHT BIT(5) | 67 | #define QUIRK_USE_KBD_BACKLIGHT BIT(5) |
72 | #define QUIRK_T100_KEYBOARD BIT(6) | 68 | #define QUIRK_T100_KEYBOARD BIT(6) |
69 | #define QUIRK_T100CHI BIT(7) | ||
73 | 70 | ||
74 | #define I2C_KEYBOARD_QUIRKS (QUIRK_FIX_NOTEBOOK_REPORT | \ | 71 | #define I2C_KEYBOARD_QUIRKS (QUIRK_FIX_NOTEBOOK_REPORT | \ |
75 | QUIRK_NO_INIT_REPORTS | \ | 72 | QUIRK_NO_INIT_REPORTS | \ |
@@ -88,19 +85,62 @@ struct asus_kbd_leds { | |||
88 | bool removed; | 85 | bool removed; |
89 | }; | 86 | }; |
90 | 87 | ||
88 | struct asus_touchpad_info { | ||
89 | int max_x; | ||
90 | int max_y; | ||
91 | int res_x; | ||
92 | int res_y; | ||
93 | int contact_size; | ||
94 | int max_contacts; | ||
95 | }; | ||
96 | |||
91 | struct asus_drvdata { | 97 | struct asus_drvdata { |
92 | unsigned long quirks; | 98 | unsigned long quirks; |
93 | struct input_dev *input; | 99 | struct input_dev *input; |
94 | struct asus_kbd_leds *kbd_backlight; | 100 | struct asus_kbd_leds *kbd_backlight; |
101 | const struct asus_touchpad_info *tp; | ||
95 | bool enable_backlight; | 102 | bool enable_backlight; |
96 | }; | 103 | }; |
97 | 104 | ||
98 | static void asus_report_contact_down(struct input_dev *input, | 105 | static const struct asus_touchpad_info asus_i2c_tp = { |
106 | .max_x = 2794, | ||
107 | .max_y = 1758, | ||
108 | .contact_size = 5, | ||
109 | .max_contacts = 5, | ||
110 | }; | ||
111 | |||
112 | static const struct asus_touchpad_info asus_t100ta_tp = { | ||
113 | .max_x = 2240, | ||
114 | .max_y = 1120, | ||
115 | .res_x = 30, /* units/mm */ | ||
116 | .res_y = 27, /* units/mm */ | ||
117 | .contact_size = 5, | ||
118 | .max_contacts = 5, | ||
119 | }; | ||
120 | |||
121 | static const struct asus_touchpad_info asus_t100chi_tp = { | ||
122 | .max_x = 2640, | ||
123 | .max_y = 1320, | ||
124 | .res_x = 31, /* units/mm */ | ||
125 | .res_y = 29, /* units/mm */ | ||
126 | .contact_size = 3, | ||
127 | .max_contacts = 4, | ||
128 | }; | ||
129 | |||
130 | static void asus_report_contact_down(struct asus_drvdata *drvdat, | ||
99 | int toolType, u8 *data) | 131 | int toolType, u8 *data) |
100 | { | 132 | { |
101 | int touch_major, pressure; | 133 | struct input_dev *input = drvdat->input; |
102 | int x = (data[0] & CONTACT_X_MSB_MASK) << 4 | data[1]; | 134 | int touch_major, pressure, x, y; |
103 | int y = MAX_Y - ((data[0] & CONTACT_Y_MSB_MASK) << 8 | data[2]); | 135 | |
136 | x = (data[0] & CONTACT_X_MSB_MASK) << 4 | data[1]; | ||
137 | y = drvdat->tp->max_y - ((data[0] & CONTACT_Y_MSB_MASK) << 8 | data[2]); | ||
138 | |||
139 | input_report_abs(input, ABS_MT_POSITION_X, x); | ||
140 | input_report_abs(input, ABS_MT_POSITION_Y, y); | ||
141 | |||
142 | if (drvdat->tp->contact_size < 5) | ||
143 | return; | ||
104 | 144 | ||
105 | if (toolType == MT_TOOL_PALM) { | 145 | if (toolType == MT_TOOL_PALM) { |
106 | touch_major = MAX_TOUCH_MAJOR; | 146 | touch_major = MAX_TOUCH_MAJOR; |
@@ -110,19 +150,20 @@ static void asus_report_contact_down(struct input_dev *input, | |||
110 | pressure = data[4] & CONTACT_PRESSURE_MASK; | 150 | pressure = data[4] & CONTACT_PRESSURE_MASK; |
111 | } | 151 | } |
112 | 152 | ||
113 | input_report_abs(input, ABS_MT_POSITION_X, x); | ||
114 | input_report_abs(input, ABS_MT_POSITION_Y, y); | ||
115 | input_report_abs(input, ABS_MT_TOUCH_MAJOR, touch_major); | 153 | input_report_abs(input, ABS_MT_TOUCH_MAJOR, touch_major); |
116 | input_report_abs(input, ABS_MT_PRESSURE, pressure); | 154 | input_report_abs(input, ABS_MT_PRESSURE, pressure); |
117 | } | 155 | } |
118 | 156 | ||
119 | /* Required for Synaptics Palm Detection */ | 157 | /* Required for Synaptics Palm Detection */ |
120 | static void asus_report_tool_width(struct input_dev *input) | 158 | static void asus_report_tool_width(struct asus_drvdata *drvdat) |
121 | { | 159 | { |
122 | struct input_mt *mt = input->mt; | 160 | struct input_mt *mt = drvdat->input->mt; |
123 | struct input_mt_slot *oldest; | 161 | struct input_mt_slot *oldest; |
124 | int oldid, count, i; | 162 | int oldid, count, i; |
125 | 163 | ||
164 | if (drvdat->tp->contact_size < 5) | ||
165 | return; | ||
166 | |||
126 | oldest = NULL; | 167 | oldest = NULL; |
127 | oldid = mt->trkid; | 168 | oldid = mt->trkid; |
128 | count = 0; | 169 | count = 0; |
@@ -141,35 +182,42 @@ static void asus_report_tool_width(struct input_dev *input) | |||
141 | } | 182 | } |
142 | 183 | ||
143 | if (oldest) { | 184 | if (oldest) { |
144 | input_report_abs(input, ABS_TOOL_WIDTH, | 185 | input_report_abs(drvdat->input, ABS_TOOL_WIDTH, |
145 | input_mt_get_value(oldest, ABS_MT_TOUCH_MAJOR)); | 186 | input_mt_get_value(oldest, ABS_MT_TOUCH_MAJOR)); |
146 | } | 187 | } |
147 | } | 188 | } |
148 | 189 | ||
149 | static void asus_report_input(struct input_dev *input, u8 *data) | 190 | static int asus_report_input(struct asus_drvdata *drvdat, u8 *data, int size) |
150 | { | 191 | { |
151 | int i; | 192 | int i, toolType = MT_TOOL_FINGER; |
152 | u8 *contactData = data + 2; | 193 | u8 *contactData = data + 2; |
153 | 194 | ||
154 | for (i = 0; i < MAX_CONTACTS; i++) { | 195 | if (size != 3 + drvdat->tp->contact_size * drvdat->tp->max_contacts) |
196 | return 0; | ||
197 | |||
198 | for (i = 0; i < drvdat->tp->max_contacts; i++) { | ||
155 | bool down = !!(data[1] & BIT(i+3)); | 199 | bool down = !!(data[1] & BIT(i+3)); |
156 | int toolType = contactData[3] & CONTACT_TOOL_TYPE_MASK ? | 200 | |
201 | if (drvdat->tp->contact_size >= 5) | ||
202 | toolType = contactData[3] & CONTACT_TOOL_TYPE_MASK ? | ||
157 | MT_TOOL_PALM : MT_TOOL_FINGER; | 203 | MT_TOOL_PALM : MT_TOOL_FINGER; |
158 | 204 | ||
159 | input_mt_slot(input, i); | 205 | input_mt_slot(drvdat->input, i); |
160 | input_mt_report_slot_state(input, toolType, down); | 206 | input_mt_report_slot_state(drvdat->input, toolType, down); |
161 | 207 | ||
162 | if (down) { | 208 | if (down) { |
163 | asus_report_contact_down(input, toolType, contactData); | 209 | asus_report_contact_down(drvdat, toolType, contactData); |
164 | contactData += CONTACT_DATA_SIZE; | 210 | contactData += drvdat->tp->contact_size; |
165 | } | 211 | } |
166 | } | 212 | } |
167 | 213 | ||
168 | input_report_key(input, BTN_LEFT, data[1] & BTN_LEFT_MASK); | 214 | input_report_key(drvdat->input, BTN_LEFT, data[1] & BTN_LEFT_MASK); |
169 | asus_report_tool_width(input); | 215 | asus_report_tool_width(drvdat); |
216 | |||
217 | input_mt_sync_frame(drvdat->input); | ||
218 | input_sync(drvdat->input); | ||
170 | 219 | ||
171 | input_mt_sync_frame(input); | 220 | return 1; |
172 | input_sync(input); | ||
173 | } | 221 | } |
174 | 222 | ||
175 | static int asus_raw_event(struct hid_device *hdev, | 223 | static int asus_raw_event(struct hid_device *hdev, |
@@ -177,12 +225,8 @@ static int asus_raw_event(struct hid_device *hdev, | |||
177 | { | 225 | { |
178 | struct asus_drvdata *drvdata = hid_get_drvdata(hdev); | 226 | struct asus_drvdata *drvdata = hid_get_drvdata(hdev); |
179 | 227 | ||
180 | if (drvdata->quirks & QUIRK_IS_MULTITOUCH && | 228 | if (drvdata->tp && data[0] == INPUT_REPORT_ID) |
181 | data[0] == INPUT_REPORT_ID && | 229 | return asus_report_input(drvdata, data, size); |
182 | size == INPUT_REPORT_SIZE) { | ||
183 | asus_report_input(drvdata->input, data); | ||
184 | return 1; | ||
185 | } | ||
186 | 230 | ||
187 | return 0; | 231 | return 0; |
188 | } | 232 | } |
@@ -334,19 +378,35 @@ static int asus_input_configured(struct hid_device *hdev, struct hid_input *hi) | |||
334 | struct input_dev *input = hi->input; | 378 | struct input_dev *input = hi->input; |
335 | struct asus_drvdata *drvdata = hid_get_drvdata(hdev); | 379 | struct asus_drvdata *drvdata = hid_get_drvdata(hdev); |
336 | 380 | ||
337 | if (drvdata->quirks & QUIRK_IS_MULTITOUCH) { | 381 | /* T100CHI uses MULTI_INPUT, bind the touchpad to the mouse hid_input */ |
382 | if (drvdata->quirks & QUIRK_T100CHI && | ||
383 | hi->report->id != T100CHI_MOUSE_REPORT_ID) | ||
384 | return 0; | ||
385 | |||
386 | if (drvdata->tp) { | ||
338 | int ret; | 387 | int ret; |
339 | 388 | ||
340 | input_set_abs_params(input, ABS_MT_POSITION_X, 0, MAX_X, 0, 0); | 389 | input_set_abs_params(input, ABS_MT_POSITION_X, 0, |
341 | input_set_abs_params(input, ABS_MT_POSITION_Y, 0, MAX_Y, 0, 0); | 390 | drvdata->tp->max_x, 0, 0); |
342 | input_set_abs_params(input, ABS_TOOL_WIDTH, 0, MAX_TOUCH_MAJOR, 0, 0); | 391 | input_set_abs_params(input, ABS_MT_POSITION_Y, 0, |
343 | input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, MAX_TOUCH_MAJOR, 0, 0); | 392 | drvdata->tp->max_y, 0, 0); |
344 | input_set_abs_params(input, ABS_MT_PRESSURE, 0, MAX_PRESSURE, 0, 0); | 393 | input_abs_set_res(input, ABS_MT_POSITION_X, drvdata->tp->res_x); |
394 | input_abs_set_res(input, ABS_MT_POSITION_Y, drvdata->tp->res_y); | ||
395 | |||
396 | if (drvdata->tp->contact_size >= 5) { | ||
397 | input_set_abs_params(input, ABS_TOOL_WIDTH, 0, | ||
398 | MAX_TOUCH_MAJOR, 0, 0); | ||
399 | input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, | ||
400 | MAX_TOUCH_MAJOR, 0, 0); | ||
401 | input_set_abs_params(input, ABS_MT_PRESSURE, 0, | ||
402 | MAX_PRESSURE, 0, 0); | ||
403 | } | ||
345 | 404 | ||
346 | __set_bit(BTN_LEFT, input->keybit); | 405 | __set_bit(BTN_LEFT, input->keybit); |
347 | __set_bit(INPUT_PROP_BUTTONPAD, input->propbit); | 406 | __set_bit(INPUT_PROP_BUTTONPAD, input->propbit); |
348 | 407 | ||
349 | ret = input_mt_init_slots(input, MAX_CONTACTS, INPUT_MT_POINTER); | 408 | ret = input_mt_init_slots(input, drvdata->tp->max_contacts, |
409 | INPUT_MT_POINTER); | ||
350 | 410 | ||
351 | if (ret) { | 411 | if (ret) { |
352 | hid_err(hdev, "Asus input mt init slots failed: %d\n", ret); | 412 | hid_err(hdev, "Asus input mt init slots failed: %d\n", ret); |
@@ -378,6 +438,26 @@ static int asus_input_mapping(struct hid_device *hdev, | |||
378 | return -1; | 438 | return -1; |
379 | } | 439 | } |
380 | 440 | ||
441 | /* | ||
442 | * Ignore a bunch of bogus collections in the T100CHI descriptor. | ||
443 | * This avoids a bunch of non-functional hid_input devices getting | ||
444 | * created because of the T100CHI using HID_QUIRK_MULTI_INPUT. | ||
445 | */ | ||
446 | if (drvdata->quirks & QUIRK_T100CHI) { | ||
447 | if (field->application == (HID_UP_GENDESK | 0x0080) || | ||
448 | usage->hid == (HID_UP_GENDEVCTRLS | 0x0024) || | ||
449 | usage->hid == (HID_UP_GENDEVCTRLS | 0x0025) || | ||
450 | usage->hid == (HID_UP_GENDEVCTRLS | 0x0026)) | ||
451 | return -1; | ||
452 | /* | ||
453 | * We use the hid_input for the mouse report for the touchpad, | ||
454 | * keep the left button, to avoid the core removing it. | ||
455 | */ | ||
456 | if (field->application == HID_GD_MOUSE && | ||
457 | usage->hid != (HID_UP_BUTTON | 1)) | ||
458 | return -1; | ||
459 | } | ||
460 | |||
381 | /* ASUS-specific keyboard hotkeys */ | 461 | /* ASUS-specific keyboard hotkeys */ |
382 | if ((usage->hid & HID_USAGE_PAGE) == 0xff310000) { | 462 | if ((usage->hid & HID_USAGE_PAGE) == 0xff310000) { |
383 | set_bit(EV_REP, hi->input->evbit); | 463 | set_bit(EV_REP, hi->input->evbit); |
@@ -496,7 +576,7 @@ static int __maybe_unused asus_reset_resume(struct hid_device *hdev) | |||
496 | { | 576 | { |
497 | struct asus_drvdata *drvdata = hid_get_drvdata(hdev); | 577 | struct asus_drvdata *drvdata = hid_get_drvdata(hdev); |
498 | 578 | ||
499 | if (drvdata->quirks & QUIRK_IS_MULTITOUCH) | 579 | if (drvdata->tp) |
500 | return asus_start_multitouch(hdev); | 580 | return asus_start_multitouch(hdev); |
501 | 581 | ||
502 | return 0; | 582 | return 0; |
@@ -517,6 +597,28 @@ static int asus_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
517 | 597 | ||
518 | drvdata->quirks = id->driver_data; | 598 | drvdata->quirks = id->driver_data; |
519 | 599 | ||
600 | if (drvdata->quirks & QUIRK_IS_MULTITOUCH) | ||
601 | drvdata->tp = &asus_i2c_tp; | ||
602 | |||
603 | if (drvdata->quirks & QUIRK_T100_KEYBOARD) { | ||
604 | struct usb_interface *intf = to_usb_interface(hdev->dev.parent); | ||
605 | |||
606 | if (intf->altsetting->desc.bInterfaceNumber == T100_TPAD_INTF) { | ||
607 | drvdata->quirks = QUIRK_SKIP_INPUT_MAPPING; | ||
608 | drvdata->tp = &asus_t100ta_tp; | ||
609 | } | ||
610 | } | ||
611 | |||
612 | if (drvdata->quirks & QUIRK_T100CHI) { | ||
613 | /* | ||
614 | * All functionality is on a single HID interface and for | ||
615 | * userspace the touchpad must be a separate input_dev. | ||
616 | */ | ||
617 | hdev->quirks |= HID_QUIRK_MULTI_INPUT | | ||
618 | HID_QUIRK_NO_EMPTY_INPUT; | ||
619 | drvdata->tp = &asus_t100chi_tp; | ||
620 | } | ||
621 | |||
520 | if (drvdata->quirks & QUIRK_NO_INIT_REPORTS) | 622 | if (drvdata->quirks & QUIRK_NO_INIT_REPORTS) |
521 | hdev->quirks |= HID_QUIRK_NO_INIT_REPORTS; | 623 | hdev->quirks |= HID_QUIRK_NO_INIT_REPORTS; |
522 | 624 | ||
@@ -538,13 +640,13 @@ static int asus_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
538 | goto err_stop_hw; | 640 | goto err_stop_hw; |
539 | } | 641 | } |
540 | 642 | ||
541 | if (drvdata->quirks & QUIRK_IS_MULTITOUCH) { | 643 | if (drvdata->tp) { |
542 | drvdata->input->name = "Asus TouchPad"; | 644 | drvdata->input->name = "Asus TouchPad"; |
543 | } else { | 645 | } else { |
544 | drvdata->input->name = "Asus Keyboard"; | 646 | drvdata->input->name = "Asus Keyboard"; |
545 | } | 647 | } |
546 | 648 | ||
547 | if (drvdata->quirks & QUIRK_IS_MULTITOUCH) { | 649 | if (drvdata->tp) { |
548 | ret = asus_start_multitouch(hdev); | 650 | ret = asus_start_multitouch(hdev); |
549 | if (ret) | 651 | if (ret) |
550 | goto err_stop_hw; | 652 | goto err_stop_hw; |
@@ -578,11 +680,34 @@ static __u8 *asus_report_fixup(struct hid_device *hdev, __u8 *rdesc, | |||
578 | hid_info(hdev, "Fixing up Asus notebook report descriptor\n"); | 680 | hid_info(hdev, "Fixing up Asus notebook report descriptor\n"); |
579 | rdesc[55] = 0xdd; | 681 | rdesc[55] = 0xdd; |
580 | } | 682 | } |
683 | /* For the T100TA keyboard dock */ | ||
581 | if (drvdata->quirks & QUIRK_T100_KEYBOARD && | 684 | if (drvdata->quirks & QUIRK_T100_KEYBOARD && |
582 | *rsize == 76 && rdesc[73] == 0x81 && rdesc[74] == 0x01) { | 685 | *rsize == 76 && rdesc[73] == 0x81 && rdesc[74] == 0x01) { |
583 | hid_info(hdev, "Fixing up Asus T100 keyb report descriptor\n"); | 686 | hid_info(hdev, "Fixing up Asus T100 keyb report descriptor\n"); |
584 | rdesc[74] &= ~HID_MAIN_ITEM_CONSTANT; | 687 | rdesc[74] &= ~HID_MAIN_ITEM_CONSTANT; |
585 | } | 688 | } |
689 | /* For the T100CHI keyboard dock */ | ||
690 | if (drvdata->quirks & QUIRK_T100CHI && | ||
691 | *rsize == 403 && rdesc[388] == 0x09 && rdesc[389] == 0x76) { | ||
692 | /* | ||
693 | * Change Usage (76h) to Usage Minimum (00h), Usage Maximum | ||
694 | * (FFh) and clear the flags in the Input() byte. | ||
695 | * Note the descriptor has a bogus 0 byte at the end so we | ||
696 | * only need 1 extra byte. | ||
697 | */ | ||
698 | *rsize = 404; | ||
699 | rdesc = kmemdup(rdesc, *rsize, GFP_KERNEL); | ||
700 | if (!rdesc) | ||
701 | return NULL; | ||
702 | |||
703 | hid_info(hdev, "Fixing up T100CHI keyb report descriptor\n"); | ||
704 | memmove(rdesc + 392, rdesc + 390, 12); | ||
705 | rdesc[388] = 0x19; | ||
706 | rdesc[389] = 0x00; | ||
707 | rdesc[390] = 0x29; | ||
708 | rdesc[391] = 0xff; | ||
709 | rdesc[402] = 0x00; | ||
710 | } | ||
586 | 711 | ||
587 | return rdesc; | 712 | return rdesc; |
588 | } | 713 | } |
@@ -602,6 +727,9 @@ static const struct hid_device_id asus_devices[] = { | |||
602 | { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_ASUS_AK1D) }, | 727 | { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_ASUS_AK1D) }, |
603 | { HID_USB_DEVICE(USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_ASUS_MD_5110) }, | 728 | { HID_USB_DEVICE(USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_ASUS_MD_5110) }, |
604 | { HID_USB_DEVICE(USB_VENDOR_ID_JESS, USB_DEVICE_ID_ASUS_MD_5112) }, | 729 | { HID_USB_DEVICE(USB_VENDOR_ID_JESS, USB_DEVICE_ID_ASUS_MD_5112) }, |
730 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ASUSTEK, | ||
731 | USB_DEVICE_ID_ASUSTEK_T100CHI_KEYBOARD), QUIRK_T100CHI }, | ||
732 | |||
605 | { } | 733 | { } |
606 | }; | 734 | }; |
607 | MODULE_DEVICE_TABLE(hid, asus_devices); | 735 | MODULE_DEVICE_TABLE(hid, asus_devices); |
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 9017dcc14502..d946d561e064 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
@@ -1982,6 +1982,7 @@ static const struct hid_device_id hid_have_special_driver[] = { | |||
1982 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_T100_KEYBOARD) }, | 1982 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_T100_KEYBOARD) }, |
1983 | { HID_USB_DEVICE(USB_VENDOR_ID_JESS, USB_DEVICE_ID_ASUS_MD_5112) }, | 1983 | { HID_USB_DEVICE(USB_VENDOR_ID_JESS, USB_DEVICE_ID_ASUS_MD_5112) }, |
1984 | { HID_USB_DEVICE(USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_ASUS_MD_5110) }, | 1984 | { HID_USB_DEVICE(USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_ASUS_MD_5110) }, |
1985 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_T100CHI_KEYBOARD) }, | ||
1985 | #endif | 1986 | #endif |
1986 | #if IS_ENABLED(CONFIG_HID_AUREAL) | 1987 | #if IS_ENABLED(CONFIG_HID_AUREAL) |
1987 | { HID_USB_DEVICE(USB_VENDOR_ID_AUREAL, USB_DEVICE_ID_AUREAL_W01RN) }, | 1988 | { HID_USB_DEVICE(USB_VENDOR_ID_AUREAL, USB_DEVICE_ID_AUREAL_W01RN) }, |
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index f23f09ea67d1..40d56b42c83b 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h | |||
@@ -176,6 +176,7 @@ | |||
176 | #define USB_DEVICE_ID_ASUSTEK_LCM 0x1726 | 176 | #define USB_DEVICE_ID_ASUSTEK_LCM 0x1726 |
177 | #define USB_DEVICE_ID_ASUSTEK_LCM2 0x175b | 177 | #define USB_DEVICE_ID_ASUSTEK_LCM2 0x175b |
178 | #define USB_DEVICE_ID_ASUSTEK_T100_KEYBOARD 0x17e0 | 178 | #define USB_DEVICE_ID_ASUSTEK_T100_KEYBOARD 0x17e0 |
179 | #define USB_DEVICE_ID_ASUSTEK_T100CHI_KEYBOARD 0x8502 | ||
179 | #define USB_DEVICE_ID_ASUSTEK_I2C_KEYBOARD 0x8585 | 180 | #define USB_DEVICE_ID_ASUSTEK_I2C_KEYBOARD 0x8585 |
180 | #define USB_DEVICE_ID_ASUSTEK_I2C_TOUCHPAD 0x0101 | 181 | #define USB_DEVICE_ID_ASUSTEK_I2C_TOUCHPAD 0x0101 |
181 | #define USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD1 0x1854 | 182 | #define USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD1 0x1854 |