HID: asus: Add support for T100 touchpad
[platform/kernel/linux-rpi.git] / drivers / hid / hid-asus.c
1 /*
2  *  HID driver for Asus notebook built-in keyboard.
3  *  Fixes small logical maximum to match usage maximum.
4  *
5  *  Currently supported devices are:
6  *    EeeBook X205TA
7  *    VivoBook E200HA
8  *
9  *  Copyright (c) 2016 Yusuke Fujimaki <usk.fujimaki@gmail.com>
10  *
11  *  This module based on hid-ortek by
12  *  Copyright (c) 2010 Johnathon Harris <jmharris@gmail.com>
13  *  Copyright (c) 2011 Jiri Kosina
14  *
15  *  This module has been updated to add support for Asus i2c touchpad.
16  *
17  *  Copyright (c) 2016 Brendan McGrath <redmcg@redmandi.dyndns.org>
18  *  Copyright (c) 2016 Victor Vlasenko <victor.vlasenko@sysgears.com>
19  *  Copyright (c) 2016 Frederik Wenigwieser <frederik.wenigwieser@gmail.com>
20  */
21
22 /*
23  * This program is free software; you can redistribute it and/or modify it
24  * under the terms of the GNU General Public License as published by the Free
25  * Software Foundation; either version 2 of the License, or (at your option)
26  * any later version.
27  */
28
29 #include <linux/hid.h>
30 #include <linux/module.h>
31 #include <linux/input/mt.h>
32 #include <linux/usb.h> /* For to_usb_interface for T100 touchpad intf check */
33
34 #include "hid-ids.h"
35
36 MODULE_AUTHOR("Yusuke Fujimaki <usk.fujimaki@gmail.com>");
37 MODULE_AUTHOR("Brendan McGrath <redmcg@redmandi.dyndns.org>");
38 MODULE_AUTHOR("Victor Vlasenko <victor.vlasenko@sysgears.com>");
39 MODULE_AUTHOR("Frederik Wenigwieser <frederik.wenigwieser@gmail.com>");
40 MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad");
41
42 #define T100_TPAD_INTF 2
43
44 #define FEATURE_REPORT_ID 0x0d
45 #define INPUT_REPORT_ID 0x5d
46 #define FEATURE_KBD_REPORT_ID 0x5a
47
48 #define INPUT_REPORT_SIZE 28
49 #define FEATURE_KBD_REPORT_SIZE 16
50
51 #define SUPPORT_KBD_BACKLIGHT BIT(0)
52
53 #define MAX_CONTACTS 5
54
55 #define MAX_X 2794
56 #define MAX_X_T100 2240
57 #define MAX_Y 1758
58 #define MAX_TOUCH_MAJOR 8
59 #define MAX_PRESSURE 128
60
61 #define CONTACT_DATA_SIZE 5
62
63 #define BTN_LEFT_MASK 0x01
64 #define CONTACT_TOOL_TYPE_MASK 0x80
65 #define CONTACT_X_MSB_MASK 0xf0
66 #define CONTACT_Y_MSB_MASK 0x0f
67 #define CONTACT_TOUCH_MAJOR_MASK 0x07
68 #define CONTACT_PRESSURE_MASK 0x7f
69
70 #define QUIRK_FIX_NOTEBOOK_REPORT       BIT(0)
71 #define QUIRK_NO_INIT_REPORTS           BIT(1)
72 #define QUIRK_SKIP_INPUT_MAPPING        BIT(2)
73 #define QUIRK_IS_MULTITOUCH             BIT(3)
74 #define QUIRK_NO_CONSUMER_USAGES        BIT(4)
75 #define QUIRK_USE_KBD_BACKLIGHT         BIT(5)
76 #define QUIRK_T100_KEYBOARD             BIT(6)
77 #define QUIRK_T100_TOUCHPAD             BIT(7)
78
79 #define I2C_KEYBOARD_QUIRKS                     (QUIRK_FIX_NOTEBOOK_REPORT | \
80                                                  QUIRK_NO_INIT_REPORTS | \
81                                                  QUIRK_NO_CONSUMER_USAGES)
82 #define TOUCHPAD_QUIRKS                         (QUIRK_NO_INIT_REPORTS | \
83                                                  QUIRK_SKIP_INPUT_MAPPING | \
84                                                  QUIRK_IS_MULTITOUCH)
85
86 #define TRKID_SGN       ((TRKID_MAX + 1) >> 1)
87
88 struct asus_kbd_leds {
89         struct led_classdev cdev;
90         struct hid_device *hdev;
91         struct work_struct work;
92         unsigned int brightness;
93         bool removed;
94 };
95
96 struct asus_drvdata {
97         unsigned long quirks;
98         struct input_dev *input;
99         struct asus_kbd_leds *kbd_backlight;
100         bool enable_backlight;
101 };
102
103 static void asus_report_contact_down(struct input_dev *input,
104                 int toolType, u8 *data)
105 {
106         int touch_major, pressure;
107         int x = (data[0] & CONTACT_X_MSB_MASK) << 4 | data[1];
108         int y = MAX_Y - ((data[0] & CONTACT_Y_MSB_MASK) << 8 | data[2]);
109
110         if (toolType == MT_TOOL_PALM) {
111                 touch_major = MAX_TOUCH_MAJOR;
112                 pressure = MAX_PRESSURE;
113         } else {
114                 touch_major = (data[3] >> 4) & CONTACT_TOUCH_MAJOR_MASK;
115                 pressure = data[4] & CONTACT_PRESSURE_MASK;
116         }
117
118         input_report_abs(input, ABS_MT_POSITION_X, x);
119         input_report_abs(input, ABS_MT_POSITION_Y, y);
120         input_report_abs(input, ABS_MT_TOUCH_MAJOR, touch_major);
121         input_report_abs(input, ABS_MT_PRESSURE, pressure);
122 }
123
124 /* Required for Synaptics Palm Detection */
125 static void asus_report_tool_width(struct input_dev *input)
126 {
127         struct input_mt *mt = input->mt;
128         struct input_mt_slot *oldest;
129         int oldid, count, i;
130
131         oldest = NULL;
132         oldid = mt->trkid;
133         count = 0;
134
135         for (i = 0; i < mt->num_slots; ++i) {
136                 struct input_mt_slot *ps = &mt->slots[i];
137                 int id = input_mt_get_value(ps, ABS_MT_TRACKING_ID);
138
139                 if (id < 0)
140                         continue;
141                 if ((id - oldid) & TRKID_SGN) {
142                         oldest = ps;
143                         oldid = id;
144                 }
145                 count++;
146         }
147
148         if (oldest) {
149                 input_report_abs(input, ABS_TOOL_WIDTH,
150                         input_mt_get_value(oldest, ABS_MT_TOUCH_MAJOR));
151         }
152 }
153
154 static void asus_report_input(struct input_dev *input, u8 *data)
155 {
156         int i;
157         u8 *contactData = data + 2;
158
159         for (i = 0; i < MAX_CONTACTS; i++) {
160                 bool down = !!(data[1] & BIT(i+3));
161                 int toolType = contactData[3] & CONTACT_TOOL_TYPE_MASK ?
162                                                 MT_TOOL_PALM : MT_TOOL_FINGER;
163
164                 input_mt_slot(input, i);
165                 input_mt_report_slot_state(input, toolType, down);
166
167                 if (down) {
168                         asus_report_contact_down(input, toolType, contactData);
169                         contactData += CONTACT_DATA_SIZE;
170                 }
171         }
172
173         input_report_key(input, BTN_LEFT, data[1] & BTN_LEFT_MASK);
174         asus_report_tool_width(input);
175
176         input_mt_sync_frame(input);
177         input_sync(input);
178 }
179
180 static int asus_raw_event(struct hid_device *hdev,
181                 struct hid_report *report, u8 *data, int size)
182 {
183         struct asus_drvdata *drvdata = hid_get_drvdata(hdev);
184
185         if (drvdata->quirks & QUIRK_IS_MULTITOUCH &&
186                                          data[0] == INPUT_REPORT_ID &&
187                                                 size == INPUT_REPORT_SIZE) {
188                 asus_report_input(drvdata->input, data);
189                 return 1;
190         }
191
192         return 0;
193 }
194
195 static int asus_kbd_set_report(struct hid_device *hdev, u8 *buf, size_t buf_size)
196 {
197         unsigned char *dmabuf;
198         int ret;
199
200         dmabuf = kmemdup(buf, buf_size, GFP_KERNEL);
201         if (!dmabuf)
202                 return -ENOMEM;
203
204         ret = hid_hw_raw_request(hdev, FEATURE_KBD_REPORT_ID, dmabuf,
205                                  buf_size, HID_FEATURE_REPORT,
206                                  HID_REQ_SET_REPORT);
207         kfree(dmabuf);
208
209         return ret;
210 }
211
212 static int asus_kbd_init(struct hid_device *hdev)
213 {
214         u8 buf[] = { FEATURE_KBD_REPORT_ID, 0x41, 0x53, 0x55, 0x53, 0x20, 0x54,
215                      0x65, 0x63, 0x68, 0x2e, 0x49, 0x6e, 0x63, 0x2e, 0x00 };
216         int ret;
217
218         ret = asus_kbd_set_report(hdev, buf, sizeof(buf));
219         if (ret < 0)
220                 hid_err(hdev, "Asus failed to send init command: %d\n", ret);
221
222         return ret;
223 }
224
225 static int asus_kbd_get_functions(struct hid_device *hdev,
226                                   unsigned char *kbd_func)
227 {
228         u8 buf[] = { FEATURE_KBD_REPORT_ID, 0x05, 0x20, 0x31, 0x00, 0x08 };
229         u8 *readbuf;
230         int ret;
231
232         ret = asus_kbd_set_report(hdev, buf, sizeof(buf));
233         if (ret < 0) {
234                 hid_err(hdev, "Asus failed to send configuration command: %d\n", ret);
235                 return ret;
236         }
237
238         readbuf = kzalloc(FEATURE_KBD_REPORT_SIZE, GFP_KERNEL);
239         if (!readbuf)
240                 return -ENOMEM;
241
242         ret = hid_hw_raw_request(hdev, FEATURE_KBD_REPORT_ID, readbuf,
243                                  FEATURE_KBD_REPORT_SIZE, HID_FEATURE_REPORT,
244                                  HID_REQ_GET_REPORT);
245         if (ret < 0) {
246                 hid_err(hdev, "Asus failed to request functions: %d\n", ret);
247                 kfree(readbuf);
248                 return ret;
249         }
250
251         *kbd_func = readbuf[6];
252
253         kfree(readbuf);
254         return ret;
255 }
256
257 static void asus_kbd_backlight_set(struct led_classdev *led_cdev,
258                                    enum led_brightness brightness)
259 {
260         struct asus_kbd_leds *led = container_of(led_cdev, struct asus_kbd_leds,
261                                                  cdev);
262         if (led->brightness == brightness)
263                 return;
264
265         led->brightness = brightness;
266         schedule_work(&led->work);
267 }
268
269 static enum led_brightness asus_kbd_backlight_get(struct led_classdev *led_cdev)
270 {
271         struct asus_kbd_leds *led = container_of(led_cdev, struct asus_kbd_leds,
272                                                  cdev);
273
274         return led->brightness;
275 }
276
277 static void asus_kbd_backlight_work(struct work_struct *work)
278 {
279         struct asus_kbd_leds *led = container_of(work, struct asus_kbd_leds, work);
280         u8 buf[] = { FEATURE_KBD_REPORT_ID, 0xba, 0xc5, 0xc4, 0x00 };
281         int ret;
282
283         if (led->removed)
284                 return;
285
286         buf[4] = led->brightness;
287
288         ret = asus_kbd_set_report(led->hdev, buf, sizeof(buf));
289         if (ret < 0)
290                 hid_err(led->hdev, "Asus failed to set keyboard backlight: %d\n", ret);
291 }
292
293 static int asus_kbd_register_leds(struct hid_device *hdev)
294 {
295         struct asus_drvdata *drvdata = hid_get_drvdata(hdev);
296         unsigned char kbd_func;
297         int ret;
298
299         /* Initialize keyboard */
300         ret = asus_kbd_init(hdev);
301         if (ret < 0)
302                 return ret;
303
304         /* Get keyboard functions */
305         ret = asus_kbd_get_functions(hdev, &kbd_func);
306         if (ret < 0)
307                 return ret;
308
309         /* Check for backlight support */
310         if (!(kbd_func & SUPPORT_KBD_BACKLIGHT))
311                 return -ENODEV;
312
313         drvdata->kbd_backlight = devm_kzalloc(&hdev->dev,
314                                               sizeof(struct asus_kbd_leds),
315                                               GFP_KERNEL);
316         if (!drvdata->kbd_backlight)
317                 return -ENOMEM;
318
319         drvdata->kbd_backlight->removed = false;
320         drvdata->kbd_backlight->brightness = 0;
321         drvdata->kbd_backlight->hdev = hdev;
322         drvdata->kbd_backlight->cdev.name = "asus::kbd_backlight";
323         drvdata->kbd_backlight->cdev.max_brightness = 3;
324         drvdata->kbd_backlight->cdev.brightness_set = asus_kbd_backlight_set;
325         drvdata->kbd_backlight->cdev.brightness_get = asus_kbd_backlight_get;
326         INIT_WORK(&drvdata->kbd_backlight->work, asus_kbd_backlight_work);
327
328         ret = devm_led_classdev_register(&hdev->dev, &drvdata->kbd_backlight->cdev);
329         if (ret < 0) {
330                 /* No need to have this still around */
331                 devm_kfree(&hdev->dev, drvdata->kbd_backlight);
332         }
333
334         return ret;
335 }
336
337 static int asus_input_configured(struct hid_device *hdev, struct hid_input *hi)
338 {
339         struct input_dev *input = hi->input;
340         struct asus_drvdata *drvdata = hid_get_drvdata(hdev);
341
342         if (drvdata->quirks & QUIRK_IS_MULTITOUCH) {
343                 int ret;
344
345                 if (drvdata->quirks & QUIRK_T100_TOUCHPAD)
346                         input_set_abs_params(input, ABS_MT_POSITION_X, 0, MAX_X_T100, 0, 0);
347                 else
348                         input_set_abs_params(input, ABS_MT_POSITION_X, 0, MAX_X, 0, 0);
349                 input_set_abs_params(input, ABS_MT_POSITION_Y, 0, MAX_Y, 0, 0);
350                 input_set_abs_params(input, ABS_TOOL_WIDTH, 0, MAX_TOUCH_MAJOR, 0, 0);
351                 input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, MAX_TOUCH_MAJOR, 0, 0);
352                 input_set_abs_params(input, ABS_MT_PRESSURE, 0, MAX_PRESSURE, 0, 0);
353
354                 __set_bit(BTN_LEFT, input->keybit);
355                 __set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
356
357                 ret = input_mt_init_slots(input, MAX_CONTACTS, INPUT_MT_POINTER);
358
359                 if (ret) {
360                         hid_err(hdev, "Asus input mt init slots failed: %d\n", ret);
361                         return ret;
362                 }
363         }
364
365         drvdata->input = input;
366
367         if (drvdata->enable_backlight && asus_kbd_register_leds(hdev))
368                 hid_warn(hdev, "Failed to initialize backlight.\n");
369
370         return 0;
371 }
372
373 #define asus_map_key_clear(c)   hid_map_usage_clear(hi, usage, bit, \
374                                                     max, EV_KEY, (c))
375 static int asus_input_mapping(struct hid_device *hdev,
376                 struct hid_input *hi, struct hid_field *field,
377                 struct hid_usage *usage, unsigned long **bit,
378                 int *max)
379 {
380         struct asus_drvdata *drvdata = hid_get_drvdata(hdev);
381
382         if (drvdata->quirks & QUIRK_SKIP_INPUT_MAPPING) {
383                 /* Don't map anything from the HID report.
384                  * We do it all manually in asus_input_configured
385                  */
386                 return -1;
387         }
388
389         /* ASUS-specific keyboard hotkeys */
390         if ((usage->hid & HID_USAGE_PAGE) == 0xff310000) {
391                 set_bit(EV_REP, hi->input->evbit);
392                 switch (usage->hid & HID_USAGE) {
393                 case 0x10: asus_map_key_clear(KEY_BRIGHTNESSDOWN);      break;
394                 case 0x20: asus_map_key_clear(KEY_BRIGHTNESSUP);                break;
395                 case 0x35: asus_map_key_clear(KEY_DISPLAY_OFF);         break;
396                 case 0x6c: asus_map_key_clear(KEY_SLEEP);               break;
397                 case 0x82: asus_map_key_clear(KEY_CAMERA);              break;
398                 case 0x88: asus_map_key_clear(KEY_RFKILL);                      break;
399                 case 0xb5: asus_map_key_clear(KEY_CALC);                        break;
400                 case 0xc4: asus_map_key_clear(KEY_KBDILLUMUP);          break;
401                 case 0xc5: asus_map_key_clear(KEY_KBDILLUMDOWN);                break;
402
403                 /* ASUS touchpad toggle */
404                 case 0x6b: asus_map_key_clear(KEY_F21);                 break;
405
406                 /* ROG key */
407                 case 0x38: asus_map_key_clear(KEY_PROG1);               break;
408
409                 /* Fn+C ASUS Splendid */
410                 case 0xba: asus_map_key_clear(KEY_PROG2);               break;
411
412                 /* Fn+Space Power4Gear Hybrid */
413                 case 0x5c: asus_map_key_clear(KEY_PROG3);               break;
414
415                 default:
416                         /* ASUS lazily declares 256 usages, ignore the rest,
417                          * as some make the keyboard appear as a pointer device. */
418                         return -1;
419                 }
420
421                 /*
422                  * Check and enable backlight only on devices with UsagePage ==
423                  * 0xff31 to avoid initializing the keyboard firmware multiple
424                  * times on devices with multiple HID descriptors but same
425                  * PID/VID.
426                  */
427                 if (drvdata->quirks & QUIRK_USE_KBD_BACKLIGHT)
428                         drvdata->enable_backlight = true;
429
430                 return 1;
431         }
432
433         if ((usage->hid & HID_USAGE_PAGE) == HID_UP_MSVENDOR) {
434                 set_bit(EV_REP, hi->input->evbit);
435                 switch (usage->hid & HID_USAGE) {
436                 case 0xff01: asus_map_key_clear(BTN_1); break;
437                 case 0xff02: asus_map_key_clear(BTN_2); break;
438                 case 0xff03: asus_map_key_clear(BTN_3); break;
439                 case 0xff04: asus_map_key_clear(BTN_4); break;
440                 case 0xff05: asus_map_key_clear(BTN_5); break;
441                 case 0xff06: asus_map_key_clear(BTN_6); break;
442                 case 0xff07: asus_map_key_clear(BTN_7); break;
443                 case 0xff08: asus_map_key_clear(BTN_8); break;
444                 case 0xff09: asus_map_key_clear(BTN_9); break;
445                 case 0xff0a: asus_map_key_clear(BTN_A); break;
446                 case 0xff0b: asus_map_key_clear(BTN_B); break;
447                 case 0x00f1: asus_map_key_clear(KEY_WLAN);      break;
448                 case 0x00f2: asus_map_key_clear(KEY_BRIGHTNESSDOWN);    break;
449                 case 0x00f3: asus_map_key_clear(KEY_BRIGHTNESSUP);      break;
450                 case 0x00f4: asus_map_key_clear(KEY_DISPLAY_OFF);       break;
451                 case 0x00f7: asus_map_key_clear(KEY_CAMERA);    break;
452                 case 0x00f8: asus_map_key_clear(KEY_PROG1);     break;
453                 default:
454                         return 0;
455                 }
456
457                 return 1;
458         }
459
460         if (drvdata->quirks & QUIRK_NO_CONSUMER_USAGES &&
461                 (usage->hid & HID_USAGE_PAGE) == HID_UP_CONSUMER) {
462                 switch (usage->hid & HID_USAGE) {
463                 case 0xe2: /* Mute */
464                 case 0xe9: /* Volume up */
465                 case 0xea: /* Volume down */
466                         return 0;
467                 default:
468                         /* Ignore dummy Consumer usages which make the
469                          * keyboard incorrectly appear as a pointer device.
470                          */
471                         return -1;
472                 }
473         }
474
475         return 0;
476 }
477
478 static int asus_start_multitouch(struct hid_device *hdev)
479 {
480         int ret;
481         const unsigned char buf[] = { FEATURE_REPORT_ID, 0x00, 0x03, 0x01, 0x00 };
482         unsigned char *dmabuf = kmemdup(buf, sizeof(buf), GFP_KERNEL);
483
484         if (!dmabuf) {
485                 ret = -ENOMEM;
486                 hid_err(hdev, "Asus failed to alloc dma buf: %d\n", ret);
487                 return ret;
488         }
489
490         ret = hid_hw_raw_request(hdev, dmabuf[0], dmabuf, sizeof(buf),
491                                         HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
492
493         kfree(dmabuf);
494
495         if (ret != sizeof(buf)) {
496                 hid_err(hdev, "Asus failed to start multitouch: %d\n", ret);
497                 return ret;
498         }
499
500         return 0;
501 }
502
503 static int __maybe_unused asus_reset_resume(struct hid_device *hdev)
504 {
505         struct asus_drvdata *drvdata = hid_get_drvdata(hdev);
506
507         if (drvdata->quirks & QUIRK_IS_MULTITOUCH)
508                 return asus_start_multitouch(hdev);
509
510         return 0;
511 }
512
513 static int asus_probe(struct hid_device *hdev, const struct hid_device_id *id)
514 {
515         int ret;
516         struct asus_drvdata *drvdata;
517
518         drvdata = devm_kzalloc(&hdev->dev, sizeof(*drvdata), GFP_KERNEL);
519         if (drvdata == NULL) {
520                 hid_err(hdev, "Can't alloc Asus descriptor\n");
521                 return -ENOMEM;
522         }
523
524         hid_set_drvdata(hdev, drvdata);
525
526         drvdata->quirks = id->driver_data;
527
528         if (drvdata->quirks & QUIRK_T100_KEYBOARD) {
529                 struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
530
531                 if (intf->altsetting->desc.bInterfaceNumber == T100_TPAD_INTF)
532                         drvdata->quirks = TOUCHPAD_QUIRKS | QUIRK_T100_TOUCHPAD;
533         }
534
535         if (drvdata->quirks & QUIRK_NO_INIT_REPORTS)
536                 hdev->quirks |= HID_QUIRK_NO_INIT_REPORTS;
537
538         ret = hid_parse(hdev);
539         if (ret) {
540                 hid_err(hdev, "Asus hid parse failed: %d\n", ret);
541                 return ret;
542         }
543
544         ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
545         if (ret) {
546                 hid_err(hdev, "Asus hw start failed: %d\n", ret);
547                 return ret;
548         }
549
550         if (!drvdata->input) {
551                 hid_err(hdev, "Asus input not registered\n");
552                 ret = -ENOMEM;
553                 goto err_stop_hw;
554         }
555
556         if (drvdata->quirks & QUIRK_IS_MULTITOUCH) {
557                 drvdata->input->name = "Asus TouchPad";
558         } else {
559                 drvdata->input->name = "Asus Keyboard";
560         }
561
562         if (drvdata->quirks & QUIRK_IS_MULTITOUCH) {
563                 ret = asus_start_multitouch(hdev);
564                 if (ret)
565                         goto err_stop_hw;
566         }
567
568         return 0;
569 err_stop_hw:
570         hid_hw_stop(hdev);
571         return ret;
572 }
573
574 static void asus_remove(struct hid_device *hdev)
575 {
576         struct asus_drvdata *drvdata = hid_get_drvdata(hdev);
577
578         if (drvdata->kbd_backlight) {
579                 drvdata->kbd_backlight->removed = true;
580                 cancel_work_sync(&drvdata->kbd_backlight->work);
581         }
582
583         hid_hw_stop(hdev);
584 }
585
586 static __u8 *asus_report_fixup(struct hid_device *hdev, __u8 *rdesc,
587                 unsigned int *rsize)
588 {
589         struct asus_drvdata *drvdata = hid_get_drvdata(hdev);
590
591         if (drvdata->quirks & QUIRK_FIX_NOTEBOOK_REPORT &&
592                         *rsize >= 56 && rdesc[54] == 0x25 && rdesc[55] == 0x65) {
593                 hid_info(hdev, "Fixing up Asus notebook report descriptor\n");
594                 rdesc[55] = 0xdd;
595         }
596         if (drvdata->quirks & QUIRK_T100_KEYBOARD &&
597                  *rsize == 76 && rdesc[73] == 0x81 && rdesc[74] == 0x01) {
598                 hid_info(hdev, "Fixing up Asus T100 keyb report descriptor\n");
599                 rdesc[74] &= ~HID_MAIN_ITEM_CONSTANT;
600         }
601
602         return rdesc;
603 }
604
605 static const struct hid_device_id asus_devices[] = {
606         { HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK,
607                 USB_DEVICE_ID_ASUSTEK_I2C_KEYBOARD), I2C_KEYBOARD_QUIRKS},
608         { HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK,
609                 USB_DEVICE_ID_ASUSTEK_I2C_TOUCHPAD), TOUCHPAD_QUIRKS },
610         { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
611                 USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD1) },
612         { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
613                 USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD2), QUIRK_USE_KBD_BACKLIGHT },
614         { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
615                 USB_DEVICE_ID_ASUSTEK_T100_KEYBOARD),
616           QUIRK_T100_KEYBOARD | QUIRK_NO_CONSUMER_USAGES },
617         { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_ASUS_AK1D) },
618         { HID_USB_DEVICE(USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_ASUS_MD_5110) },
619         { HID_USB_DEVICE(USB_VENDOR_ID_JESS, USB_DEVICE_ID_ASUS_MD_5112) },
620         { }
621 };
622 MODULE_DEVICE_TABLE(hid, asus_devices);
623
624 static struct hid_driver asus_driver = {
625         .name                   = "asus",
626         .id_table               = asus_devices,
627         .report_fixup           = asus_report_fixup,
628         .probe                  = asus_probe,
629         .remove                 = asus_remove,
630         .input_mapping          = asus_input_mapping,
631         .input_configured       = asus_input_configured,
632 #ifdef CONFIG_PM
633         .reset_resume           = asus_reset_resume,
634 #endif
635         .raw_event              = asus_raw_event
636 };
637 module_hid_driver(asus_driver);
638
639 MODULE_LICENSE("GPL");