Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid

Pull HID updates from Jiri Kosina:
"Some highlights:

- hid-sony improvements of Sixaxis device support by Antonio Ospite
- hid-hyperv driven devices can now be used as wakeup source, by
Dexuan Cui
- hid-lenovo driver is now more generic and supports more devices, by
Jamie Lentin
- hid-huion now supports wider range of tablets, by Nikolai
Kondrashov
- other various unsorted fixes and device ID additions"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid: (30 commits)
HID: hyperv: register as a wakeup source
HID: sony: Default initialize all elements of the LED max_brightness array to 1
HID: huion: Fix sparse warnings
HID: usbhid: Use flag HID_DISCONNECTED when a usb device is removed
HID: ignore jabra gn9350e
HID: cp2112: add I2C mode
HID: use multi input quirk for 22b9:2968
HID: rmi: only bind the hid-rmi driver to the mouse interface of composite USB devices
HID: rmi: check that report ids exist in the report_id_hash before accessing their size
HID: lenovo: Add support for Compact (BT|USB) keyboard
HID: lenovo: Don't call function in condition, show error codes
HID: lenovo: Prepare support for adding other devices
HID: lenovo: Rename hid-lenovo-tpkbd to hid-lenovo
HID: huion: Handle tablets with UC-Logic vendor ID
HID: huion: Switch to generating report descriptor
HID: huion: Don't ignore other interfaces
HID: huion: Use "tablet" instead of specific model
HID: add quirk for 0x04d9:0xa096 device
HID: i2c-hid: call the hid driver's suspend and resume callbacks
HID: rmi: change logging level of log messages related to unexpected reports
...

