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