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