+1196 -644
+12
Documentation/ABI/testing/sysfs-driver-hid-lenovo-tpkbd Documentation/ABI/testing/sysfs-driver-hid-lenovo
··· 4 4 Description: This controls if mouse clicks should be generated if the trackpoint is quickly pressed. How fast this press has to be 5 5 is being controlled by press_speed. 6 6 Values are 0 or 1. 7 + Applies to Thinkpad USB Keyboard with TrackPoint. 7 8 8 9 What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/dragging 9 10 Date: July 2011 10 11 Contact: linux-input@vger.kernel.org 11 12 Description: If this setting is enabled, it is possible to do dragging by pressing the trackpoint. This requires press_to_select to be enabled. 12 13 Values are 0 or 1. 14 + Applies to Thinkpad USB Keyboard with TrackPoint. 13 15 14 16 What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/release_to_select 15 17 Date: July 2011 16 18 Contact: linux-input@vger.kernel.org 17 19 Description: For details regarding this setting please refer to http://www.pc.ibm.com/ww/healthycomputing/trkpntb.html 18 20 Values are 0 or 1. 21 + Applies to Thinkpad USB Keyboard with TrackPoint. 19 22 20 23 What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/select_right 21 24 Date: July 2011 ··· 26 23 Description: This setting controls if the mouse click events generated by pressing the trackpoint (if press_to_select is enabled) generate 27 24 a left or right mouse button click. 28 25 Values are 0 or 1. 26 + Applies to Thinkpad USB Keyboard with TrackPoint. 29 27 30 28 What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/sensitivity 31 29 Date: July 2011 32 30 Contact: linux-input@vger.kernel.org 33 31 Description: This file contains the trackpoint sensitivity. 34 32 Values are decimal integers from 1 (lowest sensitivity) to 255 (highest sensitivity). 33 + Applies to Thinkpad USB Keyboard with TrackPoint. 35 34 36 35 What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/press_speed 37 36 Date: July 2011 38 37 Contact: linux-input@vger.kernel.org 39 38 Description: This setting controls how fast the trackpoint needs to be pressed to generate a mouse click if press_to_select is enabled. 40 39 Values are decimal integers from 1 (slowest) to 255 (fastest). 40 + Applies to Thinkpad USB Keyboard with TrackPoint. 41 41 42 + What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/fn_lock 43 + Date: July 2014 44 + Contact: linux-input@vger.kernel.org 45 + Description: This setting controls whether Fn Lock is enabled on the keyboard (i.e. if F1 is Mute or F1) 46 + Values are 0 or 1 47 + Applies to ThinkPad Compact (USB|Bluetooth) Keyboard with TrackPoint.
+10 -8
drivers/hid/Kconfig
··· 331 331 ---help--- 332 332 Support for LC-Power RC1000MCE RF remote control. 333 333 334 - config HID_LENOVO_TPKBD 335 - tristate "Lenovo ThinkPad USB Keyboard with TrackPoint" 334 + config HID_LENOVO 335 + tristate "Lenovo / Thinkpad devices" 336 336 depends on HID 337 337 select NEW_LEDS 338 338 select LEDS_CLASS 339 339 ---help--- 340 - Support for the Lenovo ThinkPad USB Keyboard with TrackPoint. 340 + Support for Lenovo devices that are not fully compliant with HID standard. 341 341 342 - Say Y here if you have a Lenovo ThinkPad USB Keyboard with TrackPoint 343 - and would like to use device-specific features like changing the 344 - sensitivity of the trackpoint, using the microphone mute button or 345 - controlling the mute and microphone mute LEDs. 342 + Say Y if you want support for the non-compliant features of the Lenovo 343 + Thinkpad standalone keyboards, e.g: 344 + - ThinkPad USB Keyboard with TrackPoint (supports extra LEDs and trackpoint 345 + configuration) 346 + - ThinkPad Compact Bluetooth Keyboard with TrackPoint (supports Fn keys) 347 + - ThinkPad Compact USB Keyboard with TrackPoint (supports Fn keys) 346 348 347 349 config HID_LOGITECH 348 350 tristate "Logitech devices" if EXPERT ··· 787 785 depends on HID 788 786 ---help--- 789 787 Support for Xin-Mo devices that are not fully compliant with the HID 790 - standard. Currently only supports the Xin-Mo Dual Arcade. Say Y here 788 + standard. Currently only supports the Xin-Mo Dual Arcade. Say Y here 791 789 if you have a Xin-Mo Dual Arcade controller. 792 790 793 791 config HID_ZEROPLUS
+1 -1
drivers/hid/Makefile
··· 59 59 obj-$(CONFIG_HID_KEYTOUCH) += hid-keytouch.o 60 60 obj-$(CONFIG_HID_KYE) += hid-kye.o 61 61 obj-$(CONFIG_HID_LCPOWER) += hid-lcpower.o 62 - obj-$(CONFIG_HID_LENOVO_TPKBD) += hid-lenovo-tpkbd.o 62 + obj-$(CONFIG_HID_LENOVO) += hid-lenovo.o 63 63 obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o 64 64 obj-$(CONFIG_HID_LOGITECH_DJ) += hid-logitech-dj.o 65 65 obj-$(CONFIG_HID_MAGICMOUSE) += hid-magicmouse.o
+8 -3
drivers/hid/hid-core.c
··· 783 783 * Vendor specific handlings 784 784 */ 785 785 if ((hid->vendor == USB_VENDOR_ID_SYNAPTICS) && 786 - (hid->group == HID_GROUP_GENERIC)) 786 + (hid->group == HID_GROUP_GENERIC) && 787 + /* only bind to the mouse interface of composite USB devices */ 788 + (hid->bus != BUS_USB || hid->type == HID_TYPE_USBMOUSE)) 787 789 /* hid-rmi should take care of them, not hid-generic */ 788 790 hid->group = HID_GROUP_RMI; 789 791 ··· 1784 1782 { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A070) }, 1785 1783 { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A072) }, 1786 1784 { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A081) }, 1787 - { HID_USB_DEVICE(USB_VENDOR_ID_HUION, USB_DEVICE_ID_HUION_580) }, 1785 + { HID_USB_DEVICE(USB_VENDOR_ID_HUION, USB_DEVICE_ID_HUION_TABLET) }, 1788 1786 { HID_USB_DEVICE(USB_VENDOR_ID_JESS2, USB_DEVICE_ID_JESS2_COLOR_RUMBLE_PAD) }, 1789 1787 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ION, USB_DEVICE_ID_ICADE) }, 1790 1788 { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) }, ··· 1798 1796 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X) }, 1799 1797 { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) }, 1800 1798 { HID_USB_DEVICE(USB_VENDOR_ID_LCPOWER, USB_DEVICE_ID_LCPOWER_LC1000 ) }, 1801 - #if IS_ENABLED(CONFIG_HID_LENOVO_TPKBD) 1799 + #if IS_ENABLED(CONFIG_HID_LENOVO) 1802 1800 { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) }, 1801 + { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CUSBKBD) }, 1802 + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CBTKBD) }, 1803 1803 #endif 1804 1804 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) }, 1805 1805 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) }, ··· 2270 2266 { HID_USB_DEVICE(USB_VENDOR_ID_IMATION, USB_DEVICE_ID_DISC_STAKKA) }, 2271 2267 { HID_USB_DEVICE(USB_VENDOR_ID_JABRA, USB_DEVICE_ID_JABRA_SPEAK_410) }, 2272 2268 { HID_USB_DEVICE(USB_VENDOR_ID_JABRA, USB_DEVICE_ID_JABRA_SPEAK_510) }, 2269 + { HID_USB_DEVICE(USB_VENDOR_ID_JABRA, USB_DEVICE_ID_JABRA_GN9350E) }, 2273 2270 { HID_USB_DEVICE(USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO) }, 2274 2271 { HID_USB_DEVICE(USB_VENDOR_ID_KWORLD, USB_DEVICE_ID_KWORLD_RADIO_FM700) }, 2275 2272 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_GPEN_560) },
+108 -3
drivers/hid/hid-cp2112.c
··· 240 240 u8 buf[5]; 241 241 int ret; 242 242 243 - cp2112_gpio_set(chip, offset, value); 244 - 245 243 ret = hid_hw_raw_request(hdev, CP2112_GPIO_CONFIG, buf, 246 244 sizeof(buf), HID_FEATURE_REPORT, 247 245 HID_REQ_GET_REPORT); ··· 257 259 hid_err(hdev, "error setting GPIO config: %d\n", ret); 258 260 return ret; 259 261 } 262 + 263 + /* 264 + * Set gpio value when output direction is already set, 265 + * as specified in AN495, Rev. 0.2, cpt. 4.4 266 + */ 267 + cp2112_gpio_set(chip, offset, value); 260 268 261 269 return 0; 262 270 } ··· 427 423 report->data[0] = command; 428 424 memcpy(&report->data[1], data, data_length); 429 425 return data_length + 4; 426 + } 427 + 428 + static int cp2112_i2c_write_req(void *buf, u8 slave_address, u8 *data, 429 + u8 data_length) 430 + { 431 + struct cp2112_write_req_report *report = buf; 432 + 433 + if (data_length > sizeof(report->data)) 434 + return -EINVAL; 435 + 436 + report->report = CP2112_DATA_WRITE_REQUEST; 437 + report->slave_address = slave_address << 1; 438 + report->length = data_length; 439 + memcpy(report->data, data, data_length); 440 + return data_length + 3; 441 + } 442 + 443 + static int cp2112_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, 444 + int num) 445 + { 446 + struct cp2112_device *dev = (struct cp2112_device *)adap->algo_data; 447 + struct hid_device *hdev = dev->hdev; 448 + u8 buf[64]; 449 + ssize_t count; 450 + unsigned int retries; 451 + int ret; 452 + 453 + hid_dbg(hdev, "I2C %d messages\n", num); 454 + 455 + if (num != 1) { 456 + hid_err(hdev, 457 + "Multi-message I2C transactions not supported\n"); 458 + return -EOPNOTSUPP; 459 + } 460 + 461 + if (msgs->flags & I2C_M_RD) 462 + count = cp2112_read_req(buf, msgs->addr, msgs->len); 463 + else 464 + count = cp2112_i2c_write_req(buf, msgs->addr, msgs->buf, 465 + msgs->len); 466 + 467 + if (count < 0) 468 + return count; 469 + 470 + ret = hid_hw_power(hdev, PM_HINT_FULLON); 471 + if (ret < 0) { 472 + hid_err(hdev, "power management error: %d\n", ret); 473 + return ret; 474 + } 475 + 476 + ret = cp2112_hid_output(hdev, buf, count, HID_OUTPUT_REPORT); 477 + if (ret < 0) { 478 + hid_warn(hdev, "Error starting transaction: %d\n", ret); 479 + goto power_normal; 480 + } 481 + 482 + for (retries = 0; retries < XFER_STATUS_RETRIES; ++retries) { 483 + ret = cp2112_xfer_status(dev); 484 + if (-EBUSY == ret) 485 + continue; 486 + if (ret < 0) 487 + goto power_normal; 488 + break; 489 + } 490 + 491 + if (XFER_STATUS_RETRIES <= retries) { 492 + hid_warn(hdev, "Transfer timed out, cancelling.\n"); 493 + buf[0] = CP2112_CANCEL_TRANSFER; 494 + buf[1] = 0x01; 495 + 496 + ret = cp2112_hid_output(hdev, buf, 2, HID_OUTPUT_REPORT); 497 + if (ret < 0) 498 + hid_warn(hdev, "Error cancelling transaction: %d\n", 499 + ret); 500 + 501 + ret = -ETIMEDOUT; 502 + goto power_normal; 503 + } 504 + 505 + if (!(msgs->flags & I2C_M_RD)) 506 + goto finish; 507 + 508 + ret = cp2112_read(dev, msgs->buf, msgs->len); 509 + if (ret < 0) 510 + goto power_normal; 511 + if (ret != msgs->len) { 512 + hid_warn(hdev, "short read: %d < %d\n", ret, msgs->len); 513 + ret = -EIO; 514 + goto power_normal; 515 + } 516 + 517 + finish: 518 + /* return the number of transferred messages */ 519 + ret = 1; 520 + 521 + power_normal: 522 + hid_hw_power(hdev, PM_HINT_NORMAL); 523 + hid_dbg(hdev, "I2C transfer finished: %d\n", ret); 524 + return ret; 430 525 } 431 526 432 527 static int cp2112_xfer(struct i2c_adapter *adap, u16 addr, ··· 694 591 695 592 static u32 cp2112_functionality(struct i2c_adapter *adap) 696 593 { 697 - return I2C_FUNC_SMBUS_BYTE | 594 + return I2C_FUNC_I2C | 595 + I2C_FUNC_SMBUS_BYTE | 698 596 I2C_FUNC_SMBUS_BYTE_DATA | 699 597 I2C_FUNC_SMBUS_WORD_DATA | 700 598 I2C_FUNC_SMBUS_BLOCK_DATA | ··· 705 601 } 706 602 707 603 static const struct i2c_algorithm smbus_algorithm = { 604 + .master_xfer = cp2112_i2c_xfer, 708 605 .smbus_xfer = cp2112_xfer, 709 606 .functionality = cp2112_functionality, 710 607 };
+177 -92
drivers/hid/hid-huion.c
··· 2 2 * HID driver for Huion devices not fully compliant with HID standard 3 3 * 4 4 * Copyright (c) 2013 Martin Rusko 5 + * Copyright (c) 2014 Nikolai Kondrashov 5 6 */ 6 7 7 8 /* ··· 16 15 #include <linux/hid.h> 17 16 #include <linux/module.h> 18 17 #include <linux/usb.h> 18 + #include <asm/unaligned.h> 19 19 #include "usbhid/usbhid.h" 20 20 21 21 #include "hid-ids.h" 22 22 23 - /* Original Huion 580 report descriptor size */ 24 - #define HUION_580_RDESC_ORIG_SIZE 177 23 + /* Report descriptor template placeholder head */ 24 + #define HUION_PH_HEAD 0xFE, 0xED, 0x1D 25 25 26 - /* Fixed Huion 580 report descriptor */ 27 - static __u8 huion_580_rdesc_fixed[] = { 28 - 0x05, 0x0D, /* Usage Page (Digitizer), */ 29 - 0x09, 0x02, /* Usage (Pen), */ 30 - 0xA1, 0x01, /* Collection (Application), */ 31 - 0x85, 0x07, /* Report ID (7), */ 32 - 0x09, 0x20, /* Usage (Stylus), */ 33 - 0xA0, /* Collection (Physical), */ 34 - 0x14, /* Logical Minimum (0), */ 35 - 0x25, 0x01, /* Logical Maximum (1), */ 36 - 0x75, 0x01, /* Report Size (1), */ 37 - 0x09, 0x42, /* Usage (Tip Switch), */ 38 - 0x09, 0x44, /* Usage (Barrel Switch), */ 39 - 0x09, 0x46, /* Usage (Tablet Pick), */ 40 - 0x95, 0x03, /* Report Count (3), */ 41 - 0x81, 0x02, /* Input (Variable), */ 42 - 0x95, 0x03, /* Report Count (3), */ 43 - 0x81, 0x03, /* Input (Constant, Variable), */ 44 - 0x09, 0x32, /* Usage (In Range), */ 45 - 0x95, 0x01, /* Report Count (1), */ 46 - 0x81, 0x02, /* Input (Variable), */ 47 - 0x95, 0x01, /* Report Count (1), */ 48 - 0x81, 0x03, /* Input (Constant, Variable), */ 49 - 0x75, 0x10, /* Report Size (16), */ 50 - 0x95, 0x01, /* Report Count (1), */ 51 - 0xA4, /* Push, */ 52 - 0x05, 0x01, /* Usage Page (Desktop), */ 53 - 0x65, 0x13, /* Unit (Inch), */ 54 - 0x55, 0xFD, /* Unit Exponent (-3), */ 55 - 0x34, /* Physical Minimum (0), */ 56 - 0x09, 0x30, /* Usage (X), */ 57 - 0x46, 0x40, 0x1F, /* Physical Maximum (8000), */ 58 - 0x26, 0x00, 0x7D, /* Logical Maximum (32000), */ 59 - 0x81, 0x02, /* Input (Variable), */ 60 - 0x09, 0x31, /* Usage (Y), */ 61 - 0x46, 0x88, 0x13, /* Physical Maximum (5000), */ 62 - 0x26, 0x20, 0x4E, /* Logical Maximum (20000), */ 63 - 0x81, 0x02, /* Input (Variable), */ 64 - 0xB4, /* Pop, */ 65 - 0x09, 0x30, /* Usage (Tip Pressure), */ 66 - 0x26, 0xFF, 0x07, /* Logical Maximum (2047), */ 67 - 0x81, 0x02, /* Input (Variable), */ 68 - 0xC0, /* End Collection, */ 69 - 0xC0 /* End Collection */ 26 + /* Report descriptor template placeholder IDs */ 27 + enum huion_ph_id { 28 + HUION_PH_ID_X_LM, 29 + HUION_PH_ID_X_PM, 30 + HUION_PH_ID_Y_LM, 31 + HUION_PH_ID_Y_PM, 32 + HUION_PH_ID_PRESSURE_LM, 33 + HUION_PH_ID_NUM 34 + }; 35 + 36 + /* Report descriptor template placeholder */ 37 + #define HUION_PH(_ID) HUION_PH_HEAD, HUION_PH_ID_##_ID 38 + 39 + /* Fixed report descriptor template */ 40 + static const __u8 huion_tablet_rdesc_template[] = { 41 + 0x05, 0x0D, /* Usage Page (Digitizer), */ 42 + 0x09, 0x02, /* Usage (Pen), */ 43 + 0xA1, 0x01, /* Collection (Application), */ 44 + 0x85, 0x07, /* Report ID (7), */ 45 + 0x09, 0x20, /* Usage (Stylus), */ 46 + 0xA0, /* Collection (Physical), */ 47 + 0x14, /* Logical Minimum (0), */ 48 + 0x25, 0x01, /* Logical Maximum (1), */ 49 + 0x75, 0x01, /* Report Size (1), */ 50 + 0x09, 0x42, /* Usage (Tip Switch), */ 51 + 0x09, 0x44, /* Usage (Barrel Switch), */ 52 + 0x09, 0x46, /* Usage (Tablet Pick), */ 53 + 0x95, 0x03, /* Report Count (3), */ 54 + 0x81, 0x02, /* Input (Variable), */ 55 + 0x95, 0x03, /* Report Count (3), */ 56 + 0x81, 0x03, /* Input (Constant, Variable), */ 57 + 0x09, 0x32, /* Usage (In Range), */ 58 + 0x95, 0x01, /* Report Count (1), */ 59 + 0x81, 0x02, /* Input (Variable), */ 60 + 0x95, 0x01, /* Report Count (1), */ 61 + 0x81, 0x03, /* Input (Constant, Variable), */ 62 + 0x75, 0x10, /* Report Size (16), */ 63 + 0x95, 0x01, /* Report Count (1), */ 64 + 0xA4, /* Push, */ 65 + 0x05, 0x01, /* Usage Page (Desktop), */ 66 + 0x65, 0x13, /* Unit (Inch), */ 67 + 0x55, 0xFD, /* Unit Exponent (-3), */ 68 + 0x34, /* Physical Minimum (0), */ 69 + 0x09, 0x30, /* Usage (X), */ 70 + 0x27, HUION_PH(X_LM), /* Logical Maximum (PLACEHOLDER), */ 71 + 0x47, HUION_PH(X_PM), /* Physical Maximum (PLACEHOLDER), */ 72 + 0x81, 0x02, /* Input (Variable), */ 73 + 0x09, 0x31, /* Usage (Y), */ 74 + 0x27, HUION_PH(Y_LM), /* Logical Maximum (PLACEHOLDER), */ 75 + 0x47, HUION_PH(Y_PM), /* Physical Maximum (PLACEHOLDER), */ 76 + 0x81, 0x02, /* Input (Variable), */ 77 + 0xB4, /* Pop, */ 78 + 0x09, 0x30, /* Usage (Tip Pressure), */ 79 + 0x27, 80 + HUION_PH(PRESSURE_LM), /* Logical Maximum (PLACEHOLDER), */ 81 + 0x81, 0x02, /* Input (Variable), */ 82 + 0xC0, /* End Collection, */ 83 + 0xC0 /* End Collection */ 84 + }; 85 + 86 + /* Driver data */ 87 + struct huion_drvdata { 88 + __u8 *rdesc; 89 + unsigned int rsize; 70 90 }; 71 91 72 92 static __u8 *huion_report_fixup(struct hid_device *hdev, __u8 *rdesc, 73 93 unsigned int *rsize) 74 94 { 95 + struct huion_drvdata *drvdata = hid_get_drvdata(hdev); 75 96 switch (hdev->product) { 76 - case USB_DEVICE_ID_HUION_580: 77 - if (*rsize == HUION_580_RDESC_ORIG_SIZE) { 78 - rdesc = huion_580_rdesc_fixed; 79 - *rsize = sizeof(huion_580_rdesc_fixed); 97 + case USB_DEVICE_ID_HUION_TABLET: 98 + if (drvdata->rdesc != NULL) { 99 + rdesc = drvdata->rdesc; 100 + *rsize = drvdata->rsize; 80 101 } 81 102 break; 82 103 } ··· 106 83 } 107 84 108 85 /** 109 - * Enable fully-functional tablet mode by reading special string 110 - * descriptor. 86 + * Enable fully-functional tablet mode and determine device parameters. 111 87 * 112 88 * @hdev: HID device 113 - * 114 - * The specific string descriptor and data were discovered by sniffing 115 - * the Windows driver traffic. 116 89 */ 117 90 static int huion_tablet_enable(struct hid_device *hdev) 118 91 { 119 92 int rc; 120 - char buf[22]; 93 + struct usb_device *usb_dev = hid_to_usb_dev(hdev); 94 + struct huion_drvdata *drvdata = hid_get_drvdata(hdev); 95 + __le16 buf[6]; 121 96 122 - rc = usb_string(hid_to_usb_dev(hdev), 0x64, buf, sizeof(buf)); 123 - if (rc < 0) 124 - return rc; 97 + /* 98 + * Read string descriptor containing tablet parameters. The specific 99 + * string descriptor and data were discovered by sniffing the Windows 100 + * driver traffic. 101 + * NOTE: This enables fully-functional tablet mode. 102 + */ 103 + rc = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), 104 + USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, 105 + (USB_DT_STRING << 8) + 0x64, 106 + 0x0409, buf, sizeof(buf), 107 + USB_CTRL_GET_TIMEOUT); 108 + if (rc == -EPIPE) 109 + hid_warn(hdev, "device parameters not found\n"); 110 + else if (rc < 0) 111 + hid_warn(hdev, "failed to get device parameters: %d\n", rc); 112 + else if (rc != sizeof(buf)) 113 + hid_warn(hdev, "invalid device parameters\n"); 114 + else { 115 + s32 params[HUION_PH_ID_NUM]; 116 + s32 resolution; 117 + __u8 *p; 118 + s32 v; 119 + 120 + /* Extract device parameters */ 121 + params[HUION_PH_ID_X_LM] = le16_to_cpu(buf[1]); 122 + params[HUION_PH_ID_Y_LM] = le16_to_cpu(buf[2]); 123 + params[HUION_PH_ID_PRESSURE_LM] = le16_to_cpu(buf[4]); 124 + resolution = le16_to_cpu(buf[5]); 125 + if (resolution == 0) { 126 + params[HUION_PH_ID_X_PM] = 0; 127 + params[HUION_PH_ID_Y_PM] = 0; 128 + } else { 129 + params[HUION_PH_ID_X_PM] = params[HUION_PH_ID_X_LM] * 130 + 1000 / resolution; 131 + params[HUION_PH_ID_Y_PM] = params[HUION_PH_ID_Y_LM] * 132 + 1000 / resolution; 133 + } 134 + 135 + /* Allocate fixed report descriptor */ 136 + drvdata->rdesc = devm_kmalloc(&hdev->dev, 137 + sizeof(huion_tablet_rdesc_template), 138 + GFP_KERNEL); 139 + if (drvdata->rdesc == NULL) { 140 + hid_err(hdev, "failed to allocate fixed rdesc\n"); 141 + return -ENOMEM; 142 + } 143 + drvdata->rsize = sizeof(huion_tablet_rdesc_template); 144 + 145 + /* Format fixed report descriptor */ 146 + memcpy(drvdata->rdesc, huion_tablet_rdesc_template, 147 + drvdata->rsize); 148 + for (p = drvdata->rdesc; 149 + p <= drvdata->rdesc + drvdata->rsize - 4;) { 150 + if (p[0] == 0xFE && p[1] == 0xED && p[2] == 0x1D && 151 + p[3] < sizeof(params)) { 152 + v = params[p[3]]; 153 + put_unaligned(cpu_to_le32(v), (s32 *)p); 154 + p += 4; 155 + } else { 156 + p++; 157 + } 158 + } 159 + } 125 160 126 161 return 0; 127 162 } 128 163 129 164 static int huion_probe(struct hid_device *hdev, const struct hid_device_id *id) 130 165 { 131 - int ret; 166 + int rc; 132 167 struct usb_interface *intf = to_usb_interface(hdev->dev.parent); 168 + struct huion_drvdata *drvdata; 133 169 134 - /* Ignore interfaces 1 (mouse) and 2 (keyboard) for Huion 580 tablet, 135 - * as they are not used 136 - */ 137 - switch (id->product) { 138 - case USB_DEVICE_ID_HUION_580: 139 - if (intf->cur_altsetting->desc.bInterfaceNumber != 0x00) 140 - return -ENODEV; 141 - break; 170 + /* Allocate and assign driver data */ 171 + drvdata = devm_kzalloc(&hdev->dev, sizeof(*drvdata), GFP_KERNEL); 172 + if (drvdata == NULL) { 173 + hid_err(hdev, "failed to allocate driver data\n"); 174 + return -ENOMEM; 142 175 } 143 - 144 - ret = hid_parse(hdev); 145 - if (ret) { 146 - hid_err(hdev, "parse failed\n"); 147 - goto err; 148 - } 149 - 150 - ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); 151 - if (ret) { 152 - hid_err(hdev, "hw start failed\n"); 153 - goto err; 154 - } 176 + hid_set_drvdata(hdev, drvdata); 155 177 156 178 switch (id->product) { 157 - case USB_DEVICE_ID_HUION_580: 158 - ret = huion_tablet_enable(hdev); 159 - if (ret) { 160 - hid_err(hdev, "tablet enabling failed\n"); 161 - goto enabling_err; 179 + case USB_DEVICE_ID_HUION_TABLET: 180 + /* If this is the pen interface */ 181 + if (intf->cur_altsetting->desc.bInterfaceNumber == 0) { 182 + rc = huion_tablet_enable(hdev); 183 + if (rc) { 184 + hid_err(hdev, "tablet enabling failed\n"); 185 + return rc; 186 + } 162 187 } 163 188 break; 164 189 } 165 190 191 + rc = hid_parse(hdev); 192 + if (rc) { 193 + hid_err(hdev, "parse failed\n"); 194 + return rc; 195 + } 196 + 197 + rc = hid_hw_start(hdev, HID_CONNECT_DEFAULT); 198 + if (rc) { 199 + hid_err(hdev, "hw start failed\n"); 200 + return rc; 201 + } 202 + 166 203 return 0; 167 - enabling_err: 168 - hid_hw_stop(hdev); 169 - err: 170 - return ret; 171 204 } 172 205 173 206 static int huion_raw_event(struct hid_device *hdev, struct hid_report *report, 174 207 u8 *data, int size) 175 208 { 176 - /* If this is a pen input report then invert the in-range bit */ 177 - if (report->type == HID_INPUT_REPORT && report->id == 0x07 && size >= 2) 209 + struct usb_interface *intf = to_usb_interface(hdev->dev.parent); 210 + 211 + /* If this is a pen input report */ 212 + if (intf->cur_altsetting->desc.bInterfaceNumber == 0 && 213 + report->type == HID_INPUT_REPORT && 214 + report->id == 0x07 && size >= 2) 215 + /* Invert the in-range bit */ 178 216 data[1] ^= 0x40; 179 217 180 218 return 0; 181 219 } 182 220 183 221 static const struct hid_device_id huion_devices[] = { 184 - { HID_USB_DEVICE(USB_VENDOR_ID_HUION, USB_DEVICE_ID_HUION_580) }, 222 + { HID_USB_DEVICE(USB_VENDOR_ID_HUION, USB_DEVICE_ID_HUION_TABLET) }, 223 + { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_HUION_TABLET) }, 185 224 { } 186 225 }; 187 226 MODULE_DEVICE_TABLE(hid, huion_devices);
+6
drivers/hid/hid-hyperv.c
··· 308 308 memcpy(input_dev->input_buf, input_report->buffer, len); 309 309 hid_input_report(input_dev->hid_device, HID_INPUT_REPORT, 310 310 input_dev->input_buf, len, 1); 311 + 312 + pm_wakeup_event(&input_dev->device->device, 0); 313 + 311 314 break; 312 315 default: 313 316 pr_err("unsupported hid msg type - type %d len %d", ··· 552 549 goto probe_err2; 553 550 } 554 551 552 + device_init_wakeup(&device->device, true); 553 + 555 554 input_dev->connected = true; 556 555 input_dev->init_complete = true; 557 556 ··· 576 571 { 577 572 struct mousevsc_dev *input_dev = hv_get_drvdata(dev); 578 573 574 + device_init_wakeup(&dev->device, false); 579 575 vmbus_close(dev->channel); 580 576 hid_hw_stop(input_dev->hid_device); 581 577 hid_destroy_device(input_dev->hid_device);
+5 -1
drivers/hid/hid-ids.h
··· 448 448 #define USB_DEVICE_ID_UGCI_FIGHTING 0x0030 449 449 450 450 #define USB_VENDOR_ID_HUION 0x256c 451 - #define USB_DEVICE_ID_HUION_580 0x006e 451 + #define USB_DEVICE_ID_HUION_TABLET 0x006e 452 452 453 453 #define USB_VENDOR_ID_IDEACOM 0x1cb6 454 454 #define USB_DEVICE_ID_IDEACOM_IDC6650 0x6650 ··· 479 479 #define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A070 0xa070 480 480 #define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A072 0xa072 481 481 #define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A081 0xa081 482 + #define USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD_A096 0xa096 482 483 483 484 #define USB_VENDOR_ID_IMATION 0x0718 484 485 #define USB_DEVICE_ID_DISC_STAKKA 0xd000 ··· 490 489 #define USB_VENDOR_ID_JABRA 0x0b0e 491 490 #define USB_DEVICE_ID_JABRA_SPEAK_410 0x0412 492 491 #define USB_DEVICE_ID_JABRA_SPEAK_510 0x0420 492 + #define USB_DEVICE_ID_JABRA_GN9350E 0x9350 493 493 494 494 #define USB_VENDOR_ID_JESS 0x0c45 495 495 #define USB_DEVICE_ID_JESS_YUREX 0x1010 ··· 563 561 564 562 #define USB_VENDOR_ID_LENOVO 0x17ef 565 563 #define USB_DEVICE_ID_LENOVO_TPKBD 0x6009 564 + #define USB_DEVICE_ID_LENOVO_CUSBKBD 0x6047 565 + #define USB_DEVICE_ID_LENOVO_CBTKBD 0x6048 566 566 567 567 #define USB_VENDOR_ID_LG 0x1fd2 568 568 #define USB_DEVICE_ID_LG_MULTITOUCH 0x0064
-462
drivers/hid/hid-lenovo-tpkbd.c
··· 1 - /* 2 - * HID driver for Lenovo ThinkPad USB Keyboard with TrackPoint 3 - * 4 - * Copyright (c) 2012 Bernhard Seibold 5 - */ 6 - 7 - /* 8 - * This program is free software; you can redistribute it and/or modify it 9 - * under the terms of the GNU General Public License as published by the Free 10 - * Software Foundation; either version 2 of the License, or (at your option) 11 - * any later version. 12 - */ 13 - 14 - #include <linux/module.h> 15 - #include <linux/sysfs.h> 16 - #include <linux/device.h> 17 - #include <linux/hid.h> 18 - #include <linux/input.h> 19 - #include <linux/leds.h> 20 - 21 - #include "hid-ids.h" 22 - 23 - /* This is only used for the trackpoint part of the driver, hence _tp */ 24 - struct tpkbd_data_pointer { 25 - int led_state; 26 - struct led_classdev led_mute; 27 - struct led_classdev led_micmute; 28 - int press_to_select; 29 - int dragging; 30 - int release_to_select; 31 - int select_right; 32 - int sensitivity; 33 - int press_speed; 34 - }; 35 - 36 - #define map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c)) 37 - 38 - static int tpkbd_input_mapping(struct hid_device *hdev, 39 - struct hid_input *hi, struct hid_field *field, 40 - struct hid_usage *usage, unsigned long **bit, int *max) 41 - { 42 - if (usage->hid == (HID_UP_BUTTON | 0x0010)) { 43 - /* mark the device as pointer */ 44 - hid_set_drvdata(hdev, (void *)1); 45 - map_key_clear(KEY_MICMUTE); 46 - return 1; 47 - } 48 - return 0; 49 - } 50 - 51 - #undef map_key_clear 52 - 53 - static int tpkbd_features_set(struct hid_device *hdev) 54 - { 55 - struct hid_report *report; 56 - struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev); 57 - 58 - report = hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[4]; 59 - 60 - report->field[0]->value[0] = data_pointer->press_to_select ? 0x01 : 0x02; 61 - report->field[0]->value[0] |= data_pointer->dragging ? 0x04 : 0x08; 62 - report->field[0]->value[0] |= data_pointer->release_to_select ? 0x10 : 0x20; 63 - report->field[0]->value[0] |= data_pointer->select_right ? 0x80 : 0x40; 64 - report->field[1]->value[0] = 0x03; // unknown setting, imitate windows driver 65 - report->field[2]->value[0] = data_pointer->sensitivity; 66 - report->field[3]->value[0] = data_pointer->press_speed; 67 - 68 - hid_hw_request(hdev, report, HID_REQ_SET_REPORT); 69 - return 0; 70 - } 71 - 72 - static ssize_t pointer_press_to_select_show(struct device *dev, 73 - struct device_attribute *attr, 74 - char *buf) 75 - { 76 - struct hid_device *hdev = container_of(dev, struct hid_device, dev); 77 - struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev); 78 - 79 - return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->press_to_select); 80 - } 81 - 82 - static ssize_t pointer_press_to_select_store(struct device *dev, 83 - struct device_attribute *attr, 84 - const char *buf, 85 - size_t count) 86 - { 87 - struct hid_device *hdev = container_of(dev, struct hid_device, dev); 88 - struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev); 89 - int value; 90 - 91 - if (kstrtoint(buf, 10, &value)) 92 - return -EINVAL; 93 - if (value < 0 || value > 1) 94 - return -EINVAL; 95 - 96 - data_pointer->press_to_select = value; 97 - tpkbd_features_set(hdev); 98 - 99 - return count; 100 - } 101 - 102 - static ssize_t pointer_dragging_show(struct device *dev, 103 - struct device_attribute *attr, 104 - char *buf) 105 - { 106 - struct hid_device *hdev = container_of(dev, struct hid_device, dev); 107 - struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev); 108 - 109 - return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->dragging); 110 - } 111 - 112 - static ssize_t pointer_dragging_store(struct device *dev, 113 - struct device_attribute *attr, 114 - const char *buf, 115 - size_t count) 116 - { 117 - struct hid_device *hdev = container_of(dev, struct hid_device, dev); 118 - struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev); 119 - int value; 120 - 121 - if (kstrtoint(buf, 10, &value)) 122 - return -EINVAL; 123 - if (value < 0 || value > 1) 124 - return -EINVAL; 125 - 126 - data_pointer->dragging = value; 127 - tpkbd_features_set(hdev); 128 - 129 - return count; 130 - } 131 - 132 - static ssize_t pointer_release_to_select_show(struct device *dev, 133 - struct device_attribute *attr, 134 - char *buf) 135 - { 136 - struct hid_device *hdev = container_of(dev, struct hid_device, dev); 137 - struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev); 138 - 139 - return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->release_to_select); 140 - } 141 - 142 - static ssize_t pointer_release_to_select_store(struct device *dev, 143 - struct device_attribute *attr, 144 - const char *buf, 145 - size_t count) 146 - { 147 - struct hid_device *hdev = container_of(dev, struct hid_device, dev); 148 - struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev); 149 - int value; 150 - 151 - if (kstrtoint(buf, 10, &value)) 152 - return -EINVAL; 153 - if (value < 0 || value > 1) 154 - return -EINVAL; 155 - 156 - data_pointer->release_to_select = value; 157 - tpkbd_features_set(hdev); 158 - 159 - return count; 160 - } 161 - 162 - static ssize_t pointer_select_right_show(struct device *dev, 163 - struct device_attribute *attr, 164 - char *buf) 165 - { 166 - struct hid_device *hdev = container_of(dev, struct hid_device, dev); 167 - struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev); 168 - 169 - return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->select_right); 170 - } 171 - 172 - static ssize_t pointer_select_right_store(struct device *dev, 173 - struct device_attribute *attr, 174 - const char *buf, 175 - size_t count) 176 - { 177 - struct hid_device *hdev = container_of(dev, struct hid_device, dev); 178 - struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev); 179 - int value; 180 - 181 - if (kstrtoint(buf, 10, &value)) 182 - return -EINVAL; 183 - if (value < 0 || value > 1) 184 - return -EINVAL; 185 - 186 - data_pointer->select_right = value; 187 - tpkbd_features_set(hdev); 188 - 189 - return count; 190 - } 191 - 192 - static ssize_t pointer_sensitivity_show(struct device *dev, 193 - struct device_attribute *attr, 194 - char *buf) 195 - { 196 - struct hid_device *hdev = container_of(dev, struct hid_device, dev); 197 - struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev); 198 - 199 - return snprintf(buf, PAGE_SIZE, "%u\n", 200 - data_pointer->sensitivity); 201 - } 202 - 203 - static ssize_t pointer_sensitivity_store(struct device *dev, 204 - struct device_attribute *attr, 205 - const char *buf, 206 - size_t count) 207 - { 208 - struct hid_device *hdev = container_of(dev, struct hid_device, dev); 209 - struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev); 210 - int value; 211 - 212 - if (kstrtoint(buf, 10, &value) || value < 1 || value > 255) 213 - return -EINVAL; 214 - 215 - data_pointer->sensitivity = value; 216 - tpkbd_features_set(hdev); 217 - 218 - return count; 219 - } 220 - 221 - static ssize_t pointer_press_speed_show(struct device *dev, 222 - struct device_attribute *attr, 223 - char *buf) 224 - { 225 - struct hid_device *hdev = container_of(dev, struct hid_device, dev); 226 - struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev); 227 - 228 - return snprintf(buf, PAGE_SIZE, "%u\n", 229 - data_pointer->press_speed); 230 - } 231 - 232 - static ssize_t pointer_press_speed_store(struct device *dev, 233 - struct device_attribute *attr, 234 - const char *buf, 235 - size_t count) 236 - { 237 - struct hid_device *hdev = container_of(dev, struct hid_device, dev); 238 - struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev); 239 - int value; 240 - 241 - if (kstrtoint(buf, 10, &value) || value < 1 || value > 255) 242 - return -EINVAL; 243 - 244 - data_pointer->press_speed = value; 245 - tpkbd_features_set(hdev); 246 - 247 - return count; 248 - } 249 - 250 - static struct device_attribute dev_attr_pointer_press_to_select = 251 - __ATTR(press_to_select, S_IWUSR | S_IRUGO, 252 - pointer_press_to_select_show, 253 - pointer_press_to_select_store); 254 - 255 - static struct device_attribute dev_attr_pointer_dragging = 256 - __ATTR(dragging, S_IWUSR | S_IRUGO, 257 - pointer_dragging_show, 258 - pointer_dragging_store); 259 - 260 - static struct device_attribute dev_attr_pointer_release_to_select = 261 - __ATTR(release_to_select, S_IWUSR | S_IRUGO, 262 - pointer_release_to_select_show, 263 - pointer_release_to_select_store); 264 - 265 - static struct device_attribute dev_attr_pointer_select_right = 266 - __ATTR(select_right, S_IWUSR | S_IRUGO, 267 - pointer_select_right_show, 268 - pointer_select_right_store); 269 - 270 - static struct device_attribute dev_attr_pointer_sensitivity = 271 - __ATTR(sensitivity, S_IWUSR | S_IRUGO, 272 - pointer_sensitivity_show, 273 - pointer_sensitivity_store); 274 - 275 - static struct device_attribute dev_attr_pointer_press_speed = 276 - __ATTR(press_speed, S_IWUSR | S_IRUGO, 277 - pointer_press_speed_show, 278 - pointer_press_speed_store); 279 - 280 - static struct attribute *tpkbd_attributes_pointer[] = { 281 - &dev_attr_pointer_press_to_select.attr, 282 - &dev_attr_pointer_dragging.attr, 283 - &dev_attr_pointer_release_to_select.attr, 284 - &dev_attr_pointer_select_right.attr, 285 - &dev_attr_pointer_sensitivity.attr, 286 - &dev_attr_pointer_press_speed.attr, 287 - NULL 288 - }; 289 - 290 - static const struct attribute_group tpkbd_attr_group_pointer = { 291 - .attrs = tpkbd_attributes_pointer, 292 - }; 293 - 294 - static enum led_brightness tpkbd_led_brightness_get( 295 - struct led_classdev *led_cdev) 296 - { 297 - struct device *dev = led_cdev->dev->parent; 298 - struct hid_device *hdev = container_of(dev, struct hid_device, dev); 299 - struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev); 300 - int led_nr = 0; 301 - 302 - if (led_cdev == &data_pointer->led_micmute) 303 - led_nr = 1; 304 - 305 - return data_pointer->led_state & (1 << led_nr) 306 - ? LED_FULL 307 - : LED_OFF; 308 - } 309 - 310 - static void tpkbd_led_brightness_set(struct led_classdev *led_cdev, 311 - enum led_brightness value) 312 - { 313 - struct device *dev = led_cdev->dev->parent; 314 - struct hid_device *hdev = container_of(dev, struct hid_device, dev); 315 - struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev); 316 - struct hid_report *report; 317 - int led_nr = 0; 318 - 319 - if (led_cdev == &data_pointer->led_micmute) 320 - led_nr = 1; 321 - 322 - if (value == LED_OFF) 323 - data_pointer->led_state &= ~(1 << led_nr); 324 - else 325 - data_pointer->led_state |= 1 << led_nr; 326 - 327 - report = hdev->report_enum[HID_OUTPUT_REPORT].report_id_hash[3]; 328 - report->field[0]->value[0] = (data_pointer->led_state >> 0) & 1; 329 - report->field[0]->value[1] = (data_pointer->led_state >> 1) & 1; 330 - hid_hw_request(hdev, report, HID_REQ_SET_REPORT); 331 - } 332 - 333 - static int tpkbd_probe_tp(struct hid_device *hdev) 334 - { 335 - struct device *dev = &hdev->dev; 336 - struct tpkbd_data_pointer *data_pointer; 337 - size_t name_sz = strlen(dev_name(dev)) + 16; 338 - char *name_mute, *name_micmute; 339 - int i; 340 - 341 - /* Validate required reports. */ 342 - for (i = 0; i < 4; i++) { 343 - if (!hid_validate_values(hdev, HID_FEATURE_REPORT, 4, i, 1)) 344 - return -ENODEV; 345 - } 346 - if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 3, 0, 2)) 347 - return -ENODEV; 348 - 349 - if (sysfs_create_group(&hdev->dev.kobj, 350 - &tpkbd_attr_group_pointer)) { 351 - hid_warn(hdev, "Could not create sysfs group\n"); 352 - } 353 - 354 - data_pointer = devm_kzalloc(&hdev->dev, 355 - sizeof(struct tpkbd_data_pointer), 356 - GFP_KERNEL); 357 - if (data_pointer == NULL) { 358 - hid_err(hdev, "Could not allocate memory for driver data\n"); 359 - return -ENOMEM; 360 - } 361 - 362 - // set same default values as windows driver 363 - data_pointer->sensitivity = 0xa0; 364 - data_pointer->press_speed = 0x38; 365 - 366 - name_mute = devm_kzalloc(&hdev->dev, name_sz, GFP_KERNEL); 367 - name_micmute = devm_kzalloc(&hdev->dev, name_sz, GFP_KERNEL); 368 - if (name_mute == NULL || name_micmute == NULL) { 369 - hid_err(hdev, "Could not allocate memory for led data\n"); 370 - return -ENOMEM; 371 - } 372 - snprintf(name_mute, name_sz, "%s:amber:mute", dev_name(dev)); 373 - snprintf(name_micmute, name_sz, "%s:amber:micmute", dev_name(dev)); 374 - 375 - hid_set_drvdata(hdev, data_pointer); 376 - 377 - data_pointer->led_mute.name = name_mute; 378 - data_pointer->led_mute.brightness_get = tpkbd_led_brightness_get; 379 - data_pointer->led_mute.brightness_set = tpkbd_led_brightness_set; 380 - data_pointer->led_mute.dev = dev; 381 - led_classdev_register(dev, &data_pointer->led_mute); 382 - 383 - data_pointer->led_micmute.name = name_micmute; 384 - data_pointer->led_micmute.brightness_get = tpkbd_led_brightness_get; 385 - data_pointer->led_micmute.brightness_set = tpkbd_led_brightness_set; 386 - data_pointer->led_micmute.dev = dev; 387 - led_classdev_register(dev, &data_pointer->led_micmute); 388 - 389 - tpkbd_features_set(hdev); 390 - 391 - return 0; 392 - } 393 - 394 - static int tpkbd_probe(struct hid_device *hdev, 395 - const struct hid_device_id *id) 396 - { 397 - int ret; 398 - 399 - ret = hid_parse(hdev); 400 - if (ret) { 401 - hid_err(hdev, "hid_parse failed\n"); 402 - goto err; 403 - } 404 - 405 - ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); 406 - if (ret) { 407 - hid_err(hdev, "hid_hw_start failed\n"); 408 - goto err; 409 - } 410 - 411 - if (hid_get_drvdata(hdev)) { 412 - hid_set_drvdata(hdev, NULL); 413 - ret = tpkbd_probe_tp(hdev); 414 - if (ret) 415 - goto err_hid; 416 - } 417 - 418 - return 0; 419 - err_hid: 420 - hid_hw_stop(hdev); 421 - err: 422 - return ret; 423 - } 424 - 425 - static void tpkbd_remove_tp(struct hid_device *hdev) 426 - { 427 - struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev); 428 - 429 - sysfs_remove_group(&hdev->dev.kobj, 430 - &tpkbd_attr_group_pointer); 431 - 432 - led_classdev_unregister(&data_pointer->led_micmute); 433 - led_classdev_unregister(&data_pointer->led_mute); 434 - 435 - hid_set_drvdata(hdev, NULL); 436 - } 437 - 438 - static void tpkbd_remove(struct hid_device *hdev) 439 - { 440 - if (hid_get_drvdata(hdev)) 441 - tpkbd_remove_tp(hdev); 442 - 443 - hid_hw_stop(hdev); 444 - } 445 - 446 - static const struct hid_device_id tpkbd_devices[] = { 447 - { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) }, 448 - { } 449 - }; 450 - 451 - MODULE_DEVICE_TABLE(hid, tpkbd_devices); 452 - 453 - static struct hid_driver tpkbd_driver = { 454 - .name = "lenovo_tpkbd", 455 - .id_table = tpkbd_devices, 456 - .input_mapping = tpkbd_input_mapping, 457 - .probe = tpkbd_probe, 458 - .remove = tpkbd_remove, 459 - }; 460 - module_hid_driver(tpkbd_driver); 461 - 462 - MODULE_LICENSE("GPL");
+708
drivers/hid/hid-lenovo.c
··· 1 + /* 2 + * HID driver for Lenovo: 3 + * - ThinkPad USB Keyboard with TrackPoint (tpkbd) 4 + * - ThinkPad Compact Bluetooth Keyboard with TrackPoint (cptkbd) 5 + * - ThinkPad Compact USB Keyboard with TrackPoint (cptkbd) 6 + * 7 + * Copyright (c) 2012 Bernhard Seibold 8 + * Copyright (c) 2014 Jamie Lentin <jm@lentin.co.uk> 9 + */ 10 + 11 + /* 12 + * This program is free software; you can redistribute it and/or modify it 13 + * under the terms of the GNU General Public License as published by the Free 14 + * Software Foundation; either version 2 of the License, or (at your option) 15 + * any later version. 16 + */ 17 + 18 + #include <linux/module.h> 19 + #include <linux/sysfs.h> 20 + #include <linux/device.h> 21 + #include <linux/hid.h> 22 + #include <linux/input.h> 23 + #include <linux/leds.h> 24 + 25 + #include "hid-ids.h" 26 + 27 + struct lenovo_drvdata_tpkbd { 28 + int led_state; 29 + struct led_classdev led_mute; 30 + struct led_classdev led_micmute; 31 + int press_to_select; 32 + int dragging; 33 + int release_to_select; 34 + int select_right; 35 + int sensitivity; 36 + int press_speed; 37 + }; 38 + 39 + struct lenovo_drvdata_cptkbd { 40 + bool fn_lock; 41 + }; 42 + 43 + #define map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c)) 44 + 45 + static int lenovo_input_mapping_tpkbd(struct hid_device *hdev, 46 + struct hid_input *hi, struct hid_field *field, 47 + struct hid_usage *usage, unsigned long **bit, int *max) 48 + { 49 + if (usage->hid == (HID_UP_BUTTON | 0x0010)) { 50 + /* This sub-device contains trackpoint, mark it */ 51 + hid_set_drvdata(hdev, (void *)1); 52 + map_key_clear(KEY_MICMUTE); 53 + return 1; 54 + } 55 + return 0; 56 + } 57 + 58 + static int lenovo_input_mapping_cptkbd(struct hid_device *hdev, 59 + struct hid_input *hi, struct hid_field *field, 60 + struct hid_usage *usage, unsigned long **bit, int *max) 61 + { 62 + /* HID_UP_LNVENDOR = USB, HID_UP_MSVENDOR = BT */ 63 + if ((usage->hid & HID_USAGE_PAGE) == HID_UP_MSVENDOR || 64 + (usage->hid & HID_USAGE_PAGE) == HID_UP_LNVENDOR) { 65 + set_bit(EV_REP, hi->input->evbit); 66 + switch (usage->hid & HID_USAGE) { 67 + case 0x00f1: /* Fn-F4: Mic mute */ 68 + map_key_clear(KEY_MICMUTE); 69 + return 1; 70 + case 0x00f2: /* Fn-F5: Brightness down */ 71 + map_key_clear(KEY_BRIGHTNESSDOWN); 72 + return 1; 73 + case 0x00f3: /* Fn-F6: Brightness up */ 74 + map_key_clear(KEY_BRIGHTNESSUP); 75 + return 1; 76 + case 0x00f4: /* Fn-F7: External display (projector) */ 77 + map_key_clear(KEY_SWITCHVIDEOMODE); 78 + return 1; 79 + case 0x00f5: /* Fn-F8: Wireless */ 80 + map_key_clear(KEY_WLAN); 81 + return 1; 82 + case 0x00f6: /* Fn-F9: Control panel */ 83 + map_key_clear(KEY_CONFIG); 84 + return 1; 85 + case 0x00f8: /* Fn-F11: View open applications (3 boxes) */ 86 + map_key_clear(KEY_SCALE); 87 + return 1; 88 + case 0x00fa: /* Fn-Esc: Fn-lock toggle */ 89 + map_key_clear(KEY_FN_ESC); 90 + return 1; 91 + case 0x00fb: /* Fn-F12: Open My computer (6 boxes) USB-only */ 92 + /* NB: This mapping is invented in raw_event below */ 93 + map_key_clear(KEY_FILE); 94 + return 1; 95 + } 96 + } 97 + 98 + return 0; 99 + } 100 + 101 + static int lenovo_input_mapping(struct hid_device *hdev, 102 + struct hid_input *hi, struct hid_field *field, 103 + struct hid_usage *usage, unsigned long **bit, int *max) 104 + { 105 + switch (hdev->product) { 106 + case USB_DEVICE_ID_LENOVO_TPKBD: 107 + return lenovo_input_mapping_tpkbd(hdev, hi, field, 108 + usage, bit, max); 109 + case USB_DEVICE_ID_LENOVO_CUSBKBD: 110 + case USB_DEVICE_ID_LENOVO_CBTKBD: 111 + return lenovo_input_mapping_cptkbd(hdev, hi, field, 112 + usage, bit, max); 113 + default: 114 + return 0; 115 + } 116 + } 117 + 118 + #undef map_key_clear 119 + 120 + /* Send a config command to the keyboard */ 121 + static int lenovo_send_cmd_cptkbd(struct hid_device *hdev, 122 + unsigned char byte2, unsigned char byte3) 123 + { 124 + int ret; 125 + unsigned char buf[] = {0x18, byte2, byte3}; 126 + 127 + switch (hdev->product) { 128 + case USB_DEVICE_ID_LENOVO_CUSBKBD: 129 + ret = hid_hw_raw_request(hdev, 0x13, buf, sizeof(buf), 130 + HID_FEATURE_REPORT, HID_REQ_SET_REPORT); 131 + break; 132 + case USB_DEVICE_ID_LENOVO_CBTKBD: 133 + ret = hid_hw_output_report(hdev, buf, sizeof(buf)); 134 + break; 135 + default: 136 + ret = -EINVAL; 137 + break; 138 + } 139 + 140 + return ret < 0 ? ret : 0; /* BT returns 0, USB returns sizeof(buf) */ 141 + } 142 + 143 + static void lenovo_features_set_cptkbd(struct hid_device *hdev) 144 + { 145 + int ret; 146 + struct lenovo_drvdata_cptkbd *cptkbd_data = hid_get_drvdata(hdev); 147 + 148 + ret = lenovo_send_cmd_cptkbd(hdev, 0x05, cptkbd_data->fn_lock); 149 + if (ret) 150 + hid_err(hdev, "Fn-lock setting failed: %d\n", ret); 151 + } 152 + 153 + static ssize_t attr_fn_lock_show_cptkbd(struct device *dev, 154 + struct device_attribute *attr, 155 + char *buf) 156 + { 157 + struct hid_device *hdev = container_of(dev, struct hid_device, dev); 158 + struct lenovo_drvdata_cptkbd *cptkbd_data = hid_get_drvdata(hdev); 159 + 160 + return snprintf(buf, PAGE_SIZE, "%u\n", cptkbd_data->fn_lock); 161 + } 162 + 163 + static ssize_t attr_fn_lock_store_cptkbd(struct device *dev, 164 + struct device_attribute *attr, 165 + const char *buf, 166 + size_t count) 167 + { 168 + struct hid_device *hdev = container_of(dev, struct hid_device, dev); 169 + struct lenovo_drvdata_cptkbd *cptkbd_data = hid_get_drvdata(hdev); 170 + int value; 171 + 172 + if (kstrtoint(buf, 10, &value)) 173 + return -EINVAL; 174 + if (value < 0 || value > 1) 175 + return -EINVAL; 176 + 177 + cptkbd_data->fn_lock = !!value; 178 + lenovo_features_set_cptkbd(hdev); 179 + 180 + return count; 181 + } 182 + 183 + static struct device_attribute dev_attr_fn_lock_cptkbd = 184 + __ATTR(fn_lock, S_IWUSR | S_IRUGO, 185 + attr_fn_lock_show_cptkbd, 186 + attr_fn_lock_store_cptkbd); 187 + 188 + static struct attribute *lenovo_attributes_cptkbd[] = { 189 + &dev_attr_fn_lock_cptkbd.attr, 190 + NULL 191 + }; 192 + 193 + static const struct attribute_group lenovo_attr_group_cptkbd = { 194 + .attrs = lenovo_attributes_cptkbd, 195 + }; 196 + 197 + static int lenovo_raw_event(struct hid_device *hdev, 198 + struct hid_report *report, u8 *data, int size) 199 + { 200 + /* 201 + * Compact USB keyboard's Fn-F12 report holds down many other keys, and 202 + * its own key is outside the usage page range. Remove extra 203 + * keypresses and remap to inside usage page. 204 + */ 205 + if (unlikely(hdev->product == USB_DEVICE_ID_LENOVO_CUSBKBD 206 + && size == 3 207 + && data[0] == 0x15 208 + && data[1] == 0x94 209 + && data[2] == 0x01)) { 210 + data[1] = 0x0; 211 + data[2] = 0x4; 212 + } 213 + 214 + return 0; 215 + } 216 + 217 + static int lenovo_features_set_tpkbd(struct hid_device *hdev) 218 + { 219 + struct hid_report *report; 220 + struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); 221 + 222 + report = hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[4]; 223 + 224 + report->field[0]->value[0] = data_pointer->press_to_select ? 0x01 : 0x02; 225 + report->field[0]->value[0] |= data_pointer->dragging ? 0x04 : 0x08; 226 + report->field[0]->value[0] |= data_pointer->release_to_select ? 0x10 : 0x20; 227 + report->field[0]->value[0] |= data_pointer->select_right ? 0x80 : 0x40; 228 + report->field[1]->value[0] = 0x03; // unknown setting, imitate windows driver 229 + report->field[2]->value[0] = data_pointer->sensitivity; 230 + report->field[3]->value[0] = data_pointer->press_speed; 231 + 232 + hid_hw_request(hdev, report, HID_REQ_SET_REPORT); 233 + return 0; 234 + } 235 + 236 + static ssize_t attr_press_to_select_show_tpkbd(struct device *dev, 237 + struct device_attribute *attr, 238 + char *buf) 239 + { 240 + struct hid_device *hdev = container_of(dev, struct hid_device, dev); 241 + struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); 242 + 243 + return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->press_to_select); 244 + } 245 + 246 + static ssize_t attr_press_to_select_store_tpkbd(struct device *dev, 247 + struct device_attribute *attr, 248 + const char *buf, 249 + size_t count) 250 + { 251 + struct hid_device *hdev = container_of(dev, struct hid_device, dev); 252 + struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); 253 + int value; 254 + 255 + if (kstrtoint(buf, 10, &value)) 256 + return -EINVAL; 257 + if (value < 0 || value > 1) 258 + return -EINVAL; 259 + 260 + data_pointer->press_to_select = value; 261 + lenovo_features_set_tpkbd(hdev); 262 + 263 + return count; 264 + } 265 + 266 + static ssize_t attr_dragging_show_tpkbd(struct device *dev, 267 + struct device_attribute *attr, 268 + char *buf) 269 + { 270 + struct hid_device *hdev = container_of(dev, struct hid_device, dev); 271 + struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); 272 + 273 + return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->dragging); 274 + } 275 + 276 + static ssize_t attr_dragging_store_tpkbd(struct device *dev, 277 + struct device_attribute *attr, 278 + const char *buf, 279 + size_t count) 280 + { 281 + struct hid_device *hdev = container_of(dev, struct hid_device, dev); 282 + struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); 283 + int value; 284 + 285 + if (kstrtoint(buf, 10, &value)) 286 + return -EINVAL; 287 + if (value < 0 || value > 1) 288 + return -EINVAL; 289 + 290 + data_pointer->dragging = value; 291 + lenovo_features_set_tpkbd(hdev); 292 + 293 + return count; 294 + } 295 + 296 + static ssize_t attr_release_to_select_show_tpkbd(struct device *dev, 297 + struct device_attribute *attr, 298 + char *buf) 299 + { 300 + struct hid_device *hdev = container_of(dev, struct hid_device, dev); 301 + struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); 302 + 303 + return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->release_to_select); 304 + } 305 + 306 + static ssize_t attr_release_to_select_store_tpkbd(struct device *dev, 307 + struct device_attribute *attr, 308 + const char *buf, 309 + size_t count) 310 + { 311 + struct hid_device *hdev = container_of(dev, struct hid_device, dev); 312 + struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); 313 + int value; 314 + 315 + if (kstrtoint(buf, 10, &value)) 316 + return -EINVAL; 317 + if (value < 0 || value > 1) 318 + return -EINVAL; 319 + 320 + data_pointer->release_to_select = value; 321 + lenovo_features_set_tpkbd(hdev); 322 + 323 + return count; 324 + } 325 + 326 + static ssize_t attr_select_right_show_tpkbd(struct device *dev, 327 + struct device_attribute *attr, 328 + char *buf) 329 + { 330 + struct hid_device *hdev = container_of(dev, struct hid_device, dev); 331 + struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); 332 + 333 + return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->select_right); 334 + } 335 + 336 + static ssize_t attr_select_right_store_tpkbd(struct device *dev, 337 + struct device_attribute *attr, 338 + const char *buf, 339 + size_t count) 340 + { 341 + struct hid_device *hdev = container_of(dev, struct hid_device, dev); 342 + struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); 343 + int value; 344 + 345 + if (kstrtoint(buf, 10, &value)) 346 + return -EINVAL; 347 + if (value < 0 || value > 1) 348 + return -EINVAL; 349 + 350 + data_pointer->select_right = value; 351 + lenovo_features_set_tpkbd(hdev); 352 + 353 + return count; 354 + } 355 + 356 + static ssize_t attr_sensitivity_show_tpkbd(struct device *dev, 357 + struct device_attribute *attr, 358 + char *buf) 359 + { 360 + struct hid_device *hdev = container_of(dev, struct hid_device, dev); 361 + struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); 362 + 363 + return snprintf(buf, PAGE_SIZE, "%u\n", 364 + data_pointer->sensitivity); 365 + } 366 + 367 + static ssize_t attr_sensitivity_store_tpkbd(struct device *dev, 368 + struct device_attribute *attr, 369 + const char *buf, 370 + size_t count) 371 + { 372 + struct hid_device *hdev = container_of(dev, struct hid_device, dev); 373 + struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); 374 + int value; 375 + 376 + if (kstrtoint(buf, 10, &value) || value < 1 || value > 255) 377 + return -EINVAL; 378 + 379 + data_pointer->sensitivity = value; 380 + lenovo_features_set_tpkbd(hdev); 381 + 382 + return count; 383 + } 384 + 385 + static ssize_t attr_press_speed_show_tpkbd(struct device *dev, 386 + struct device_attribute *attr, 387 + char *buf) 388 + { 389 + struct hid_device *hdev = container_of(dev, struct hid_device, dev); 390 + struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); 391 + 392 + return snprintf(buf, PAGE_SIZE, "%u\n", 393 + data_pointer->press_speed); 394 + } 395 + 396 + static ssize_t attr_press_speed_store_tpkbd(struct device *dev, 397 + struct device_attribute *attr, 398 + const char *buf, 399 + size_t count) 400 + { 401 + struct hid_device *hdev = container_of(dev, struct hid_device, dev); 402 + struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); 403 + int value; 404 + 405 + if (kstrtoint(buf, 10, &value) || value < 1 || value > 255) 406 + return -EINVAL; 407 + 408 + data_pointer->press_speed = value; 409 + lenovo_features_set_tpkbd(hdev); 410 + 411 + return count; 412 + } 413 + 414 + static struct device_attribute dev_attr_press_to_select_tpkbd = 415 + __ATTR(press_to_select, S_IWUSR | S_IRUGO, 416 + attr_press_to_select_show_tpkbd, 417 + attr_press_to_select_store_tpkbd); 418 + 419 + static struct device_attribute dev_attr_dragging_tpkbd = 420 + __ATTR(dragging, S_IWUSR | S_IRUGO, 421 + attr_dragging_show_tpkbd, 422 + attr_dragging_store_tpkbd); 423 + 424 + static struct device_attribute dev_attr_release_to_select_tpkbd = 425 + __ATTR(release_to_select, S_IWUSR | S_IRUGO, 426 + attr_release_to_select_show_tpkbd, 427 + attr_release_to_select_store_tpkbd); 428 + 429 + static struct device_attribute dev_attr_select_right_tpkbd = 430 + __ATTR(select_right, S_IWUSR | S_IRUGO, 431 + attr_select_right_show_tpkbd, 432 + attr_select_right_store_tpkbd); 433 + 434 + static struct device_attribute dev_attr_sensitivity_tpkbd = 435 + __ATTR(sensitivity, S_IWUSR | S_IRUGO, 436 + attr_sensitivity_show_tpkbd, 437 + attr_sensitivity_store_tpkbd); 438 + 439 + static struct device_attribute dev_attr_press_speed_tpkbd = 440 + __ATTR(press_speed, S_IWUSR | S_IRUGO, 441 + attr_press_speed_show_tpkbd, 442 + attr_press_speed_store_tpkbd); 443 + 444 + static struct attribute *lenovo_attributes_tpkbd[] = { 445 + &dev_attr_press_to_select_tpkbd.attr, 446 + &dev_attr_dragging_tpkbd.attr, 447 + &dev_attr_release_to_select_tpkbd.attr, 448 + &dev_attr_select_right_tpkbd.attr, 449 + &dev_attr_sensitivity_tpkbd.attr, 450 + &dev_attr_press_speed_tpkbd.attr, 451 + NULL 452 + }; 453 + 454 + static const struct attribute_group lenovo_attr_group_tpkbd = { 455 + .attrs = lenovo_attributes_tpkbd, 456 + }; 457 + 458 + static enum led_brightness lenovo_led_brightness_get_tpkbd( 459 + struct led_classdev *led_cdev) 460 + { 461 + struct device *dev = led_cdev->dev->parent; 462 + struct hid_device *hdev = container_of(dev, struct hid_device, dev); 463 + struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); 464 + int led_nr = 0; 465 + 466 + if (led_cdev == &data_pointer->led_micmute) 467 + led_nr = 1; 468 + 469 + return data_pointer->led_state & (1 << led_nr) 470 + ? LED_FULL 471 + : LED_OFF; 472 + } 473 + 474 + static void lenovo_led_brightness_set_tpkbd(struct led_classdev *led_cdev, 475 + enum led_brightness value) 476 + { 477 + struct device *dev = led_cdev->dev->parent; 478 + struct hid_device *hdev = container_of(dev, struct hid_device, dev); 479 + struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); 480 + struct hid_report *report; 481 + int led_nr = 0; 482 + 483 + if (led_cdev == &data_pointer->led_micmute) 484 + led_nr = 1; 485 + 486 + if (value == LED_OFF) 487 + data_pointer->led_state &= ~(1 << led_nr); 488 + else 489 + data_pointer->led_state |= 1 << led_nr; 490 + 491 + report = hdev->report_enum[HID_OUTPUT_REPORT].report_id_hash[3]; 492 + report->field[0]->value[0] = (data_pointer->led_state >> 0) & 1; 493 + report->field[0]->value[1] = (data_pointer->led_state >> 1) & 1; 494 + hid_hw_request(hdev, report, HID_REQ_SET_REPORT); 495 + } 496 + 497 + static int lenovo_probe_tpkbd(struct hid_device *hdev) 498 + { 499 + struct device *dev = &hdev->dev; 500 + struct lenovo_drvdata_tpkbd *data_pointer; 501 + size_t name_sz = strlen(dev_name(dev)) + 16; 502 + char *name_mute, *name_micmute; 503 + int i; 504 + int ret; 505 + 506 + /* 507 + * Only register extra settings against subdevice where input_mapping 508 + * set drvdata to 1, i.e. the trackpoint. 509 + */ 510 + if (!hid_get_drvdata(hdev)) 511 + return 0; 512 + 513 + hid_set_drvdata(hdev, NULL); 514 + 515 + /* Validate required reports. */ 516 + for (i = 0; i < 4; i++) { 517 + if (!hid_validate_values(hdev, HID_FEATURE_REPORT, 4, i, 1)) 518 + return -ENODEV; 519 + } 520 + if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 3, 0, 2)) 521 + return -ENODEV; 522 + 523 + ret = sysfs_create_group(&hdev->dev.kobj, &lenovo_attr_group_tpkbd); 524 + if (ret) 525 + hid_warn(hdev, "Could not create sysfs group: %d\n", ret); 526 + 527 + data_pointer = devm_kzalloc(&hdev->dev, 528 + sizeof(struct lenovo_drvdata_tpkbd), 529 + GFP_KERNEL); 530 + if (data_pointer == NULL) { 531 + hid_err(hdev, "Could not allocate memory for driver data\n"); 532 + return -ENOMEM; 533 + } 534 + 535 + // set same default values as windows driver 536 + data_pointer->sensitivity = 0xa0; 537 + data_pointer->press_speed = 0x38; 538 + 539 + name_mute = devm_kzalloc(&hdev->dev, name_sz, GFP_KERNEL); 540 + name_micmute = devm_kzalloc(&hdev->dev, name_sz, GFP_KERNEL); 541 + if (name_mute == NULL || name_micmute == NULL) { 542 + hid_err(hdev, "Could not allocate memory for led data\n"); 543 + return -ENOMEM; 544 + } 545 + snprintf(name_mute, name_sz, "%s:amber:mute", dev_name(dev)); 546 + snprintf(name_micmute, name_sz, "%s:amber:micmute", dev_name(dev)); 547 + 548 + hid_set_drvdata(hdev, data_pointer); 549 + 550 + data_pointer->led_mute.name = name_mute; 551 + data_pointer->led_mute.brightness_get = lenovo_led_brightness_get_tpkbd; 552 + data_pointer->led_mute.brightness_set = lenovo_led_brightness_set_tpkbd; 553 + data_pointer->led_mute.dev = dev; 554 + led_classdev_register(dev, &data_pointer->led_mute); 555 + 556 + data_pointer->led_micmute.name = name_micmute; 557 + data_pointer->led_micmute.brightness_get = 558 + lenovo_led_brightness_get_tpkbd; 559 + data_pointer->led_micmute.brightness_set = 560 + lenovo_led_brightness_set_tpkbd; 561 + data_pointer->led_micmute.dev = dev; 562 + led_classdev_register(dev, &data_pointer->led_micmute); 563 + 564 + lenovo_features_set_tpkbd(hdev); 565 + 566 + return 0; 567 + } 568 + 569 + static int lenovo_probe_cptkbd(struct hid_device *hdev) 570 + { 571 + int ret; 572 + struct lenovo_drvdata_cptkbd *cptkbd_data; 573 + 574 + /* All the custom action happens on the USBMOUSE device for USB */ 575 + if (hdev->product == USB_DEVICE_ID_LENOVO_CUSBKBD 576 + && hdev->type != HID_TYPE_USBMOUSE) { 577 + hid_dbg(hdev, "Ignoring keyboard half of device\n"); 578 + return 0; 579 + } 580 + 581 + cptkbd_data = devm_kzalloc(&hdev->dev, 582 + sizeof(*cptkbd_data), 583 + GFP_KERNEL); 584 + if (cptkbd_data == NULL) { 585 + hid_err(hdev, "can't alloc keyboard descriptor\n"); 586 + return -ENOMEM; 587 + } 588 + hid_set_drvdata(hdev, cptkbd_data); 589 + 590 + /* 591 + * Tell the keyboard a driver understands it, and turn F7, F9, F11 into 592 + * regular keys 593 + */ 594 + ret = lenovo_send_cmd_cptkbd(hdev, 0x01, 0x03); 595 + if (ret) 596 + hid_warn(hdev, "Failed to switch F7/9/11 mode: %d\n", ret); 597 + 598 + /* Turn Fn-Lock on by default */ 599 + cptkbd_data->fn_lock = true; 600 + lenovo_features_set_cptkbd(hdev); 601 + 602 + ret = sysfs_create_group(&hdev->dev.kobj, &lenovo_attr_group_cptkbd); 603 + if (ret) 604 + hid_warn(hdev, "Could not create sysfs group: %d\n", ret); 605 + 606 + return 0; 607 + } 608 + 609 + static int lenovo_probe(struct hid_device *hdev, 610 + const struct hid_device_id *id) 611 + { 612 + int ret; 613 + 614 + ret = hid_parse(hdev); 615 + if (ret) { 616 + hid_err(hdev, "hid_parse failed\n"); 617 + goto err; 618 + } 619 + 620 + ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); 621 + if (ret) { 622 + hid_err(hdev, "hid_hw_start failed\n"); 623 + goto err; 624 + } 625 + 626 + switch (hdev->product) { 627 + case USB_DEVICE_ID_LENOVO_TPKBD: 628 + ret = lenovo_probe_tpkbd(hdev); 629 + break; 630 + case USB_DEVICE_ID_LENOVO_CUSBKBD: 631 + case USB_DEVICE_ID_LENOVO_CBTKBD: 632 + ret = lenovo_probe_cptkbd(hdev); 633 + break; 634 + default: 635 + ret = 0; 636 + break; 637 + } 638 + if (ret) 639 + goto err_hid; 640 + 641 + return 0; 642 + err_hid: 643 + hid_hw_stop(hdev); 644 + err: 645 + return ret; 646 + } 647 + 648 + static void lenovo_remove_tpkbd(struct hid_device *hdev) 649 + { 650 + struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); 651 + 652 + /* 653 + * Only the trackpoint half of the keyboard has drvdata and stuff that 654 + * needs unregistering. 655 + */ 656 + if (data_pointer == NULL) 657 + return; 658 + 659 + sysfs_remove_group(&hdev->dev.kobj, 660 + &lenovo_attr_group_tpkbd); 661 + 662 + led_classdev_unregister(&data_pointer->led_micmute); 663 + led_classdev_unregister(&data_pointer->led_mute); 664 + 665 + hid_set_drvdata(hdev, NULL); 666 + } 667 + 668 + static void lenovo_remove_cptkbd(struct hid_device *hdev) 669 + { 670 + sysfs_remove_group(&hdev->dev.kobj, 671 + &lenovo_attr_group_cptkbd); 672 + } 673 + 674 + static void lenovo_remove(struct hid_device *hdev) 675 + { 676 + switch (hdev->product) { 677 + case USB_DEVICE_ID_LENOVO_TPKBD: 678 + lenovo_remove_tpkbd(hdev); 679 + break; 680 + case USB_DEVICE_ID_LENOVO_CUSBKBD: 681 + case USB_DEVICE_ID_LENOVO_CBTKBD: 682 + lenovo_remove_cptkbd(hdev); 683 + break; 684 + } 685 + 686 + hid_hw_stop(hdev); 687 + } 688 + 689 + static const struct hid_device_id lenovo_devices[] = { 690 + { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) }, 691 + { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CUSBKBD) }, 692 + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CBTKBD) }, 693 + { } 694 + }; 695 + 696 + MODULE_DEVICE_TABLE(hid, lenovo_devices); 697 + 698 + static struct hid_driver lenovo_driver = { 699 + .name = "lenovo", 700 + .id_table = lenovo_devices, 701 + .input_mapping = lenovo_input_mapping, 702 + .probe = lenovo_probe, 703 + .remove = lenovo_remove, 704 + .raw_event = lenovo_raw_event, 705 + }; 706 + module_hid_driver(lenovo_driver); 707 + 708 + MODULE_LICENSE("GPL");
+3 -6
drivers/hid/hid-picolcd_debugfs.c
··· 883 883 884 884 dent = data->debug_reset; 885 885 data->debug_reset = NULL; 886 - if (dent) 887 - debugfs_remove(dent); 886 + debugfs_remove(dent); 888 887 dent = data->debug_eeprom; 889 888 data->debug_eeprom = NULL; 890 - if (dent) 891 - debugfs_remove(dent); 889 + debugfs_remove(dent); 892 890 dent = data->debug_flash; 893 891 data->debug_flash = NULL; 894 - if (dent) 895 - debugfs_remove(dent); 892 + debugfs_remove(dent); 896 893 mutex_destroy(&data->mutex_flash); 897 894 } 898 895
+49 -18
drivers/hid/hid-rmi.c
··· 377 377 irq_mask |= hdata->f30.irq_mask; 378 378 379 379 if (data[1] & ~irq_mask) 380 - hid_warn(hdev, "unknown intr source:%02lx %s:%d\n", 380 + hid_dbg(hdev, "unknown intr source:%02lx %s:%d\n", 381 381 data[1] & ~irq_mask, __FILE__, __LINE__); 382 382 383 383 if (hdata->f11.interrupt_base < hdata->f30.interrupt_base) { ··· 400 400 struct rmi_data *hdata = hid_get_drvdata(hdev); 401 401 402 402 if (!test_bit(RMI_READ_REQUEST_PENDING, &hdata->flags)) { 403 - hid_err(hdev, "no read request pending\n"); 403 + hid_dbg(hdev, "no read request pending\n"); 404 404 return 0; 405 405 } 406 406 ··· 549 549 u8 buf[20]; 550 550 int ret; 551 551 bool has_query9; 552 - bool has_query10; 552 + bool has_query10 = false; 553 553 bool has_query11; 554 554 bool has_query12; 555 555 bool has_physical_props; 556 + bool has_gestures; 557 + bool has_rel; 556 558 unsigned x_size, y_size; 557 559 u16 query12_offset; 558 560 ··· 591 589 return -ENODEV; 592 590 } 593 591 594 - /* query 8 to find out if query 10 exists */ 595 - ret = rmi_read(hdev, data->f11.query_base_addr + 8, buf); 596 - if (ret) { 597 - hid_err(hdev, "can not read gesture information: %d.\n", ret); 598 - return ret; 592 + has_rel = !!(buf[0] & BIT(3)); 593 + has_gestures = !!(buf[0] & BIT(5)); 594 + 595 + if (has_gestures) { 596 + /* query 8 to find out if query 10 exists */ 597 + ret = rmi_read(hdev, data->f11.query_base_addr + 8, buf); 598 + if (ret) { 599 + hid_err(hdev, "can not read gesture information: %d.\n", 600 + ret); 601 + return ret; 602 + } 603 + has_query10 = !!(buf[0] & BIT(2)); 599 604 } 600 - has_query10 = !!(buf[0] & BIT(2)); 601 605 602 606 /* 603 - * At least 8 queries are guaranteed to be present in F11 604 - * +1 for query12. 607 + * At least 4 queries are guaranteed to be present in F11 608 + * +1 for query 5 which is present since absolute events are 609 + * reported and +1 for query 12. 605 610 */ 606 - query12_offset = 9; 611 + query12_offset = 6; 612 + 613 + if (has_rel) 614 + ++query12_offset; /* query 6 is present */ 615 + 616 + if (has_gestures) 617 + query12_offset += 2; /* query 7 and 8 are present */ 607 618 608 619 if (has_query9) 609 620 ++query12_offset; ··· 848 833 struct rmi_data *data = NULL; 849 834 int ret; 850 835 size_t alloc_size; 836 + struct hid_report *input_report; 837 + struct hid_report *output_report; 851 838 852 839 data = devm_kzalloc(&hdev->dev, sizeof(struct rmi_data), GFP_KERNEL); 853 840 if (!data) ··· 868 851 return ret; 869 852 } 870 853 871 - data->input_report_size = (hdev->report_enum[HID_INPUT_REPORT] 872 - .report_id_hash[RMI_ATTN_REPORT_ID]->size >> 3) 873 - + 1 /* report id */; 874 - data->output_report_size = (hdev->report_enum[HID_OUTPUT_REPORT] 875 - .report_id_hash[RMI_WRITE_REPORT_ID]->size >> 3) 876 - + 1 /* report id */; 854 + input_report = hdev->report_enum[HID_INPUT_REPORT] 855 + .report_id_hash[RMI_ATTN_REPORT_ID]; 856 + if (!input_report) { 857 + hid_err(hdev, "device does not have expected input report\n"); 858 + ret = -ENODEV; 859 + return ret; 860 + } 861 + 862 + data->input_report_size = (input_report->size >> 3) + 1 /* report id */; 863 + 864 + output_report = hdev->report_enum[HID_OUTPUT_REPORT] 865 + .report_id_hash[RMI_WRITE_REPORT_ID]; 866 + if (!output_report) { 867 + hid_err(hdev, "device does not have expected output report\n"); 868 + ret = -ENODEV; 869 + return ret; 870 + } 871 + 872 + data->output_report_size = (output_report->size >> 3) 873 + + 1 /* report id */; 877 874 878 875 alloc_size = data->output_report_size + data->input_report_size; 879 876
+1 -1
drivers/hid/hid-roccat-lua.c
··· 61 61 return -EINVAL; 62 62 63 63 mutex_lock(&lua->lua_lock); 64 - retval = roccat_common2_send(usb_dev, command, (void *)buf, real_size); 64 + retval = roccat_common2_send(usb_dev, command, buf, real_size); 65 65 mutex_unlock(&lua->lua_lock); 66 66 67 67 return retval ? retval : real_size;
+86 -46
drivers/hid/hid-sony.c
··· 56 56 57 57 #define MAX_LEDS 4 58 58 59 - static const u8 sixaxis_rdesc_fixup[] = { 60 - 0x95, 0x13, 0x09, 0x01, 0x81, 0x02, 0x95, 0x0C, 61 - 0x81, 0x01, 0x75, 0x10, 0x95, 0x04, 0x26, 0xFF, 62 - 0x03, 0x46, 0xFF, 0x03, 0x09, 0x01, 0x81, 0x02 63 - }; 64 - 65 - static const u8 sixaxis_rdesc_fixup2[] = { 66 - 0x05, 0x01, 0x09, 0x04, 0xa1, 0x01, 0xa1, 0x02, 67 - 0x85, 0x01, 0x75, 0x08, 0x95, 0x01, 0x15, 0x00, 68 - 0x26, 0xff, 0x00, 0x81, 0x03, 0x75, 0x01, 0x95, 69 - 0x13, 0x15, 0x00, 0x25, 0x01, 0x35, 0x00, 0x45, 70 - 0x01, 0x05, 0x09, 0x19, 0x01, 0x29, 0x13, 0x81, 71 - 0x02, 0x75, 0x01, 0x95, 0x0d, 0x06, 0x00, 0xff, 72 - 0x81, 0x03, 0x15, 0x00, 0x26, 0xff, 0x00, 0x05, 73 - 0x01, 0x09, 0x01, 0xa1, 0x00, 0x75, 0x08, 0x95, 74 - 0x04, 0x35, 0x00, 0x46, 0xff, 0x00, 0x09, 0x30, 75 - 0x09, 0x31, 0x09, 0x32, 0x09, 0x35, 0x81, 0x02, 76 - 0xc0, 0x05, 0x01, 0x95, 0x13, 0x09, 0x01, 0x81, 77 - 0x02, 0x95, 0x0c, 0x81, 0x01, 0x75, 0x10, 0x95, 78 - 0x04, 0x26, 0xff, 0x03, 0x46, 0xff, 0x03, 0x09, 79 - 0x01, 0x81, 0x02, 0xc0, 0xa1, 0x02, 0x85, 0x02, 80 - 0x75, 0x08, 0x95, 0x30, 0x09, 0x01, 0xb1, 0x02, 81 - 0xc0, 0xa1, 0x02, 0x85, 0xee, 0x75, 0x08, 0x95, 82 - 0x30, 0x09, 0x01, 0xb1, 0x02, 0xc0, 0xa1, 0x02, 83 - 0x85, 0xef, 0x75, 0x08, 0x95, 0x30, 0x09, 0x01, 84 - 0xb1, 0x02, 0xc0, 0xc0, 59 + static __u8 sixaxis_rdesc[] = { 60 + 0x05, 0x01, /* Usage Page (Desktop), */ 61 + 0x09, 0x04, /* Usage (Joystik), */ 62 + 0xA1, 0x01, /* Collection (Application), */ 63 + 0xA1, 0x02, /* Collection (Logical), */ 64 + 0x85, 0x01, /* Report ID (1), */ 65 + 0x75, 0x08, /* Report Size (8), */ 66 + 0x95, 0x01, /* Report Count (1), */ 67 + 0x15, 0x00, /* Logical Minimum (0), */ 68 + 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 69 + 0x81, 0x03, /* Input (Constant, Variable), */ 70 + 0x75, 0x01, /* Report Size (1), */ 71 + 0x95, 0x13, /* Report Count (19), */ 72 + 0x15, 0x00, /* Logical Minimum (0), */ 73 + 0x25, 0x01, /* Logical Maximum (1), */ 74 + 0x35, 0x00, /* Physical Minimum (0), */ 75 + 0x45, 0x01, /* Physical Maximum (1), */ 76 + 0x05, 0x09, /* Usage Page (Button), */ 77 + 0x19, 0x01, /* Usage Minimum (01h), */ 78 + 0x29, 0x13, /* Usage Maximum (13h), */ 79 + 0x81, 0x02, /* Input (Variable), */ 80 + 0x75, 0x01, /* Report Size (1), */ 81 + 0x95, 0x0D, /* Report Count (13), */ 82 + 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 83 + 0x81, 0x03, /* Input (Constant, Variable), */ 84 + 0x15, 0x00, /* Logical Minimum (0), */ 85 + 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 86 + 0x05, 0x01, /* Usage Page (Desktop), */ 87 + 0x09, 0x01, /* Usage (Pointer), */ 88 + 0xA1, 0x00, /* Collection (Physical), */ 89 + 0x75, 0x08, /* Report Size (8), */ 90 + 0x95, 0x04, /* Report Count (4), */ 91 + 0x35, 0x00, /* Physical Minimum (0), */ 92 + 0x46, 0xFF, 0x00, /* Physical Maximum (255), */ 93 + 0x09, 0x30, /* Usage (X), */ 94 + 0x09, 0x31, /* Usage (Y), */ 95 + 0x09, 0x32, /* Usage (Z), */ 96 + 0x09, 0x35, /* Usage (Rz), */ 97 + 0x81, 0x02, /* Input (Variable), */ 98 + 0xC0, /* End Collection, */ 99 + 0x05, 0x01, /* Usage Page (Desktop), */ 100 + 0x95, 0x13, /* Report Count (19), */ 101 + 0x09, 0x01, /* Usage (Pointer), */ 102 + 0x81, 0x02, /* Input (Variable), */ 103 + 0x95, 0x0C, /* Report Count (12), */ 104 + 0x81, 0x01, /* Input (Constant), */ 105 + 0x75, 0x10, /* Report Size (16), */ 106 + 0x95, 0x04, /* Report Count (4), */ 107 + 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ 108 + 0x46, 0xFF, 0x03, /* Physical Maximum (1023), */ 109 + 0x09, 0x01, /* Usage (Pointer), */ 110 + 0x81, 0x02, /* Input (Variable), */ 111 + 0xC0, /* End Collection, */ 112 + 0xA1, 0x02, /* Collection (Logical), */ 113 + 0x85, 0x02, /* Report ID (2), */ 114 + 0x75, 0x08, /* Report Size (8), */ 115 + 0x95, 0x30, /* Report Count (48), */ 116 + 0x09, 0x01, /* Usage (Pointer), */ 117 + 0xB1, 0x02, /* Feature (Variable), */ 118 + 0xC0, /* End Collection, */ 119 + 0xA1, 0x02, /* Collection (Logical), */ 120 + 0x85, 0xEE, /* Report ID (238), */ 121 + 0x75, 0x08, /* Report Size (8), */ 122 + 0x95, 0x30, /* Report Count (48), */ 123 + 0x09, 0x01, /* Usage (Pointer), */ 124 + 0xB1, 0x02, /* Feature (Variable), */ 125 + 0xC0, /* End Collection, */ 126 + 0xA1, 0x02, /* Collection (Logical), */ 127 + 0x85, 0xEF, /* Report ID (239), */ 128 + 0x75, 0x08, /* Report Size (8), */ 129 + 0x95, 0x30, /* Report Count (48), */ 130 + 0x09, 0x01, /* Usage (Pointer), */ 131 + 0xB1, 0x02, /* Feature (Variable), */ 132 + 0xC0, /* End Collection, */ 133 + 0xC0 /* End Collection */ 85 134 }; 86 135 87 136 /* ··· 827 778 __u8 led_count; 828 779 }; 829 780 781 + static __u8 *sixaxis_fixup(struct hid_device *hdev, __u8 *rdesc, 782 + unsigned int *rsize) 783 + { 784 + *rsize = sizeof(sixaxis_rdesc); 785 + return sixaxis_rdesc; 786 + } 787 + 830 788 static __u8 *ps3remote_fixup(struct hid_device *hdev, __u8 *rdesc, 831 789 unsigned int *rsize) 832 790 { ··· 875 819 return 1; 876 820 } 877 821 878 - 879 - /* Sony Vaio VGX has wrongly mouse pointer declared as constant */ 880 822 static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc, 881 823 unsigned int *rsize) 882 824 { ··· 911 857 *rsize = sizeof(dualshock4_bt_rdesc); 912 858 } 913 859 914 - /* The HID descriptor exposed over BT has a trailing zero byte */ 915 - if ((((sc->quirks & SIXAXIS_CONTROLLER_USB) && *rsize == 148) || 916 - ((sc->quirks & SIXAXIS_CONTROLLER_BT) && *rsize == 149)) && 917 - rdesc[83] == 0x75) { 918 - hid_info(hdev, "Fixing up Sony Sixaxis report descriptor\n"); 919 - memcpy((void *)&rdesc[83], (void *)&sixaxis_rdesc_fixup, 920 - sizeof(sixaxis_rdesc_fixup)); 921 - } else if (sc->quirks & SIXAXIS_CONTROLLER_USB && 922 - *rsize > sizeof(sixaxis_rdesc_fixup2)) { 923 - hid_info(hdev, "Sony Sixaxis clone detected. Using original report descriptor (size: %d clone; %d new)\n", 924 - *rsize, (int)sizeof(sixaxis_rdesc_fixup2)); 925 - *rsize = sizeof(sixaxis_rdesc_fixup2); 926 - memcpy(rdesc, &sixaxis_rdesc_fixup2, *rsize); 927 - } 860 + if (sc->quirks & SIXAXIS_CONTROLLER) 861 + return sixaxis_fixup(hdev, rdesc, rsize); 928 862 929 863 if (sc->quirks & PS3REMOTE) 930 864 return ps3remote_fixup(hdev, rdesc, rsize); ··· 1349 1307 static const char * const ds4_name_str[] = { "red", "green", "blue", 1350 1308 "global" }; 1351 1309 __u8 initial_values[MAX_LEDS] = { 0 }; 1352 - __u8 max_brightness[MAX_LEDS] = { 1 }; 1310 + __u8 max_brightness[MAX_LEDS] = { [0 ... (MAX_LEDS - 1)] = 1 }; 1353 1311 __u8 use_hw_blink[MAX_LEDS] = { 0 }; 1354 1312 1355 1313 BUG_ON(!(sc->quirks & SONY_LED_SUPPORT)); ··· 1872 1830 1873 1831 if (sc->quirks & VAIO_RDESC_CONSTANT) 1874 1832 connect_mask |= HID_CONNECT_HIDDEV_FORCE; 1875 - else if (sc->quirks & SIXAXIS_CONTROLLER_USB) 1876 - connect_mask |= HID_CONNECT_HIDDEV_FORCE; 1877 - else if (sc->quirks & SIXAXIS_CONTROLLER_BT) 1833 + else if (sc->quirks & SIXAXIS_CONTROLLER) 1878 1834 connect_mask |= HID_CONNECT_HIDDEV_FORCE; 1879 1835 1880 1836 ret = hid_hw_start(hdev, connect_mask);
+14 -1
drivers/hid/i2c-hid/i2c-hid.c
··· 1054 1054 static int i2c_hid_suspend(struct device *dev) 1055 1055 { 1056 1056 struct i2c_client *client = to_i2c_client(dev); 1057 + struct i2c_hid *ihid = i2c_get_clientdata(client); 1058 + struct hid_device *hid = ihid->hid; 1059 + int ret = 0; 1057 1060 1058 1061 disable_irq(client->irq); 1059 1062 if (device_may_wakeup(&client->dev)) 1060 1063 enable_irq_wake(client->irq); 1061 1064 1065 + if (hid->driver && hid->driver->suspend) 1066 + ret = hid->driver->suspend(hid, PMSG_SUSPEND); 1067 + 1062 1068 /* Save some power */ 1063 1069 i2c_hid_set_power(client, I2C_HID_PWR_SLEEP); 1064 1070 1065 - return 0; 1071 + return ret; 1066 1072 } 1067 1073 1068 1074 static int i2c_hid_resume(struct device *dev) 1069 1075 { 1070 1076 int ret; 1071 1077 struct i2c_client *client = to_i2c_client(dev); 1078 + struct i2c_hid *ihid = i2c_get_clientdata(client); 1079 + struct hid_device *hid = ihid->hid; 1072 1080 1073 1081 enable_irq(client->irq); 1074 1082 ret = i2c_hid_hwreset(client); ··· 1085 1077 1086 1078 if (device_may_wakeup(&client->dev)) 1087 1079 disable_irq_wake(client->irq); 1080 + 1081 + if (hid->driver && hid->driver->reset_resume) { 1082 + ret = hid->driver->reset_resume(hid); 1083 + return ret; 1084 + } 1088 1085 1089 1086 return 0; 1090 1087 }
+6 -2
drivers/hid/usbhid/hid-core.c
··· 58 58 MODULE_PARM_DESC(ignoreled, "Autosuspend with active leds"); 59 59 60 60 /* Quirks specified at module load time */ 61 - static char *quirks_param[MAX_USBHID_BOOT_QUIRKS] = { [ 0 ... (MAX_USBHID_BOOT_QUIRKS - 1) ] = NULL }; 61 + static char *quirks_param[MAX_USBHID_BOOT_QUIRKS]; 62 62 module_param_array_named(quirks, quirks_param, charp, NULL, 0444); 63 63 MODULE_PARM_DESC(quirks, "Add/modify USB HID quirks by specifying " 64 64 " quirks=vendorID:productID:quirks" ··· 536 536 int head; 537 537 struct usbhid_device *usbhid = hid->driver_data; 538 538 539 - if ((hid->quirks & HID_QUIRK_NOGET) && dir == USB_DIR_IN) 539 + if (((hid->quirks & HID_QUIRK_NOGET) && dir == USB_DIR_IN) || 540 + test_bit(HID_DISCONNECTED, &usbhid->iofl)) 540 541 return; 541 542 542 543 if (usbhid->urbout && dir == USB_DIR_OUT && report->type == HID_OUTPUT_REPORT) { ··· 1367 1366 return; 1368 1367 1369 1368 usbhid = hid->driver_data; 1369 + spin_lock_irq(&usbhid->lock); /* Sync with error and led handlers */ 1370 + set_bit(HID_DISCONNECTED, &usbhid->iofl); 1371 + spin_unlock_irq(&usbhid->lock); 1370 1372 hid_destroy_device(hid); 1371 1373 kfree(usbhid); 1372 1374 }
+1
drivers/hid/usbhid/hid-quirks.c
··· 124 124 { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_HD, HID_QUIRK_NO_INIT_REPORTS }, 125 125 { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_QUAD_HD, HID_QUIRK_NO_INIT_REPORTS }, 126 126 { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_TP_V103, HID_QUIRK_NO_INIT_REPORTS }, 127 + { USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD_A096, HID_QUIRK_NO_INIT_INPUT_REPORTS }, 127 128 128 129 { 0, 0 } 129 130 };
+1
include/linux/hid.h
··· 167 167 #define HID_UP_MSVENDOR 0xff000000 168 168 #define HID_UP_CUSTOM 0x00ff0000 169 169 #define HID_UP_LOGIVENDOR 0xffbc0000 170 + #define HID_UP_LNVENDOR 0xffa00000 170 171 #define HID_UP_SENSOR 0x00200000 171 172 172 173 #define HID_USAGE 0x0000ffff