diff options
| -rw-r--r-- | drivers/hid/Kconfig | 22 | ||||
| -rw-r--r-- | drivers/hid/Makefile | 2 | ||||
| -rw-r--r-- | drivers/hid/hid-core.c | 30 | ||||
| -rw-r--r-- | drivers/hid/hid-ids.h | 9 | ||||
| -rw-r--r-- | drivers/hid/hid-input.c | 2 | ||||
| -rw-r--r-- | drivers/hid/hid-lenovo.c | 13 | ||||
| -rw-r--r-- | drivers/hid/hid-logitech-dj.c | 397 | ||||
| -rw-r--r-- | drivers/hid/hid-logitech-dj.h | 125 | ||||
| -rw-r--r-- | drivers/hid/hid-logitech-hidpp.c | 1241 | ||||
| -rw-r--r-- | drivers/hid/hid-microsoft.c | 2 | ||||
| -rw-r--r-- | drivers/hid/hid-plantronics.c | 55 | ||||
| -rw-r--r-- | drivers/hid/hid-rmi.c | 83 | ||||
| -rw-r--r-- | drivers/hid/hid-roccat-kone.c | 9 | ||||
| -rw-r--r-- | drivers/hid/hid-saitek.c | 4 | ||||
| -rw-r--r-- | drivers/hid/hid-sony.c | 150 | ||||
| -rw-r--r-- | drivers/hid/i2c-hid/i2c-hid.c | 16 | ||||
| -rw-r--r-- | drivers/hid/usbhid/hid-core.c | 36 | ||||
| -rw-r--r-- | drivers/hid/usbhid/hid-quirks.c | 2 | ||||
| -rw-r--r-- | drivers/hid/usbhid/usbhid.h | 1 | ||||
| -rw-r--r-- | drivers/hid/wacom.h | 2 | ||||
| -rw-r--r-- | drivers/hid/wacom_sys.c | 60 | ||||
| -rw-r--r-- | drivers/hid/wacom_wac.c | 216 | ||||
| -rw-r--r-- | drivers/hid/wacom_wac.h | 3 | ||||
| -rw-r--r-- | drivers/usb/core/quirks.c | 3 | ||||
| -rw-r--r-- | include/linux/hid.h | 32 |
25 files changed, 2097 insertions, 418 deletions
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index f42df4dd58d2..230b6f887cd8 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig | |||
| @@ -371,6 +371,7 @@ config HID_LOGITECH_DJ | |||
| 371 | tristate "Logitech Unifying receivers full support" | 371 | tristate "Logitech Unifying receivers full support" |
| 372 | depends on HIDRAW | 372 | depends on HIDRAW |
| 373 | depends on HID_LOGITECH | 373 | depends on HID_LOGITECH |
| 374 | select HID_LOGITECH_HIDPP | ||
| 374 | ---help--- | 375 | ---help--- |
| 375 | Say Y if you want support for Logitech Unifying receivers and devices. | 376 | Say Y if you want support for Logitech Unifying receivers and devices. |
| 376 | Unifying receivers are capable of pairing up to 6 Logitech compliant | 377 | Unifying receivers are capable of pairing up to 6 Logitech compliant |
| @@ -378,6 +379,17 @@ config HID_LOGITECH_DJ | |||
| 378 | generic USB_HID driver and all incoming events will be multiplexed | 379 | generic USB_HID driver and all incoming events will be multiplexed |
| 379 | into a single mouse and a single keyboard device. | 380 | into a single mouse and a single keyboard device. |
| 380 | 381 | ||
| 382 | config HID_LOGITECH_HIDPP | ||
| 383 | tristate "Logitech HID++ devices support" | ||
| 384 | depends on HID_LOGITECH | ||
| 385 | ---help--- | ||
| 386 | Support for Logitech devices relyingon the HID++ Logitech specification | ||
| 387 | |||
| 388 | Say Y if you want support for Logitech devices relying on the HID++ | ||
| 389 | specification. Such devices are the various Logitech Touchpads (T650, | ||
| 390 | T651, TK820), some mice (Zone Touch mouse), or even keyboards (Solar | ||
| 391 | Keayboard). | ||
| 392 | |||
| 381 | config LOGITECH_FF | 393 | config LOGITECH_FF |
| 382 | bool "Logitech force feedback support" | 394 | bool "Logitech force feedback support" |
| 383 | depends on HID_LOGITECH | 395 | depends on HID_LOGITECH |
| @@ -613,6 +625,13 @@ config HID_PICOLCD_CIR | |||
| 613 | ---help--- | 625 | ---help--- |
| 614 | Provide access to PicoLCD's CIR interface via remote control (LIRC). | 626 | Provide access to PicoLCD's CIR interface via remote control (LIRC). |
| 615 | 627 | ||
| 628 | config HID_PLANTRONICS | ||
| 629 | tristate "Plantronics USB HID Driver" | ||
| 630 | default !EXPERT | ||
| 631 | depends on HID | ||
| 632 | ---help--- | ||
| 633 | Provides HID support for Plantronics telephony devices. | ||
| 634 | |||
| 616 | config HID_PRIMAX | 635 | config HID_PRIMAX |
| 617 | tristate "Primax non-fully HID-compliant devices" | 636 | tristate "Primax non-fully HID-compliant devices" |
| 618 | depends on HID | 637 | depends on HID |
| @@ -629,7 +648,7 @@ config HID_ROCCAT | |||
| 629 | support for its special functionalities. | 648 | support for its special functionalities. |
| 630 | 649 | ||
| 631 | config HID_SAITEK | 650 | config HID_SAITEK |
| 632 | tristate "Saitek non-fully HID-compliant devices" | 651 | tristate "Saitek (Mad Catz) non-fully HID-compliant devices" |
| 633 | depends on HID | 652 | depends on HID |
| 634 | ---help--- | 653 | ---help--- |
| 635 | Support for Saitek devices that are not fully compliant with the | 654 | Support for Saitek devices that are not fully compliant with the |
| @@ -637,6 +656,7 @@ config HID_SAITEK | |||
| 637 | 656 | ||
| 638 | Supported devices: | 657 | Supported devices: |
| 639 | - PS1000 Dual Analog Pad | 658 | - PS1000 Dual Analog Pad |
| 659 | - R.A.T.9 Gaming Mouse | ||
| 640 | - R.A.T.7 Gaming Mouse | 660 | - R.A.T.7 Gaming Mouse |
| 641 | - M.M.O.7 Gaming Mouse | 661 | - M.M.O.7 Gaming Mouse |
| 642 | 662 | ||
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index e2850d8af9ca..debd15b44b59 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile | |||
| @@ -63,6 +63,7 @@ obj-$(CONFIG_HID_LCPOWER) += hid-lcpower.o | |||
| 63 | obj-$(CONFIG_HID_LENOVO) += hid-lenovo.o | 63 | obj-$(CONFIG_HID_LENOVO) += hid-lenovo.o |
| 64 | obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o | 64 | obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o |
| 65 | obj-$(CONFIG_HID_LOGITECH_DJ) += hid-logitech-dj.o | 65 | obj-$(CONFIG_HID_LOGITECH_DJ) += hid-logitech-dj.o |
| 66 | obj-$(CONFIG_HID_LOGITECH_HIDPP) += hid-logitech-hidpp.o | ||
| 66 | obj-$(CONFIG_HID_MAGICMOUSE) += hid-magicmouse.o | 67 | obj-$(CONFIG_HID_MAGICMOUSE) += hid-magicmouse.o |
| 67 | obj-$(CONFIG_HID_MICROSOFT) += hid-microsoft.o | 68 | obj-$(CONFIG_HID_MICROSOFT) += hid-microsoft.o |
| 68 | obj-$(CONFIG_HID_MONTEREY) += hid-monterey.o | 69 | obj-$(CONFIG_HID_MONTEREY) += hid-monterey.o |
| @@ -94,6 +95,7 @@ ifdef CONFIG_DEBUG_FS | |||
| 94 | hid-picolcd-y += hid-picolcd_debugfs.o | 95 | hid-picolcd-y += hid-picolcd_debugfs.o |
| 95 | endif | 96 | endif |
| 96 | 97 | ||
| 98 | obj-$(CONFIG_HID_PLANTRONICS) += hid-plantronics.o | ||
| 97 | obj-$(CONFIG_HID_PRIMAX) += hid-primax.o | 99 | obj-$(CONFIG_HID_PRIMAX) += hid-primax.o |
| 98 | obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o hid-roccat-common.o \ | 100 | obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o hid-roccat-common.o \ |
| 99 | hid-roccat-arvo.o hid-roccat-isku.o hid-roccat-kone.o \ | 101 | hid-roccat-arvo.o hid-roccat-isku.o hid-roccat-kone.o \ |
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index ee6ba7625e77..c3d0ac1a0988 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
| @@ -702,6 +702,11 @@ static void hid_scan_collection(struct hid_parser *parser, unsigned type) | |||
| 702 | if (((parser->global.usage_page << 16) == HID_UP_SENSOR) && | 702 | if (((parser->global.usage_page << 16) == HID_UP_SENSOR) && |
| 703 | type == HID_COLLECTION_PHYSICAL) | 703 | type == HID_COLLECTION_PHYSICAL) |
| 704 | hid->group = HID_GROUP_SENSOR_HUB; | 704 | hid->group = HID_GROUP_SENSOR_HUB; |
| 705 | |||
| 706 | if (hid->vendor == USB_VENDOR_ID_MICROSOFT && | ||
| 707 | hid->product == USB_DEVICE_ID_MS_TYPE_COVER_3 && | ||
| 708 | hid->group == HID_GROUP_MULTITOUCH) | ||
| 709 | hid->group = HID_GROUP_GENERIC; | ||
| 705 | } | 710 | } |
| 706 | 711 | ||
| 707 | static int hid_scan_main(struct hid_parser *parser, struct hid_item *item) | 712 | static int hid_scan_main(struct hid_parser *parser, struct hid_item *item) |
| @@ -780,22 +785,19 @@ static int hid_scan_report(struct hid_device *hid) | |||
| 780 | hid->group = HID_GROUP_MULTITOUCH_WIN_8; | 785 | hid->group = HID_GROUP_MULTITOUCH_WIN_8; |
| 781 | 786 | ||
| 782 | /* | 787 | /* |
| 783 | * Vendor specific handlings | ||
| 784 | */ | ||
| 785 | if ((hid->vendor == USB_VENDOR_ID_SYNAPTICS) && | ||
| 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)) | ||
| 789 | /* hid-rmi should take care of them, not hid-generic */ | ||
| 790 | hid->group = HID_GROUP_RMI; | ||
| 791 | |||
| 792 | /* | ||
| 793 | * Vendor specific handlings | 788 | * Vendor specific handlings |
| 794 | */ | 789 | */ |
| 795 | switch (hid->vendor) { | 790 | switch (hid->vendor) { |
| 796 | case USB_VENDOR_ID_WACOM: | 791 | case USB_VENDOR_ID_WACOM: |
| 797 | hid->group = HID_GROUP_WACOM; | 792 | hid->group = HID_GROUP_WACOM; |
| 798 | break; | 793 | break; |
| 794 | case USB_VENDOR_ID_SYNAPTICS: | ||
| 795 | if ((hid->group == HID_GROUP_GENERIC) && | ||
| 796 | (hid->bus != BUS_USB || hid->type == HID_TYPE_USBMOUSE)) | ||
| 797 | /* hid-rmi should only bind to the mouse interface of | ||
| 798 | * composite USB devices */ | ||
| 799 | hid->group = HID_GROUP_RMI; | ||
| 800 | break; | ||
| 799 | } | 801 | } |
| 800 | 802 | ||
| 801 | vfree(parser); | 803 | vfree(parser); |
| @@ -1816,6 +1818,7 @@ static const struct hid_device_id hid_have_special_driver[] = { | |||
| 1816 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2) }, | 1818 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2) }, |
| 1817 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RECEIVER) }, | 1819 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RECEIVER) }, |
| 1818 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3) }, | 1820 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3) }, |
| 1821 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_T651) }, | ||
| 1819 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP) }, | 1822 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP) }, |
| 1820 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE) }, | 1823 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE) }, |
| 1821 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI) }, | 1824 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI) }, |
| @@ -1856,6 +1859,7 @@ static const struct hid_device_id hid_have_special_driver[] = { | |||
| 1856 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K) }, | 1859 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K) }, |
| 1857 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) }, | 1860 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) }, |
| 1858 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_OFFICE_KB) }, | 1861 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_OFFICE_KB) }, |
| 1862 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3) }, | ||
| 1859 | { HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) }, | 1863 | { HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) }, |
| 1860 | { HID_USB_DEVICE(USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL) }, | 1864 | { HID_USB_DEVICE(USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL) }, |
| 1861 | { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN) }, | 1865 | { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN) }, |
| @@ -1881,6 +1885,7 @@ static const struct hid_device_id hid_have_special_driver[] = { | |||
| 1881 | { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) }, | 1885 | { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) }, |
| 1882 | { HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_6000) }, | 1886 | { HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_6000) }, |
| 1883 | { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) }, | 1887 | { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) }, |
| 1888 | { HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS, HID_ANY_ID) }, | ||
| 1884 | { HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_KEYBOARD) }, | 1889 | { HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_KEYBOARD) }, |
| 1885 | #if IS_ENABLED(CONFIG_HID_ROCCAT) | 1890 | #if IS_ENABLED(CONFIG_HID_ROCCAT) |
| 1886 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ARVO) }, | 1891 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ARVO) }, |
| @@ -1904,10 +1909,12 @@ static const struct hid_device_id hid_have_special_driver[] = { | |||
| 1904 | { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_PS1000) }, | 1909 | { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_PS1000) }, |
| 1905 | { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT7) }, | 1910 | { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT7) }, |
| 1906 | { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_MMO7) }, | 1911 | { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_MMO7) }, |
| 1912 | { HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_RAT9) }, | ||
| 1907 | #endif | 1913 | #endif |
| 1908 | { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, | 1914 | { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, |
| 1909 | { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) }, | 1915 | { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) }, |
| 1910 | { HID_USB_DEVICE(USB_VENDOR_ID_SKYCABLE, USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER) }, | 1916 | { HID_USB_DEVICE(USB_VENDOR_ID_SKYCABLE, USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER) }, |
| 1917 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SMK, USB_DEVICE_ID_SMK_PS3_BDREMOTE) }, | ||
| 1911 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_BUZZ_CONTROLLER) }, | 1918 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_BUZZ_CONTROLLER) }, |
| 1912 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER) }, | 1919 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER) }, |
| 1913 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE) }, | 1920 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE) }, |
| @@ -2533,7 +2540,8 @@ int hid_add_device(struct hid_device *hdev) | |||
| 2533 | * Scan generic devices for group information | 2540 | * Scan generic devices for group information |
| 2534 | */ | 2541 | */ |
| 2535 | if (hid_ignore_special_drivers || | 2542 | if (hid_ignore_special_drivers || |
| 2536 | !hid_match_id(hdev, hid_have_special_driver)) { | 2543 | (!hdev->group && |
| 2544 | !hid_match_id(hdev, hid_have_special_driver))) { | ||
| 2537 | ret = hid_scan_report(hdev); | 2545 | ret = hid_scan_report(hdev); |
| 2538 | if (ret) | 2546 | if (ret) |
| 2539 | hid_warn(hdev, "bad device descriptor (%d)\n", ret); | 2547 | hid_warn(hdev, "bad device descriptor (%d)\n", ret); |
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index d6cc6a9cf10f..7460f3402298 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h | |||
| @@ -300,6 +300,7 @@ | |||
| 300 | #define USB_DEVICE_ID_ELAN_TOUCHSCREEN 0x0089 | 300 | #define USB_DEVICE_ID_ELAN_TOUCHSCREEN 0x0089 |
| 301 | #define USB_DEVICE_ID_ELAN_TOUCHSCREEN_009B 0x009b | 301 | #define USB_DEVICE_ID_ELAN_TOUCHSCREEN_009B 0x009b |
| 302 | #define USB_DEVICE_ID_ELAN_TOUCHSCREEN_0103 0x0103 | 302 | #define USB_DEVICE_ID_ELAN_TOUCHSCREEN_0103 0x0103 |
| 303 | #define USB_DEVICE_ID_ELAN_TOUCHSCREEN_010c 0x010c | ||
| 303 | #define USB_DEVICE_ID_ELAN_TOUCHSCREEN_016F 0x016f | 304 | #define USB_DEVICE_ID_ELAN_TOUCHSCREEN_016F 0x016f |
| 304 | 305 | ||
| 305 | #define USB_VENDOR_ID_ELECOM 0x056e | 306 | #define USB_VENDOR_ID_ELECOM 0x056e |
| @@ -578,6 +579,7 @@ | |||
| 578 | 579 | ||
| 579 | #define USB_VENDOR_ID_LOGITECH 0x046d | 580 | #define USB_VENDOR_ID_LOGITECH 0x046d |
| 580 | #define USB_DEVICE_ID_LOGITECH_AUDIOHUB 0x0a0e | 581 | #define USB_DEVICE_ID_LOGITECH_AUDIOHUB 0x0a0e |
| 582 | #define USB_DEVICE_ID_LOGITECH_T651 0xb00c | ||
| 581 | #define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101 | 583 | #define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101 |
| 582 | #define USB_DEVICE_ID_LOGITECH_HARMONY_FIRST 0xc110 | 584 | #define USB_DEVICE_ID_LOGITECH_HARMONY_FIRST 0xc110 |
| 583 | #define USB_DEVICE_ID_LOGITECH_HARMONY_LAST 0xc14f | 585 | #define USB_DEVICE_ID_LOGITECH_HARMONY_LAST 0xc14f |
| @@ -620,6 +622,7 @@ | |||
| 620 | 622 | ||
| 621 | #define USB_VENDOR_ID_MADCATZ 0x0738 | 623 | #define USB_VENDOR_ID_MADCATZ 0x0738 |
| 622 | #define USB_DEVICE_ID_MADCATZ_BEATPAD 0x4540 | 624 | #define USB_DEVICE_ID_MADCATZ_BEATPAD 0x4540 |
| 625 | #define USB_DEVICE_ID_MADCATZ_RAT9 0x1709 | ||
| 623 | 626 | ||
| 624 | #define USB_VENDOR_ID_MCC 0x09db | 627 | #define USB_VENDOR_ID_MCC 0x09db |
| 625 | #define USB_DEVICE_ID_MCC_PMD1024LS 0x0076 | 628 | #define USB_DEVICE_ID_MCC_PMD1024LS 0x0076 |
| @@ -649,6 +652,7 @@ | |||
| 649 | #define USB_DEVICE_ID_MS_SURFACE_PRO_2 0x0799 | 652 | #define USB_DEVICE_ID_MS_SURFACE_PRO_2 0x0799 |
| 650 | #define USB_DEVICE_ID_MS_TOUCH_COVER_2 0x07a7 | 653 | #define USB_DEVICE_ID_MS_TOUCH_COVER_2 0x07a7 |
| 651 | #define USB_DEVICE_ID_MS_TYPE_COVER_2 0x07a9 | 654 | #define USB_DEVICE_ID_MS_TYPE_COVER_2 0x07a9 |
| 655 | #define USB_DEVICE_ID_MS_TYPE_COVER_3 0x07dc | ||
| 652 | 656 | ||
| 653 | #define USB_VENDOR_ID_MOJO 0x8282 | 657 | #define USB_VENDOR_ID_MOJO 0x8282 |
| 654 | #define USB_DEVICE_ID_RETRO_ADAPTER 0x3201 | 658 | #define USB_DEVICE_ID_RETRO_ADAPTER 0x3201 |
| @@ -716,6 +720,8 @@ | |||
| 716 | #define USB_DEVICE_ID_ORTEK_PKB1700 0x1700 | 720 | #define USB_DEVICE_ID_ORTEK_PKB1700 0x1700 |
| 717 | #define USB_DEVICE_ID_ORTEK_WKB2000 0x2000 | 721 | #define USB_DEVICE_ID_ORTEK_WKB2000 0x2000 |
| 718 | 722 | ||
| 723 | #define USB_VENDOR_ID_PLANTRONICS 0x047f | ||
| 724 | |||
| 719 | #define USB_VENDOR_ID_PANASONIC 0x04da | 725 | #define USB_VENDOR_ID_PANASONIC 0x04da |
| 720 | #define USB_DEVICE_ID_PANABOARD_UBT780 0x1044 | 726 | #define USB_DEVICE_ID_PANABOARD_UBT780 0x1044 |
| 721 | #define USB_DEVICE_ID_PANABOARD_UBT880 0x104d | 727 | #define USB_DEVICE_ID_PANABOARD_UBT880 0x104d |
| @@ -813,6 +819,9 @@ | |||
| 813 | #define USB_VENDOR_ID_SKYCABLE 0x1223 | 819 | #define USB_VENDOR_ID_SKYCABLE 0x1223 |
| 814 | #define USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER 0x3F07 | 820 | #define USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER 0x3F07 |
| 815 | 821 | ||
| 822 | #define USB_VENDOR_ID_SMK 0x0609 | ||
| 823 | #define USB_DEVICE_ID_SMK_PS3_BDREMOTE 0x0306 | ||
| 824 | |||
| 816 | #define USB_VENDOR_ID_SONY 0x054c | 825 | #define USB_VENDOR_ID_SONY 0x054c |
| 817 | #define USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE 0x024b | 826 | #define USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE 0x024b |
| 818 | #define USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE 0x0374 | 827 | #define USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE 0x0374 |
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 1e95f4df4146..e0a0f06ac5ef 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c | |||
| @@ -872,7 +872,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
| 872 | case 0x2cb: map_key_clear(KEY_KBDINPUTASSIST_ACCEPT); break; | 872 | case 0x2cb: map_key_clear(KEY_KBDINPUTASSIST_ACCEPT); break; |
| 873 | case 0x2cc: map_key_clear(KEY_KBDINPUTASSIST_CANCEL); break; | 873 | case 0x2cc: map_key_clear(KEY_KBDINPUTASSIST_CANCEL); break; |
| 874 | 874 | ||
| 875 | default: goto ignore; | 875 | default: map_key_clear(KEY_UNKNOWN); |
| 876 | } | 876 | } |
| 877 | break; | 877 | break; |
| 878 | 878 | ||
diff --git a/drivers/hid/hid-lenovo.c b/drivers/hid/hid-lenovo.c index bf227f7679af..4c55f4d95798 100644 --- a/drivers/hid/hid-lenovo.c +++ b/drivers/hid/hid-lenovo.c | |||
| @@ -62,7 +62,6 @@ static int lenovo_input_mapping_cptkbd(struct hid_device *hdev, | |||
| 62 | /* HID_UP_LNVENDOR = USB, HID_UP_MSVENDOR = BT */ | 62 | /* HID_UP_LNVENDOR = USB, HID_UP_MSVENDOR = BT */ |
| 63 | if ((usage->hid & HID_USAGE_PAGE) == HID_UP_MSVENDOR || | 63 | if ((usage->hid & HID_USAGE_PAGE) == HID_UP_MSVENDOR || |
| 64 | (usage->hid & HID_USAGE_PAGE) == HID_UP_LNVENDOR) { | 64 | (usage->hid & HID_USAGE_PAGE) == HID_UP_LNVENDOR) { |
| 65 | set_bit(EV_REP, hi->input->evbit); | ||
| 66 | switch (usage->hid & HID_USAGE) { | 65 | switch (usage->hid & HID_USAGE) { |
| 67 | case 0x00f1: /* Fn-F4: Mic mute */ | 66 | case 0x00f1: /* Fn-F4: Mic mute */ |
| 68 | map_key_clear(KEY_MICMUTE); | 67 | map_key_clear(KEY_MICMUTE); |
| @@ -85,13 +84,13 @@ static int lenovo_input_mapping_cptkbd(struct hid_device *hdev, | |||
| 85 | case 0x00f8: /* Fn-F11: View open applications (3 boxes) */ | 84 | case 0x00f8: /* Fn-F11: View open applications (3 boxes) */ |
| 86 | map_key_clear(KEY_SCALE); | 85 | map_key_clear(KEY_SCALE); |
| 87 | return 1; | 86 | return 1; |
| 88 | case 0x00fa: /* Fn-Esc: Fn-lock toggle */ | 87 | case 0x00f9: /* Fn-F12: Open My computer (6 boxes) USB-only */ |
| 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 */ | 88 | /* NB: This mapping is invented in raw_event below */ |
| 93 | map_key_clear(KEY_FILE); | 89 | map_key_clear(KEY_FILE); |
| 94 | return 1; | 90 | return 1; |
| 91 | case 0x00fa: /* Fn-Esc: Fn-lock toggle */ | ||
| 92 | map_key_clear(KEY_FN_ESC); | ||
| 93 | return 1; | ||
| 95 | } | 94 | } |
| 96 | } | 95 | } |
| 97 | 96 | ||
| @@ -207,8 +206,8 @@ static int lenovo_raw_event(struct hid_device *hdev, | |||
| 207 | && data[0] == 0x15 | 206 | && data[0] == 0x15 |
| 208 | && data[1] == 0x94 | 207 | && data[1] == 0x94 |
| 209 | && data[2] == 0x01)) { | 208 | && data[2] == 0x01)) { |
| 210 | data[1] = 0x0; | 209 | data[1] = 0x00; |
| 211 | data[2] = 0x4; | 210 | data[2] = 0x01; |
| 212 | } | 211 | } |
| 213 | 212 | ||
| 214 | return 0; | 213 | return 0; |
diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index 71f569292cab..c917ab61aafa 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c | |||
| @@ -26,9 +26,104 @@ | |||
| 26 | #include <linux/hid.h> | 26 | #include <linux/hid.h> |
| 27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
| 28 | #include <linux/usb.h> | 28 | #include <linux/usb.h> |
| 29 | #include <linux/kfifo.h> | ||
| 29 | #include <asm/unaligned.h> | 30 | #include <asm/unaligned.h> |
| 30 | #include "hid-ids.h" | 31 | #include "hid-ids.h" |
| 31 | #include "hid-logitech-dj.h" | 32 | |
| 33 | #define DJ_MAX_PAIRED_DEVICES 6 | ||
| 34 | #define DJ_MAX_NUMBER_NOTIFICATIONS 8 | ||
| 35 | #define DJ_RECEIVER_INDEX 0 | ||
| 36 | #define DJ_DEVICE_INDEX_MIN 1 | ||
| 37 | #define DJ_DEVICE_INDEX_MAX 6 | ||
| 38 | |||
| 39 | #define DJREPORT_SHORT_LENGTH 15 | ||
| 40 | #define DJREPORT_LONG_LENGTH 32 | ||
| 41 | |||
| 42 | #define REPORT_ID_DJ_SHORT 0x20 | ||
| 43 | #define REPORT_ID_DJ_LONG 0x21 | ||
| 44 | |||
| 45 | #define REPORT_ID_HIDPP_SHORT 0x10 | ||
| 46 | #define REPORT_ID_HIDPP_LONG 0x11 | ||
| 47 | |||
| 48 | #define HIDPP_REPORT_SHORT_LENGTH 7 | ||
| 49 | #define HIDPP_REPORT_LONG_LENGTH 20 | ||
| 50 | |||
| 51 | #define HIDPP_RECEIVER_INDEX 0xff | ||
| 52 | |||
| 53 | #define REPORT_TYPE_RFREPORT_FIRST 0x01 | ||
| 54 | #define REPORT_TYPE_RFREPORT_LAST 0x1F | ||
| 55 | |||
| 56 | /* Command Switch to DJ mode */ | ||
| 57 | #define REPORT_TYPE_CMD_SWITCH 0x80 | ||
| 58 | #define CMD_SWITCH_PARAM_DEVBITFIELD 0x00 | ||
| 59 | #define CMD_SWITCH_PARAM_TIMEOUT_SECONDS 0x01 | ||
| 60 | #define TIMEOUT_NO_KEEPALIVE 0x00 | ||
| 61 | |||
| 62 | /* Command to Get the list of Paired devices */ | ||
| 63 | #define REPORT_TYPE_CMD_GET_PAIRED_DEVICES 0x81 | ||
| 64 | |||
| 65 | /* Device Paired Notification */ | ||
| 66 | #define REPORT_TYPE_NOTIF_DEVICE_PAIRED 0x41 | ||
| 67 | #define SPFUNCTION_MORE_NOTIF_EXPECTED 0x01 | ||
| 68 | #define SPFUNCTION_DEVICE_LIST_EMPTY 0x02 | ||
| 69 | #define DEVICE_PAIRED_PARAM_SPFUNCTION 0x00 | ||
| 70 | #define DEVICE_PAIRED_PARAM_EQUAD_ID_LSB 0x01 | ||
| 71 | #define DEVICE_PAIRED_PARAM_EQUAD_ID_MSB 0x02 | ||
| 72 | #define DEVICE_PAIRED_RF_REPORT_TYPE 0x03 | ||
| 73 | |||
| 74 | /* Device Un-Paired Notification */ | ||
| 75 | #define REPORT_TYPE_NOTIF_DEVICE_UNPAIRED 0x40 | ||
| 76 | |||
| 77 | |||
| 78 | /* Connection Status Notification */ | ||
| 79 | #define REPORT_TYPE_NOTIF_CONNECTION_STATUS 0x42 | ||
| 80 | #define CONNECTION_STATUS_PARAM_STATUS 0x00 | ||
| 81 | #define STATUS_LINKLOSS 0x01 | ||
| 82 | |||
| 83 | /* Error Notification */ | ||
| 84 | #define REPORT_TYPE_NOTIF_ERROR 0x7F | ||
| 85 | #define NOTIF_ERROR_PARAM_ETYPE 0x00 | ||
| 86 | #define ETYPE_KEEPALIVE_TIMEOUT 0x01 | ||
| 87 | |||
| 88 | /* supported DJ HID && RF report types */ | ||
| 89 | #define REPORT_TYPE_KEYBOARD 0x01 | ||
| 90 | #define REPORT_TYPE_MOUSE 0x02 | ||
| 91 | #define REPORT_TYPE_CONSUMER_CONTROL 0x03 | ||
| 92 | #define REPORT_TYPE_SYSTEM_CONTROL 0x04 | ||
| 93 | #define REPORT_TYPE_MEDIA_CENTER 0x08 | ||
| 94 | #define REPORT_TYPE_LEDS 0x0E | ||
| 95 | |||
| 96 | /* RF Report types bitfield */ | ||
| 97 | #define STD_KEYBOARD 0x00000002 | ||
| 98 | #define STD_MOUSE 0x00000004 | ||
| 99 | #define MULTIMEDIA 0x00000008 | ||
| 100 | #define POWER_KEYS 0x00000010 | ||
| 101 | #define MEDIA_CENTER 0x00000100 | ||
| 102 | #define KBD_LEDS 0x00004000 | ||
| 103 | |||
| 104 | struct dj_report { | ||
| 105 | u8 report_id; | ||
| 106 | u8 device_index; | ||
| 107 | u8 report_type; | ||
| 108 | u8 report_params[DJREPORT_SHORT_LENGTH - 3]; | ||
| 109 | }; | ||
| 110 | |||
| 111 | struct dj_receiver_dev { | ||
| 112 | struct hid_device *hdev; | ||
| 113 | struct dj_device *paired_dj_devices[DJ_MAX_PAIRED_DEVICES + | ||
| 114 | DJ_DEVICE_INDEX_MIN]; | ||
| 115 | struct work_struct work; | ||
| 116 | struct kfifo notif_fifo; | ||
| 117 | spinlock_t lock; | ||
| 118 | bool querying_devices; | ||
| 119 | }; | ||
| 120 | |||
| 121 | struct dj_device { | ||
| 122 | struct hid_device *hdev; | ||
| 123 | struct dj_receiver_dev *dj_receiver_dev; | ||
| 124 | u32 reports_supported; | ||
| 125 | u8 device_index; | ||
| 126 | }; | ||
| 32 | 127 | ||
| 33 | /* Keyboard descriptor (1) */ | 128 | /* Keyboard descriptor (1) */ |
| 34 | static const char kbd_descriptor[] = { | 129 | static const char kbd_descriptor[] = { |
| @@ -156,6 +251,57 @@ static const char media_descriptor[] = { | |||
| 156 | 0xc0, /* EndCollection */ | 251 | 0xc0, /* EndCollection */ |
| 157 | }; /* */ | 252 | }; /* */ |
| 158 | 253 | ||
| 254 | /* HIDPP descriptor */ | ||
| 255 | static const char hidpp_descriptor[] = { | ||
| 256 | 0x06, 0x00, 0xff, /* Usage Page (Vendor Defined Page 1) */ | ||
| 257 | 0x09, 0x01, /* Usage (Vendor Usage 1) */ | ||
| 258 | 0xa1, 0x01, /* Collection (Application) */ | ||
| 259 | 0x85, 0x10, /* Report ID (16) */ | ||
| 260 | 0x75, 0x08, /* Report Size (8) */ | ||
| 261 | 0x95, 0x06, /* Report Count (6) */ | ||
| 262 | 0x15, 0x00, /* Logical Minimum (0) */ | ||
| 263 | 0x26, 0xff, 0x00, /* Logical Maximum (255) */ | ||
| 264 | 0x09, 0x01, /* Usage (Vendor Usage 1) */ | ||
| 265 | 0x81, 0x00, /* Input (Data,Arr,Abs) */ | ||
| 266 | 0x09, 0x01, /* Usage (Vendor Usage 1) */ | ||
| 267 | 0x91, 0x00, /* Output (Data,Arr,Abs) */ | ||
| 268 | 0xc0, /* End Collection */ | ||
| 269 | 0x06, 0x00, 0xff, /* Usage Page (Vendor Defined Page 1) */ | ||
| 270 | 0x09, 0x02, /* Usage (Vendor Usage 2) */ | ||
| 271 | 0xa1, 0x01, /* Collection (Application) */ | ||
| 272 | 0x85, 0x11, /* Report ID (17) */ | ||
| 273 | 0x75, 0x08, /* Report Size (8) */ | ||
| 274 | 0x95, 0x13, /* Report Count (19) */ | ||
| 275 | 0x15, 0x00, /* Logical Minimum (0) */ | ||
| 276 | 0x26, 0xff, 0x00, /* Logical Maximum (255) */ | ||
| 277 | 0x09, 0x02, /* Usage (Vendor Usage 2) */ | ||
| 278 | 0x81, 0x00, /* Input (Data,Arr,Abs) */ | ||
| 279 | 0x09, 0x02, /* Usage (Vendor Usage 2) */ | ||
| 280 | 0x91, 0x00, /* Output (Data,Arr,Abs) */ | ||
| 281 | 0xc0, /* End Collection */ | ||
| 282 | 0x06, 0x00, 0xff, /* Usage Page (Vendor Defined Page 1) */ | ||
| 283 | 0x09, 0x04, /* Usage (Vendor Usage 0x04) */ | ||
| 284 | 0xa1, 0x01, /* Collection (Application) */ | ||
| 285 | 0x85, 0x20, /* Report ID (32) */ | ||
| 286 | 0x75, 0x08, /* Report Size (8) */ | ||
| 287 | 0x95, 0x0e, /* Report Count (14) */ | ||
| 288 | 0x15, 0x00, /* Logical Minimum (0) */ | ||
| 289 | 0x26, 0xff, 0x00, /* Logical Maximum (255) */ | ||
| 290 | 0x09, 0x41, /* Usage (Vendor Usage 0x41) */ | ||
| 291 | 0x81, 0x00, /* Input (Data,Arr,Abs) */ | ||
| 292 | 0x09, 0x41, /* Usage (Vendor Usage 0x41) */ | ||
| 293 | 0x91, 0x00, /* Output (Data,Arr,Abs) */ | ||
| 294 | 0x85, 0x21, /* Report ID (33) */ | ||
| 295 | 0x95, 0x1f, /* Report Count (31) */ | ||
| 296 | 0x15, 0x00, /* Logical Minimum (0) */ | ||
| 297 | 0x26, 0xff, 0x00, /* Logical Maximum (255) */ | ||
| 298 | 0x09, 0x42, /* Usage (Vendor Usage 0x42) */ | ||
| 299 | 0x81, 0x00, /* Input (Data,Arr,Abs) */ | ||
| 300 | 0x09, 0x42, /* Usage (Vendor Usage 0x42) */ | ||
| 301 | 0x91, 0x00, /* Output (Data,Arr,Abs) */ | ||
| 302 | 0xc0, /* End Collection */ | ||
| 303 | }; | ||
| 304 | |||
| 159 | /* Maximum size of all defined hid reports in bytes (including report id) */ | 305 | /* Maximum size of all defined hid reports in bytes (including report id) */ |
| 160 | #define MAX_REPORT_SIZE 8 | 306 | #define MAX_REPORT_SIZE 8 |
| 161 | 307 | ||
| @@ -165,7 +311,8 @@ static const char media_descriptor[] = { | |||
| 165 | sizeof(mse_descriptor) + \ | 311 | sizeof(mse_descriptor) + \ |
| 166 | sizeof(consumer_descriptor) + \ | 312 | sizeof(consumer_descriptor) + \ |
| 167 | sizeof(syscontrol_descriptor) + \ | 313 | sizeof(syscontrol_descriptor) + \ |
| 168 | sizeof(media_descriptor)) | 314 | sizeof(media_descriptor) + \ |
| 315 | sizeof(hidpp_descriptor)) | ||
| 169 | 316 | ||
| 170 | /* Number of possible hid report types that can be created by this driver. | 317 | /* Number of possible hid report types that can be created by this driver. |
| 171 | * | 318 | * |
| @@ -256,11 +403,15 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev, | |||
| 256 | dj_hiddev->dev.parent = &djrcv_hdev->dev; | 403 | dj_hiddev->dev.parent = &djrcv_hdev->dev; |
| 257 | dj_hiddev->bus = BUS_USB; | 404 | dj_hiddev->bus = BUS_USB; |
| 258 | dj_hiddev->vendor = le16_to_cpu(usbdev->descriptor.idVendor); | 405 | dj_hiddev->vendor = le16_to_cpu(usbdev->descriptor.idVendor); |
| 259 | dj_hiddev->product = le16_to_cpu(usbdev->descriptor.idProduct); | 406 | dj_hiddev->product = |
| 407 | (dj_report->report_params[DEVICE_PAIRED_PARAM_EQUAD_ID_MSB] | ||
| 408 | << 8) | | ||
| 409 | dj_report->report_params[DEVICE_PAIRED_PARAM_EQUAD_ID_LSB]; | ||
| 260 | snprintf(dj_hiddev->name, sizeof(dj_hiddev->name), | 410 | snprintf(dj_hiddev->name, sizeof(dj_hiddev->name), |
| 261 | "Logitech Unifying Device. Wireless PID:%02x%02x", | 411 | "Logitech Unifying Device. Wireless PID:%04x", |
| 262 | dj_report->report_params[DEVICE_PAIRED_PARAM_EQUAD_ID_MSB], | 412 | dj_hiddev->product); |
| 263 | dj_report->report_params[DEVICE_PAIRED_PARAM_EQUAD_ID_LSB]); | 413 | |
| 414 | dj_hiddev->group = HID_GROUP_LOGITECH_DJ_DEVICE; | ||
| 264 | 415 | ||
| 265 | usb_make_path(usbdev, dj_hiddev->phys, sizeof(dj_hiddev->phys)); | 416 | usb_make_path(usbdev, dj_hiddev->phys, sizeof(dj_hiddev->phys)); |
| 266 | snprintf(tmpstr, sizeof(tmpstr), ":%d", dj_report->device_index); | 417 | snprintf(tmpstr, sizeof(tmpstr), ":%d", dj_report->device_index); |
| @@ -422,6 +573,13 @@ static void logi_dj_recv_forward_report(struct dj_receiver_dev *djrcv_dev, | |||
| 422 | } | 573 | } |
| 423 | } | 574 | } |
| 424 | 575 | ||
| 576 | static void logi_dj_recv_forward_hidpp(struct dj_device *dj_dev, u8 *data, | ||
| 577 | int size) | ||
| 578 | { | ||
| 579 | /* We are called from atomic context (tasklet && djrcv->lock held) */ | ||
| 580 | if (hid_input_report(dj_dev->hdev, HID_INPUT_REPORT, data, size, 1)) | ||
| 581 | dbg_hid("hid_input_report error\n"); | ||
| 582 | } | ||
| 425 | 583 | ||
| 426 | static int logi_dj_recv_send_report(struct dj_receiver_dev *djrcv_dev, | 584 | static int logi_dj_recv_send_report(struct dj_receiver_dev *djrcv_dev, |
| 427 | struct dj_report *dj_report) | 585 | struct dj_report *dj_report) |
| @@ -472,7 +630,9 @@ static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev) | |||
| 472 | static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev, | 630 | static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev, |
| 473 | unsigned timeout) | 631 | unsigned timeout) |
| 474 | { | 632 | { |
| 633 | struct hid_device *hdev = djrcv_dev->hdev; | ||
| 475 | struct dj_report *dj_report; | 634 | struct dj_report *dj_report; |
| 635 | u8 *buf; | ||
| 476 | int retval; | 636 | int retval; |
| 477 | 637 | ||
| 478 | dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL); | 638 | dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL); |
| @@ -484,7 +644,6 @@ static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev, | |||
| 484 | dj_report->report_params[CMD_SWITCH_PARAM_DEVBITFIELD] = 0x3F; | 644 | dj_report->report_params[CMD_SWITCH_PARAM_DEVBITFIELD] = 0x3F; |
| 485 | dj_report->report_params[CMD_SWITCH_PARAM_TIMEOUT_SECONDS] = (u8)timeout; | 645 | dj_report->report_params[CMD_SWITCH_PARAM_TIMEOUT_SECONDS] = (u8)timeout; |
| 486 | retval = logi_dj_recv_send_report(djrcv_dev, dj_report); | 646 | retval = logi_dj_recv_send_report(djrcv_dev, dj_report); |
| 487 | kfree(dj_report); | ||
| 488 | 647 | ||
| 489 | /* | 648 | /* |
| 490 | * Ugly sleep to work around a USB 3.0 bug when the receiver is still | 649 | * Ugly sleep to work around a USB 3.0 bug when the receiver is still |
| @@ -493,6 +652,30 @@ static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev, | |||
| 493 | */ | 652 | */ |
| 494 | msleep(50); | 653 | msleep(50); |
| 495 | 654 | ||
| 655 | /* | ||
| 656 | * Magical bits to set up hidpp notifications when the dj devices | ||
| 657 | * are connected/disconnected. | ||
| 658 | * | ||
| 659 | * We can reuse dj_report because HIDPP_REPORT_SHORT_LENGTH is smaller | ||
| 660 | * than DJREPORT_SHORT_LENGTH. | ||
| 661 | */ | ||
| 662 | buf = (u8 *)dj_report; | ||
| 663 | |||
| 664 | memset(buf, 0, HIDPP_REPORT_SHORT_LENGTH); | ||
| 665 | |||
| 666 | buf[0] = REPORT_ID_HIDPP_SHORT; | ||
| 667 | buf[1] = 0xFF; | ||
| 668 | buf[2] = 0x80; | ||
| 669 | buf[3] = 0x00; | ||
| 670 | buf[4] = 0x00; | ||
| 671 | buf[5] = 0x09; | ||
| 672 | buf[6] = 0x00; | ||
| 673 | |||
| 674 | hid_hw_raw_request(hdev, REPORT_ID_HIDPP_SHORT, buf, | ||
| 675 | HIDPP_REPORT_SHORT_LENGTH, HID_OUTPUT_REPORT, | ||
| 676 | HID_REQ_SET_REPORT); | ||
| 677 | |||
| 678 | kfree(dj_report); | ||
| 496 | return retval; | 679 | return retval; |
| 497 | } | 680 | } |
| 498 | 681 | ||
| @@ -509,6 +692,9 @@ static void logi_dj_ll_close(struct hid_device *hid) | |||
| 509 | dbg_hid("%s:%s\n", __func__, hid->phys); | 692 | dbg_hid("%s:%s\n", __func__, hid->phys); |
| 510 | } | 693 | } |
| 511 | 694 | ||
| 695 | static u8 unifying_name_query[] = {0x10, 0xff, 0x83, 0xb5, 0x40, 0x00, 0x00}; | ||
| 696 | static u8 unifying_name_answer[] = {0x11, 0xff, 0x83, 0xb5}; | ||
| 697 | |||
| 512 | static int logi_dj_ll_raw_request(struct hid_device *hid, | 698 | static int logi_dj_ll_raw_request(struct hid_device *hid, |
| 513 | unsigned char reportnum, __u8 *buf, | 699 | unsigned char reportnum, __u8 *buf, |
| 514 | size_t count, unsigned char report_type, | 700 | size_t count, unsigned char report_type, |
| @@ -519,6 +705,22 @@ static int logi_dj_ll_raw_request(struct hid_device *hid, | |||
| 519 | u8 *out_buf; | 705 | u8 *out_buf; |
| 520 | int ret; | 706 | int ret; |
| 521 | 707 | ||
| 708 | if ((buf[0] == REPORT_ID_HIDPP_SHORT) || | ||
| 709 | (buf[0] == REPORT_ID_HIDPP_LONG)) { | ||
| 710 | if (count < 2) | ||
| 711 | return -EINVAL; | ||
| 712 | |||
| 713 | /* special case where we should not overwrite | ||
| 714 | * the device_index */ | ||
| 715 | if (count == 7 && !memcmp(buf, unifying_name_query, | ||
| 716 | sizeof(unifying_name_query))) | ||
| 717 | buf[4] |= djdev->device_index - 1; | ||
| 718 | else | ||
| 719 | buf[1] = djdev->device_index; | ||
| 720 | return hid_hw_raw_request(djrcv_dev->hdev, reportnum, buf, | ||
| 721 | count, report_type, reqtype); | ||
| 722 | } | ||
| 723 | |||
| 522 | if (buf[0] != REPORT_TYPE_LEDS) | 724 | if (buf[0] != REPORT_TYPE_LEDS) |
| 523 | return -EINVAL; | 725 | return -EINVAL; |
| 524 | 726 | ||
| @@ -597,6 +799,8 @@ static int logi_dj_ll_parse(struct hid_device *hid) | |||
| 597 | __func__, djdev->reports_supported); | 799 | __func__, djdev->reports_supported); |
| 598 | } | 800 | } |
| 599 | 801 | ||
| 802 | rdcat(rdesc, &rsize, hidpp_descriptor, sizeof(hidpp_descriptor)); | ||
| 803 | |||
| 600 | retval = hid_parse_report(hid, rdesc, rsize); | 804 | retval = hid_parse_report(hid, rdesc, rsize); |
| 601 | kfree(rdesc); | 805 | kfree(rdesc); |
| 602 | 806 | ||
| @@ -624,8 +828,7 @@ static struct hid_ll_driver logi_dj_ll_driver = { | |||
| 624 | .raw_request = logi_dj_ll_raw_request, | 828 | .raw_request = logi_dj_ll_raw_request, |
| 625 | }; | 829 | }; |
| 626 | 830 | ||
| 627 | 831 | static int logi_dj_dj_event(struct hid_device *hdev, | |
| 628 | static int logi_dj_raw_event(struct hid_device *hdev, | ||
| 629 | struct hid_report *report, u8 *data, | 832 | struct hid_report *report, u8 *data, |
| 630 | int size) | 833 | int size) |
| 631 | { | 834 | { |
| @@ -633,36 +836,24 @@ static int logi_dj_raw_event(struct hid_device *hdev, | |||
| 633 | struct dj_report *dj_report = (struct dj_report *) data; | 836 | struct dj_report *dj_report = (struct dj_report *) data; |
| 634 | unsigned long flags; | 837 | unsigned long flags; |
| 635 | 838 | ||
| 636 | dbg_hid("%s, size:%d\n", __func__, size); | 839 | /* |
| 637 | 840 | * Here we receive all data coming from iface 2, there are 3 cases: | |
| 638 | /* Here we receive all data coming from iface 2, there are 4 cases: | ||
| 639 | * | ||
| 640 | * 1) Data should continue its normal processing i.e. data does not | ||
| 641 | * come from the DJ collection, in which case we do nothing and | ||
| 642 | * return 0, so hid-core can continue normal processing (will forward | ||
| 643 | * to associated hidraw device) | ||
| 644 | * | 841 | * |
| 645 | * 2) Data is from DJ collection, and is intended for this driver i. e. | 842 | * 1) Data is intended for this driver i. e. data contains arrival, |
| 646 | * data contains arrival, departure, etc notifications, in which case | 843 | * departure, etc notifications, in which case we queue them for delayed |
| 647 | * we queue them for delayed processing by the work queue. We return 1 | 844 | * processing by the work queue. We return 1 to hid-core as no further |
| 648 | * to hid-core as no further processing is required from it. | 845 | * processing is required from it. |
| 649 | * | 846 | * |
| 650 | * 3) Data is from DJ collection, and informs a connection change, | 847 | * 2) Data informs a connection change, if the change means rf link |
| 651 | * if the change means rf link loss, then we must send a null report | 848 | * loss, then we must send a null report to the upper layer to discard |
| 652 | * to the upper layer to discard potentially pressed keys that may be | 849 | * potentially pressed keys that may be repeated forever by the input |
| 653 | * repeated forever by the input layer. Return 1 to hid-core as no | 850 | * layer. Return 1 to hid-core as no further processing is required. |
| 654 | * further processing is required. | ||
| 655 | * | 851 | * |
| 656 | * 4) Data is from DJ collection and is an actual input event from | 852 | * 3) Data is an actual input event from a paired DJ device in which |
| 657 | * a paired DJ device in which case we forward it to the correct hid | 853 | * case we forward it to the correct hid device (via hid_input_report() |
| 658 | * device (via hid_input_report() ) and return 1 so hid-core does not do | 854 | * ) and return 1 so hid-core does not anything else with it. |
| 659 | * anything else with it. | ||
| 660 | */ | 855 | */ |
| 661 | 856 | ||
| 662 | /* case 1) */ | ||
| 663 | if (data[0] != REPORT_ID_DJ_SHORT) | ||
| 664 | return false; | ||
| 665 | |||
| 666 | if ((dj_report->device_index < DJ_DEVICE_INDEX_MIN) || | 857 | if ((dj_report->device_index < DJ_DEVICE_INDEX_MIN) || |
| 667 | (dj_report->device_index > DJ_DEVICE_INDEX_MAX)) { | 858 | (dj_report->device_index > DJ_DEVICE_INDEX_MAX)) { |
| 668 | /* | 859 | /* |
| @@ -707,6 +898,80 @@ out: | |||
| 707 | return true; | 898 | return true; |
| 708 | } | 899 | } |
| 709 | 900 | ||
| 901 | static int logi_dj_hidpp_event(struct hid_device *hdev, | ||
| 902 | struct hid_report *report, u8 *data, | ||
| 903 | int size) | ||
| 904 | { | ||
| 905 | struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev); | ||
| 906 | struct dj_report *dj_report = (struct dj_report *) data; | ||
| 907 | unsigned long flags; | ||
| 908 | u8 device_index = dj_report->device_index; | ||
| 909 | |||
| 910 | if (device_index == HIDPP_RECEIVER_INDEX) { | ||
| 911 | /* special case were the device wants to know its unifying | ||
| 912 | * name */ | ||
| 913 | if (size == HIDPP_REPORT_LONG_LENGTH && | ||
| 914 | !memcmp(data, unifying_name_answer, | ||
| 915 | sizeof(unifying_name_answer)) && | ||
| 916 | ((data[4] & 0xF0) == 0x40)) | ||
| 917 | device_index = (data[4] & 0x0F) + 1; | ||
| 918 | else | ||
| 919 | return false; | ||
| 920 | } | ||
| 921 | |||
| 922 | /* | ||
| 923 | * Data is from the HID++ collection, in this case, we forward the | ||
| 924 | * data to the corresponding child dj device and return 0 to hid-core | ||
| 925 | * so he data also goes to the hidraw device of the receiver. This | ||
| 926 | * allows a user space application to implement the full HID++ routing | ||
| 927 | * via the receiver. | ||
| 928 | */ | ||
| 929 | |||
| 930 | if ((device_index < DJ_DEVICE_INDEX_MIN) || | ||
| 931 | (device_index > DJ_DEVICE_INDEX_MAX)) { | ||
| 932 | /* | ||
| 933 | * Device index is wrong, bail out. | ||
| 934 | * This driver can ignore safely the receiver notifications, | ||
| 935 | * so ignore those reports too. | ||
| 936 | */ | ||
| 937 | dev_err(&hdev->dev, "%s: invalid device index:%d\n", | ||
| 938 | __func__, dj_report->device_index); | ||
| 939 | return false; | ||
| 940 | } | ||
| 941 | |||
| 942 | spin_lock_irqsave(&djrcv_dev->lock, flags); | ||
| 943 | |||
| 944 | if (!djrcv_dev->paired_dj_devices[device_index]) | ||
| 945 | /* received an event for an unknown device, bail out */ | ||
| 946 | goto out; | ||
| 947 | |||
| 948 | logi_dj_recv_forward_hidpp(djrcv_dev->paired_dj_devices[device_index], | ||
| 949 | data, size); | ||
| 950 | |||
| 951 | out: | ||
| 952 | spin_unlock_irqrestore(&djrcv_dev->lock, flags); | ||
| 953 | |||
| 954 | return false; | ||
| 955 | } | ||
| 956 | |||
| 957 | static int logi_dj_raw_event(struct hid_device *hdev, | ||
| 958 | struct hid_report *report, u8 *data, | ||
| 959 | int size) | ||
| 960 | { | ||
| 961 | dbg_hid("%s, size:%d\n", __func__, size); | ||
| 962 | |||
| 963 | switch (data[0]) { | ||
| 964 | case REPORT_ID_DJ_SHORT: | ||
| 965 | return logi_dj_dj_event(hdev, report, data, size); | ||
| 966 | case REPORT_ID_HIDPP_SHORT: | ||
| 967 | /* intentional fallthrough */ | ||
| 968 | case REPORT_ID_HIDPP_LONG: | ||
| 969 | return logi_dj_hidpp_event(hdev, report, data, size); | ||
| 970 | } | ||
| 971 | |||
| 972 | return false; | ||
| 973 | } | ||
| 974 | |||
| 710 | static int logi_dj_probe(struct hid_device *hdev, | 975 | static int logi_dj_probe(struct hid_device *hdev, |
| 711 | const struct hid_device_id *id) | 976 | const struct hid_device_id *id) |
| 712 | { | 977 | { |
| @@ -714,9 +979,6 @@ static int logi_dj_probe(struct hid_device *hdev, | |||
| 714 | struct dj_receiver_dev *djrcv_dev; | 979 | struct dj_receiver_dev *djrcv_dev; |
| 715 | int retval; | 980 | int retval; |
| 716 | 981 | ||
| 717 | if (is_dj_device((struct dj_device *)hdev->driver_data)) | ||
| 718 | return -ENODEV; | ||
| 719 | |||
| 720 | dbg_hid("%s called for ifnum %d\n", __func__, | 982 | dbg_hid("%s called for ifnum %d\n", __func__, |
| 721 | intf->cur_altsetting->desc.bInterfaceNumber); | 983 | intf->cur_altsetting->desc.bInterfaceNumber); |
| 722 | 984 | ||
| @@ -869,22 +1131,6 @@ static void logi_dj_remove(struct hid_device *hdev) | |||
| 869 | hid_set_drvdata(hdev, NULL); | 1131 | hid_set_drvdata(hdev, NULL); |
| 870 | } | 1132 | } |
| 871 | 1133 | ||
| 872 | static int logi_djdevice_probe(struct hid_device *hdev, | ||
| 873 | const struct hid_device_id *id) | ||
| 874 | { | ||
| 875 | int ret; | ||
| 876 | struct dj_device *dj_dev = hdev->driver_data; | ||
| 877 | |||
| 878 | if (!is_dj_device(dj_dev)) | ||
| 879 | return -ENODEV; | ||
| 880 | |||
| 881 | ret = hid_parse(hdev); | ||
| 882 | if (!ret) | ||
| 883 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); | ||
| 884 | |||
| 885 | return ret; | ||
| 886 | } | ||
| 887 | |||
| 888 | static const struct hid_device_id logi_dj_receivers[] = { | 1134 | static const struct hid_device_id logi_dj_receivers[] = { |
| 889 | {HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, | 1135 | {HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, |
| 890 | USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER)}, | 1136 | USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER)}, |
| @@ -906,51 +1152,8 @@ static struct hid_driver logi_djreceiver_driver = { | |||
| 906 | #endif | 1152 | #endif |
| 907 | }; | 1153 | }; |
| 908 | 1154 | ||
| 1155 | module_hid_driver(logi_djreceiver_driver); | ||
| 909 | 1156 | ||
| 910 | static const struct hid_device_id logi_dj_devices[] = { | ||
| 911 | {HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, | ||
| 912 | USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER)}, | ||
| 913 | {HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, | ||
| 914 | USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER_2)}, | ||
| 915 | {} | ||
| 916 | }; | ||
| 917 | |||
| 918 | static struct hid_driver logi_djdevice_driver = { | ||
| 919 | .name = "logitech-djdevice", | ||
| 920 | .id_table = logi_dj_devices, | ||
| 921 | .probe = logi_djdevice_probe, | ||
| 922 | }; | ||
| 923 | |||
| 924 | |||
| 925 | static int __init logi_dj_init(void) | ||
| 926 | { | ||
| 927 | int retval; | ||
| 928 | |||
| 929 | dbg_hid("Logitech-DJ:%s\n", __func__); | ||
| 930 | |||
| 931 | retval = hid_register_driver(&logi_djreceiver_driver); | ||
| 932 | if (retval) | ||
| 933 | return retval; | ||
| 934 | |||
| 935 | retval = hid_register_driver(&logi_djdevice_driver); | ||
| 936 | if (retval) | ||
| 937 | hid_unregister_driver(&logi_djreceiver_driver); | ||
| 938 | |||
| 939 | return retval; | ||
| 940 | |||
| 941 | } | ||
| 942 | |||
| 943 | static void __exit logi_dj_exit(void) | ||
| 944 | { | ||
| 945 | dbg_hid("Logitech-DJ:%s\n", __func__); | ||
| 946 | |||
| 947 | hid_unregister_driver(&logi_djdevice_driver); | ||
| 948 | hid_unregister_driver(&logi_djreceiver_driver); | ||
| 949 | |||
| 950 | } | ||
| 951 | |||
| 952 | module_init(logi_dj_init); | ||
| 953 | module_exit(logi_dj_exit); | ||
| 954 | MODULE_LICENSE("GPL"); | 1157 | MODULE_LICENSE("GPL"); |
| 955 | MODULE_AUTHOR("Logitech"); | 1158 | MODULE_AUTHOR("Logitech"); |
| 956 | MODULE_AUTHOR("Nestor Lopez Casado"); | 1159 | MODULE_AUTHOR("Nestor Lopez Casado"); |
diff --git a/drivers/hid/hid-logitech-dj.h b/drivers/hid/hid-logitech-dj.h deleted file mode 100644 index daeb0aa4bee9..000000000000 --- a/drivers/hid/hid-logitech-dj.h +++ /dev/null | |||
| @@ -1,125 +0,0 @@ | |||
| 1 | #ifndef __HID_LOGITECH_DJ_H | ||
| 2 | #define __HID_LOGITECH_DJ_H | ||
| 3 | |||
| 4 | /* | ||
| 5 | * HID driver for Logitech Unifying receivers | ||
| 6 | * | ||
| 7 | * Copyright (c) 2011 Logitech | ||
| 8 | */ | ||
| 9 | |||
| 10 | /* | ||
| 11 | * This program is free software; you can redistribute it and/or modify | ||
| 12 | * it under the terms of the GNU General Public License version 2 as | ||
| 13 | * published by the Free Software Foundation. | ||
| 14 | * | ||
| 15 | * This program is distributed in the hope that it will be useful, | ||
| 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 18 | * GNU General Public License for more details. | ||
| 19 | * | ||
| 20 | * You should have received a copy of the GNU General Public License | ||
| 21 | * along with this program; if not, write to the Free Software | ||
| 22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 23 | * | ||
| 24 | */ | ||
| 25 | |||
| 26 | #include <linux/kfifo.h> | ||
| 27 | |||
| 28 | #define DJ_MAX_PAIRED_DEVICES 6 | ||
| 29 | #define DJ_MAX_NUMBER_NOTIFICATIONS 8 | ||
| 30 | #define DJ_RECEIVER_INDEX 0 | ||
| 31 | #define DJ_DEVICE_INDEX_MIN 1 | ||
| 32 | #define DJ_DEVICE_INDEX_MAX 6 | ||
| 33 | |||
| 34 | #define DJREPORT_SHORT_LENGTH 15 | ||
| 35 | #define DJREPORT_LONG_LENGTH 32 | ||
| 36 | |||
| 37 | #define REPORT_ID_DJ_SHORT 0x20 | ||
| 38 | #define REPORT_ID_DJ_LONG 0x21 | ||
| 39 | |||
| 40 | #define REPORT_TYPE_RFREPORT_FIRST 0x01 | ||
| 41 | #define REPORT_TYPE_RFREPORT_LAST 0x1F | ||
| 42 | |||
| 43 | /* Command Switch to DJ mode */ | ||
| 44 | #define REPORT_TYPE_CMD_SWITCH 0x80 | ||
| 45 | #define CMD_SWITCH_PARAM_DEVBITFIELD 0x00 | ||
| 46 | #define CMD_SWITCH_PARAM_TIMEOUT_SECONDS 0x01 | ||
| 47 | #define TIMEOUT_NO_KEEPALIVE 0x00 | ||
| 48 | |||
| 49 | /* Command to Get the list of Paired devices */ | ||
| 50 | #define REPORT_TYPE_CMD_GET_PAIRED_DEVICES 0x81 | ||
| 51 | |||
| 52 | /* Device Paired Notification */ | ||
| 53 | #define REPORT_TYPE_NOTIF_DEVICE_PAIRED 0x41 | ||
| 54 | #define SPFUNCTION_MORE_NOTIF_EXPECTED 0x01 | ||
| 55 | #define SPFUNCTION_DEVICE_LIST_EMPTY 0x02 | ||
| 56 | #define DEVICE_PAIRED_PARAM_SPFUNCTION 0x00 | ||
| 57 | #define DEVICE_PAIRED_PARAM_EQUAD_ID_LSB 0x01 | ||
| 58 | #define DEVICE_PAIRED_PARAM_EQUAD_ID_MSB 0x02 | ||
| 59 | #define DEVICE_PAIRED_RF_REPORT_TYPE 0x03 | ||
| 60 | |||
| 61 | /* Device Un-Paired Notification */ | ||
| 62 | #define REPORT_TYPE_NOTIF_DEVICE_UNPAIRED 0x40 | ||
| 63 | |||
| 64 | |||
| 65 | /* Connection Status Notification */ | ||
| 66 | #define REPORT_TYPE_NOTIF_CONNECTION_STATUS 0x42 | ||
| 67 | #define CONNECTION_STATUS_PARAM_STATUS 0x00 | ||
| 68 | #define STATUS_LINKLOSS 0x01 | ||
| 69 | |||
| 70 | /* Error Notification */ | ||
| 71 | #define REPORT_TYPE_NOTIF_ERROR 0x7F | ||
| 72 | #define NOTIF_ERROR_PARAM_ETYPE 0x00 | ||
| 73 | #define ETYPE_KEEPALIVE_TIMEOUT 0x01 | ||
| 74 | |||
| 75 | /* supported DJ HID && RF report types */ | ||
| 76 | #define REPORT_TYPE_KEYBOARD 0x01 | ||
| 77 | #define REPORT_TYPE_MOUSE 0x02 | ||
| 78 | #define REPORT_TYPE_CONSUMER_CONTROL 0x03 | ||
| 79 | #define REPORT_TYPE_SYSTEM_CONTROL 0x04 | ||
| 80 | #define REPORT_TYPE_MEDIA_CENTER 0x08 | ||
| 81 | #define REPORT_TYPE_LEDS 0x0E | ||
| 82 | |||
| 83 | /* RF Report types bitfield */ | ||
| 84 | #define STD_KEYBOARD 0x00000002 | ||
| 85 | #define STD_MOUSE 0x00000004 | ||
| 86 | #define MULTIMEDIA 0x00000008 | ||
| 87 | #define POWER_KEYS 0x00000010 | ||
| 88 | #define MEDIA_CENTER 0x00000100 | ||
| 89 | #define KBD_LEDS 0x00004000 | ||
| 90 | |||
| 91 | struct dj_report { | ||
| 92 | u8 report_id; | ||
| 93 | u8 device_index; | ||
| 94 | u8 report_type; | ||
| 95 | u8 report_params[DJREPORT_SHORT_LENGTH - 3]; | ||
| 96 | }; | ||
| 97 | |||
| 98 | struct dj_receiver_dev { | ||
| 99 | struct hid_device *hdev; | ||
| 100 | struct dj_device *paired_dj_devices[DJ_MAX_PAIRED_DEVICES + | ||
| 101 | DJ_DEVICE_INDEX_MIN]; | ||
| 102 | struct work_struct work; | ||
| 103 | struct kfifo notif_fifo; | ||
| 104 | spinlock_t lock; | ||
| 105 | bool querying_devices; | ||
| 106 | }; | ||
| 107 | |||
| 108 | struct dj_device { | ||
| 109 | struct hid_device *hdev; | ||
| 110 | struct dj_receiver_dev *dj_receiver_dev; | ||
| 111 | u32 reports_supported; | ||
| 112 | u8 device_index; | ||
| 113 | }; | ||
| 114 | |||
| 115 | /** | ||
| 116 | * is_dj_device - know if the given dj_device is not the receiver. | ||
| 117 | * @dj_dev: the dj device to test | ||
| 118 | * | ||
| 119 | * This macro tests if a struct dj_device pointer is a device created | ||
| 120 | * by the bus enumarator. | ||
| 121 | */ | ||
| 122 | #define is_dj_device(dj_dev) \ | ||
| 123 | (&(dj_dev)->dj_receiver_dev->hdev->dev == (dj_dev)->hdev->dev.parent) | ||
| 124 | |||
| 125 | #endif | ||
diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c new file mode 100644 index 000000000000..2f420c0b6609 --- /dev/null +++ b/drivers/hid/hid-logitech-hidpp.c | |||
| @@ -0,0 +1,1241 @@ | |||
| 1 | /* | ||
| 2 | * HIDPP protocol for Logitech Unifying receivers | ||
| 3 | * | ||
| 4 | * Copyright (c) 2011 Logitech (c) | ||
| 5 | * Copyright (c) 2012-2013 Google (c) | ||
| 6 | * Copyright (c) 2013-2014 Red Hat Inc. | ||
| 7 | */ | ||
| 8 | |||
| 9 | /* | ||
| 10 | * This program is free software; you can redistribute it and/or modify it | ||
| 11 | * under the terms of the GNU General Public License as published by the Free | ||
| 12 | * Software Foundation; version 2 of the License. | ||
| 13 | */ | ||
| 14 | |||
| 15 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 16 | |||
| 17 | #include <linux/device.h> | ||
| 18 | #include <linux/hid.h> | ||
| 19 | #include <linux/module.h> | ||
| 20 | #include <linux/slab.h> | ||
| 21 | #include <linux/sched.h> | ||
| 22 | #include <linux/kfifo.h> | ||
| 23 | #include <linux/input/mt.h> | ||
| 24 | #include <asm/unaligned.h> | ||
| 25 | #include "hid-ids.h" | ||
| 26 | |||
| 27 | MODULE_LICENSE("GPL"); | ||
| 28 | MODULE_AUTHOR("Benjamin Tissoires <benjamin.tissoires@gmail.com>"); | ||
| 29 | MODULE_AUTHOR("Nestor Lopez Casado <nlopezcasad@logitech.com>"); | ||
| 30 | |||
| 31 | #define REPORT_ID_HIDPP_SHORT 0x10 | ||
| 32 | #define REPORT_ID_HIDPP_LONG 0x11 | ||
| 33 | |||
| 34 | #define HIDPP_REPORT_SHORT_LENGTH 7 | ||
| 35 | #define HIDPP_REPORT_LONG_LENGTH 20 | ||
| 36 | |||
| 37 | #define HIDPP_QUIRK_CLASS_WTP BIT(0) | ||
| 38 | |||
| 39 | /* bits 1..20 are reserved for classes */ | ||
| 40 | #define HIDPP_QUIRK_DELAYED_INIT BIT(21) | ||
| 41 | #define HIDPP_QUIRK_WTP_PHYSICAL_BUTTONS BIT(22) | ||
| 42 | #define HIDPP_QUIRK_MULTI_INPUT BIT(23) | ||
| 43 | |||
| 44 | /* | ||
| 45 | * There are two hidpp protocols in use, the first version hidpp10 is known | ||
| 46 | * as register access protocol or RAP, the second version hidpp20 is known as | ||
| 47 | * feature access protocol or FAP | ||
| 48 | * | ||
| 49 | * Most older devices (including the Unifying usb receiver) use the RAP protocol | ||
| 50 | * where as most newer devices use the FAP protocol. Both protocols are | ||
| 51 | * compatible with the underlying transport, which could be usb, Unifiying, or | ||
| 52 | * bluetooth. The message lengths are defined by the hid vendor specific report | ||
| 53 | * descriptor for the HIDPP_SHORT report type (total message lenth 7 bytes) and | ||
| 54 | * the HIDPP_LONG report type (total message length 20 bytes) | ||
| 55 | * | ||
| 56 | * The RAP protocol uses both report types, whereas the FAP only uses HIDPP_LONG | ||
| 57 | * messages. The Unifying receiver itself responds to RAP messages (device index | ||
| 58 | * is 0xFF for the receiver), and all messages (short or long) with a device | ||
| 59 | * index between 1 and 6 are passed untouched to the corresponding paired | ||
| 60 | * Unifying device. | ||
| 61 | * | ||
| 62 | * The paired device can be RAP or FAP, it will receive the message untouched | ||
| 63 | * from the Unifiying receiver. | ||
| 64 | */ | ||
| 65 | |||
| 66 | struct fap { | ||
| 67 | u8 feature_index; | ||
| 68 | u8 funcindex_clientid; | ||
| 69 | u8 params[HIDPP_REPORT_LONG_LENGTH - 4U]; | ||
| 70 | }; | ||
| 71 | |||
| 72 | struct rap { | ||
| 73 | u8 sub_id; | ||
| 74 | u8 reg_address; | ||
| 75 | u8 params[HIDPP_REPORT_LONG_LENGTH - 4U]; | ||
| 76 | }; | ||
| 77 | |||
| 78 | struct hidpp_report { | ||
| 79 | u8 report_id; | ||
| 80 | u8 device_index; | ||
| 81 | union { | ||
| 82 | struct fap fap; | ||
| 83 | struct rap rap; | ||
| 84 | u8 rawbytes[sizeof(struct fap)]; | ||
| 85 | }; | ||
| 86 | } __packed; | ||
| 87 | |||
| 88 | struct hidpp_device { | ||
| 89 | struct hid_device *hid_dev; | ||
| 90 | struct mutex send_mutex; | ||
| 91 | void *send_receive_buf; | ||
| 92 | wait_queue_head_t wait; | ||
| 93 | bool answer_available; | ||
| 94 | u8 protocol_major; | ||
| 95 | u8 protocol_minor; | ||
| 96 | |||
| 97 | void *private_data; | ||
| 98 | |||
| 99 | struct work_struct work; | ||
| 100 | struct kfifo delayed_work_fifo; | ||
| 101 | atomic_t connected; | ||
| 102 | struct input_dev *delayed_input; | ||
| 103 | |||
| 104 | unsigned long quirks; | ||
| 105 | }; | ||
| 106 | |||
| 107 | |||
| 108 | #define HIDPP_ERROR 0x8f | ||
| 109 | #define HIDPP_ERROR_SUCCESS 0x00 | ||
| 110 | #define HIDPP_ERROR_INVALID_SUBID 0x01 | ||
| 111 | #define HIDPP_ERROR_INVALID_ADRESS 0x02 | ||
| 112 | #define HIDPP_ERROR_INVALID_VALUE 0x03 | ||
| 113 | #define HIDPP_ERROR_CONNECT_FAIL 0x04 | ||
| 114 | #define HIDPP_ERROR_TOO_MANY_DEVICES 0x05 | ||
| 115 | #define HIDPP_ERROR_ALREADY_EXISTS 0x06 | ||
| 116 | #define HIDPP_ERROR_BUSY 0x07 | ||
| 117 | #define HIDPP_ERROR_UNKNOWN_DEVICE 0x08 | ||
| 118 | #define HIDPP_ERROR_RESOURCE_ERROR 0x09 | ||
| 119 | #define HIDPP_ERROR_REQUEST_UNAVAILABLE 0x0a | ||
| 120 | #define HIDPP_ERROR_INVALID_PARAM_VALUE 0x0b | ||
| 121 | #define HIDPP_ERROR_WRONG_PIN_CODE 0x0c | ||
| 122 | |||
| 123 | static void hidpp_connect_event(struct hidpp_device *hidpp_dev); | ||
| 124 | |||
| 125 | static int __hidpp_send_report(struct hid_device *hdev, | ||
| 126 | struct hidpp_report *hidpp_report) | ||
| 127 | { | ||
| 128 | int fields_count, ret; | ||
| 129 | |||
| 130 | switch (hidpp_report->report_id) { | ||
| 131 | case REPORT_ID_HIDPP_SHORT: | ||
| 132 | fields_count = HIDPP_REPORT_SHORT_LENGTH; | ||
| 133 | break; | ||
| 134 | case REPORT_ID_HIDPP_LONG: | ||
| 135 | fields_count = HIDPP_REPORT_LONG_LENGTH; | ||
| 136 | break; | ||
| 137 | default: | ||
| 138 | return -ENODEV; | ||
| 139 | } | ||
| 140 | |||
| 141 | /* | ||
| 142 | * set the device_index as the receiver, it will be overwritten by | ||
| 143 | * hid_hw_request if needed | ||
| 144 | */ | ||
| 145 | hidpp_report->device_index = 0xff; | ||
| 146 | |||
| 147 | ret = hid_hw_raw_request(hdev, hidpp_report->report_id, | ||
| 148 | (u8 *)hidpp_report, fields_count, HID_OUTPUT_REPORT, | ||
| 149 | HID_REQ_SET_REPORT); | ||
| 150 | |||
| 151 | return ret == fields_count ? 0 : -1; | ||
| 152 | } | ||
| 153 | |||
| 154 | /** | ||
| 155 | * hidpp_send_message_sync() returns 0 in case of success, and something else | ||
| 156 | * in case of a failure. | ||
| 157 | * - If ' something else' is positive, that means that an error has been raised | ||
| 158 | * by the protocol itself. | ||
| 159 | * - If ' something else' is negative, that means that we had a classic error | ||
| 160 | * (-ENOMEM, -EPIPE, etc...) | ||
| 161 | */ | ||
| 162 | static int hidpp_send_message_sync(struct hidpp_device *hidpp, | ||
| 163 | struct hidpp_report *message, | ||
| 164 | struct hidpp_report *response) | ||
| 165 | { | ||
| 166 | int ret; | ||
| 167 | |||
| 168 | mutex_lock(&hidpp->send_mutex); | ||
| 169 | |||
| 170 | hidpp->send_receive_buf = response; | ||
| 171 | hidpp->answer_available = false; | ||
| 172 | |||
| 173 | /* | ||
| 174 | * So that we can later validate the answer when it arrives | ||
| 175 | * in hidpp_raw_event | ||
| 176 | */ | ||
| 177 | *response = *message; | ||
| 178 | |||
| 179 | ret = __hidpp_send_report(hidpp->hid_dev, message); | ||
| 180 | |||
| 181 | if (ret) { | ||
| 182 | dbg_hid("__hidpp_send_report returned err: %d\n", ret); | ||
| 183 | memset(response, 0, sizeof(struct hidpp_report)); | ||
| 184 | goto exit; | ||
| 185 | } | ||
| 186 | |||
| 187 | if (!wait_event_timeout(hidpp->wait, hidpp->answer_available, | ||
| 188 | 5*HZ)) { | ||
| 189 | dbg_hid("%s:timeout waiting for response\n", __func__); | ||
| 190 | memset(response, 0, sizeof(struct hidpp_report)); | ||
| 191 | ret = -ETIMEDOUT; | ||
| 192 | } | ||
| 193 | |||
| 194 | if (response->report_id == REPORT_ID_HIDPP_SHORT && | ||
| 195 | response->fap.feature_index == HIDPP_ERROR) { | ||
| 196 | ret = response->fap.params[1]; | ||
| 197 | dbg_hid("__hidpp_send_report got hidpp error %02X\n", ret); | ||
| 198 | goto exit; | ||
| 199 | } | ||
| 200 | |||
| 201 | exit: | ||
| 202 | mutex_unlock(&hidpp->send_mutex); | ||
| 203 | return ret; | ||
| 204 | |||
| 205 | } | ||
| 206 | |||
| 207 | static int hidpp_send_fap_command_sync(struct hidpp_device *hidpp, | ||
| 208 | u8 feat_index, u8 funcindex_clientid, u8 *params, int param_count, | ||
| 209 | struct hidpp_report *response) | ||
| 210 | { | ||
| 211 | struct hidpp_report *message; | ||
| 212 | int ret; | ||
| 213 | |||
| 214 | if (param_count > sizeof(message->fap.params)) | ||
| 215 | return -EINVAL; | ||
| 216 | |||
| 217 | message = kzalloc(sizeof(struct hidpp_report), GFP_KERNEL); | ||
| 218 | if (!message) | ||
| 219 | return -ENOMEM; | ||
| 220 | message->report_id = REPORT_ID_HIDPP_LONG; | ||
| 221 | message->fap.feature_index = feat_index; | ||
| 222 | message->fap.funcindex_clientid = funcindex_clientid; | ||
| 223 | memcpy(&message->fap.params, params, param_count); | ||
| 224 | |||
| 225 | ret = hidpp_send_message_sync(hidpp, message, response); | ||
| 226 | kfree(message); | ||
| 227 | return ret; | ||
| 228 | } | ||
| 229 | |||
| 230 | static int hidpp_send_rap_command_sync(struct hidpp_device *hidpp_dev, | ||
| 231 | u8 report_id, u8 sub_id, u8 reg_address, u8 *params, int param_count, | ||
| 232 | struct hidpp_report *response) | ||
| 233 | { | ||
| 234 | struct hidpp_report *message; | ||
| 235 | int ret; | ||
| 236 | |||
| 237 | if ((report_id != REPORT_ID_HIDPP_SHORT) && | ||
| 238 | (report_id != REPORT_ID_HIDPP_LONG)) | ||
| 239 | return -EINVAL; | ||
| 240 | |||
| 241 | if (param_count > sizeof(message->rap.params)) | ||
| 242 | return -EINVAL; | ||
| 243 | |||
| 244 | message = kzalloc(sizeof(struct hidpp_report), GFP_KERNEL); | ||
| 245 | if (!message) | ||
| 246 | return -ENOMEM; | ||
| 247 | message->report_id = report_id; | ||
| 248 | message->rap.sub_id = sub_id; | ||
| 249 | message->rap.reg_address = reg_address; | ||
| 250 | memcpy(&message->rap.params, params, param_count); | ||
| 251 | |||
| 252 | ret = hidpp_send_message_sync(hidpp_dev, message, response); | ||
| 253 | kfree(message); | ||
| 254 | return ret; | ||
| 255 | } | ||
| 256 | |||
| 257 | static void delayed_work_cb(struct work_struct *work) | ||
| 258 | { | ||
| 259 | struct hidpp_device *hidpp = container_of(work, struct hidpp_device, | ||
| 260 | work); | ||
| 261 | hidpp_connect_event(hidpp); | ||
| 262 | } | ||
| 263 | |||
| 264 | static inline bool hidpp_match_answer(struct hidpp_report *question, | ||
| 265 | struct hidpp_report *answer) | ||
| 266 | { | ||
| 267 | return (answer->fap.feature_index == question->fap.feature_index) && | ||
| 268 | (answer->fap.funcindex_clientid == question->fap.funcindex_clientid); | ||
| 269 | } | ||
| 270 | |||
| 271 | static inline bool hidpp_match_error(struct hidpp_report *question, | ||
| 272 | struct hidpp_report *answer) | ||
| 273 | { | ||
| 274 | return (answer->fap.feature_index == HIDPP_ERROR) && | ||
| 275 | (answer->fap.funcindex_clientid == question->fap.feature_index) && | ||
| 276 | (answer->fap.params[0] == question->fap.funcindex_clientid); | ||
| 277 | } | ||
| 278 | |||
| 279 | static inline bool hidpp_report_is_connect_event(struct hidpp_report *report) | ||
| 280 | { | ||
| 281 | return (report->report_id == REPORT_ID_HIDPP_SHORT) && | ||
| 282 | (report->rap.sub_id == 0x41); | ||
| 283 | } | ||
| 284 | |||
| 285 | /* -------------------------------------------------------------------------- */ | ||
| 286 | /* HIDP++ 1.0 commands */ | ||
| 287 | /* -------------------------------------------------------------------------- */ | ||
| 288 | |||
| 289 | #define HIDPP_SET_REGISTER 0x80 | ||
| 290 | #define HIDPP_GET_REGISTER 0x81 | ||
| 291 | #define HIDPP_SET_LONG_REGISTER 0x82 | ||
| 292 | #define HIDPP_GET_LONG_REGISTER 0x83 | ||
| 293 | |||
| 294 | #define HIDPP_REG_PAIRING_INFORMATION 0xB5 | ||
| 295 | #define DEVICE_NAME 0x40 | ||
| 296 | |||
| 297 | static char *hidpp_get_unifying_name(struct hidpp_device *hidpp_dev) | ||
| 298 | { | ||
| 299 | struct hidpp_report response; | ||
| 300 | int ret; | ||
| 301 | /* hid-logitech-dj is in charge of setting the right device index */ | ||
| 302 | u8 params[1] = { DEVICE_NAME }; | ||
| 303 | char *name; | ||
| 304 | int len; | ||
| 305 | |||
| 306 | ret = hidpp_send_rap_command_sync(hidpp_dev, | ||
| 307 | REPORT_ID_HIDPP_SHORT, | ||
| 308 | HIDPP_GET_LONG_REGISTER, | ||
| 309 | HIDPP_REG_PAIRING_INFORMATION, | ||
| 310 | params, 1, &response); | ||
| 311 | if (ret) | ||
| 312 | return NULL; | ||
| 313 | |||
| 314 | len = response.rap.params[1]; | ||
| 315 | |||
| 316 | if (2 + len > sizeof(response.rap.params)) | ||
| 317 | return NULL; | ||
| 318 | |||
| 319 | name = kzalloc(len + 1, GFP_KERNEL); | ||
| 320 | if (!name) | ||
| 321 | return NULL; | ||
| 322 | |||
| 323 | memcpy(name, &response.rap.params[2], len); | ||
| 324 | return name; | ||
| 325 | } | ||
| 326 | |||
| 327 | /* -------------------------------------------------------------------------- */ | ||
| 328 | /* 0x0000: Root */ | ||
| 329 | /* -------------------------------------------------------------------------- */ | ||
| 330 | |||
| 331 | #define HIDPP_PAGE_ROOT 0x0000 | ||
| 332 | #define HIDPP_PAGE_ROOT_IDX 0x00 | ||
| 333 | |||
| 334 | #define CMD_ROOT_GET_FEATURE 0x01 | ||
| 335 | #define CMD_ROOT_GET_PROTOCOL_VERSION 0x11 | ||
| 336 | |||
| 337 | static int hidpp_root_get_feature(struct hidpp_device *hidpp, u16 feature, | ||
| 338 | u8 *feature_index, u8 *feature_type) | ||
| 339 | { | ||
| 340 | struct hidpp_report response; | ||
| 341 | int ret; | ||
| 342 | u8 params[2] = { feature >> 8, feature & 0x00FF }; | ||
| 343 | |||
| 344 | ret = hidpp_send_fap_command_sync(hidpp, | ||
| 345 | HIDPP_PAGE_ROOT_IDX, | ||
| 346 | CMD_ROOT_GET_FEATURE, | ||
| 347 | params, 2, &response); | ||
| 348 | if (ret) | ||
| 349 | return ret; | ||
| 350 | |||
| 351 | *feature_index = response.fap.params[0]; | ||
| 352 | *feature_type = response.fap.params[1]; | ||
| 353 | |||
| 354 | return ret; | ||
| 355 | } | ||
| 356 | |||
| 357 | static int hidpp_root_get_protocol_version(struct hidpp_device *hidpp) | ||
| 358 | { | ||
| 359 | struct hidpp_report response; | ||
| 360 | int ret; | ||
| 361 | |||
| 362 | ret = hidpp_send_fap_command_sync(hidpp, | ||
| 363 | HIDPP_PAGE_ROOT_IDX, | ||
| 364 | CMD_ROOT_GET_PROTOCOL_VERSION, | ||
| 365 | NULL, 0, &response); | ||
| 366 | |||
| 367 | if (ret == HIDPP_ERROR_INVALID_SUBID) { | ||
| 368 | hidpp->protocol_major = 1; | ||
| 369 | hidpp->protocol_minor = 0; | ||
| 370 | return 0; | ||
| 371 | } | ||
| 372 | |||
| 373 | /* the device might not be connected */ | ||
| 374 | if (ret == HIDPP_ERROR_RESOURCE_ERROR) | ||
| 375 | return -EIO; | ||
| 376 | |||
| 377 | if (ret > 0) { | ||
| 378 | hid_err(hidpp->hid_dev, "%s: received protocol error 0x%02x\n", | ||
| 379 | __func__, ret); | ||
| 380 | return -EPROTO; | ||
| 381 | } | ||
| 382 | if (ret) | ||
| 383 | return ret; | ||
| 384 | |||
| 385 | hidpp->protocol_major = response.fap.params[0]; | ||
| 386 | hidpp->protocol_minor = response.fap.params[1]; | ||
| 387 | |||
| 388 | return ret; | ||
| 389 | } | ||
| 390 | |||
| 391 | static bool hidpp_is_connected(struct hidpp_device *hidpp) | ||
| 392 | { | ||
| 393 | int ret; | ||
| 394 | |||
| 395 | ret = hidpp_root_get_protocol_version(hidpp); | ||
| 396 | if (!ret) | ||
| 397 | hid_dbg(hidpp->hid_dev, "HID++ %u.%u device connected.\n", | ||
| 398 | hidpp->protocol_major, hidpp->protocol_minor); | ||
| 399 | return ret == 0; | ||
| 400 | } | ||
| 401 | |||
| 402 | /* -------------------------------------------------------------------------- */ | ||
| 403 | /* 0x0005: GetDeviceNameType */ | ||
| 404 | /* -------------------------------------------------------------------------- */ | ||
| 405 | |||
| 406 | #define HIDPP_PAGE_GET_DEVICE_NAME_TYPE 0x0005 | ||
| 407 | |||
| 408 | #define CMD_GET_DEVICE_NAME_TYPE_GET_COUNT 0x01 | ||
| 409 | #define CMD_GET_DEVICE_NAME_TYPE_GET_DEVICE_NAME 0x11 | ||
| 410 | #define CMD_GET_DEVICE_NAME_TYPE_GET_TYPE 0x21 | ||
| 411 | |||
| 412 | static int hidpp_devicenametype_get_count(struct hidpp_device *hidpp, | ||
| 413 | u8 feature_index, u8 *nameLength) | ||
| 414 | { | ||
| 415 | struct hidpp_report response; | ||
| 416 | int ret; | ||
| 417 | |||
| 418 | ret = hidpp_send_fap_command_sync(hidpp, feature_index, | ||
| 419 | CMD_GET_DEVICE_NAME_TYPE_GET_COUNT, NULL, 0, &response); | ||
| 420 | |||
| 421 | if (ret > 0) { | ||
| 422 | hid_err(hidpp->hid_dev, "%s: received protocol error 0x%02x\n", | ||
| 423 | __func__, ret); | ||
| 424 | return -EPROTO; | ||
| 425 | } | ||
| 426 | if (ret) | ||
| 427 | return ret; | ||
| 428 | |||
| 429 | *nameLength = response.fap.params[0]; | ||
| 430 | |||
| 431 | return ret; | ||
| 432 | } | ||
| 433 | |||
| 434 | static int hidpp_devicenametype_get_device_name(struct hidpp_device *hidpp, | ||
| 435 | u8 feature_index, u8 char_index, char *device_name, int len_buf) | ||
| 436 | { | ||
| 437 | struct hidpp_report response; | ||
| 438 | int ret, i; | ||
| 439 | int count; | ||
| 440 | |||
| 441 | ret = hidpp_send_fap_command_sync(hidpp, feature_index, | ||
| 442 | CMD_GET_DEVICE_NAME_TYPE_GET_DEVICE_NAME, &char_index, 1, | ||
| 443 | &response); | ||
| 444 | |||
| 445 | if (ret > 0) { | ||
| 446 | hid_err(hidpp->hid_dev, "%s: received protocol error 0x%02x\n", | ||
| 447 | __func__, ret); | ||
| 448 | return -EPROTO; | ||
| 449 | } | ||
| 450 | if (ret) | ||
| 451 | return ret; | ||
| 452 | |||
| 453 | if (response.report_id == REPORT_ID_HIDPP_LONG) | ||
| 454 | count = HIDPP_REPORT_LONG_LENGTH - 4; | ||
| 455 | else | ||
| 456 | count = HIDPP_REPORT_SHORT_LENGTH - 4; | ||
| 457 | |||
| 458 | if (len_buf < count) | ||
| 459 | count = len_buf; | ||
| 460 | |||
| 461 | for (i = 0; i < count; i++) | ||
| 462 | device_name[i] = response.fap.params[i]; | ||
| 463 | |||
| 464 | return count; | ||
| 465 | } | ||
| 466 | |||
| 467 | static char *hidpp_get_device_name(struct hidpp_device *hidpp) | ||
| 468 | { | ||
| 469 | u8 feature_type; | ||
| 470 | u8 feature_index; | ||
| 471 | u8 __name_length; | ||
| 472 | char *name; | ||
| 473 | unsigned index = 0; | ||
| 474 | int ret; | ||
| 475 | |||
| 476 | ret = hidpp_root_get_feature(hidpp, HIDPP_PAGE_GET_DEVICE_NAME_TYPE, | ||
| 477 | &feature_index, &feature_type); | ||
| 478 | if (ret) | ||
| 479 | return NULL; | ||
| 480 | |||
| 481 | ret = hidpp_devicenametype_get_count(hidpp, feature_index, | ||
| 482 | &__name_length); | ||
| 483 | if (ret) | ||
| 484 | return NULL; | ||
| 485 | |||
| 486 | name = kzalloc(__name_length + 1, GFP_KERNEL); | ||
| 487 | if (!name) | ||
| 488 | return NULL; | ||
| 489 | |||
| 490 | while (index < __name_length) { | ||
| 491 | ret = hidpp_devicenametype_get_device_name(hidpp, | ||
| 492 | feature_index, index, name + index, | ||
| 493 | __name_length - index); | ||
| 494 | if (ret <= 0) { | ||
| 495 | kfree(name); | ||
| 496 | return NULL; | ||
| 497 | } | ||
| 498 | index += ret; | ||
| 499 | } | ||
| 500 | |||
| 501 | return name; | ||
| 502 | } | ||
| 503 | |||
| 504 | /* -------------------------------------------------------------------------- */ | ||
| 505 | /* 0x6100: TouchPadRawXY */ | ||
| 506 | /* -------------------------------------------------------------------------- */ | ||
| 507 | |||
| 508 | #define HIDPP_PAGE_TOUCHPAD_RAW_XY 0x6100 | ||
| 509 | |||
| 510 | #define CMD_TOUCHPAD_GET_RAW_INFO 0x01 | ||
| 511 | #define CMD_TOUCHPAD_SET_RAW_REPORT_STATE 0x21 | ||
| 512 | |||
| 513 | #define EVENT_TOUCHPAD_RAW_XY 0x00 | ||
| 514 | |||
| 515 | #define TOUCHPAD_RAW_XY_ORIGIN_LOWER_LEFT 0x01 | ||
| 516 | #define TOUCHPAD_RAW_XY_ORIGIN_UPPER_LEFT 0x03 | ||
| 517 | |||
| 518 | struct hidpp_touchpad_raw_info { | ||
| 519 | u16 x_size; | ||
| 520 | u16 y_size; | ||
| 521 | u8 z_range; | ||
| 522 | u8 area_range; | ||
| 523 | u8 timestamp_unit; | ||
| 524 | u8 maxcontacts; | ||
| 525 | u8 origin; | ||
| 526 | u16 res; | ||
| 527 | }; | ||
| 528 | |||
| 529 | struct hidpp_touchpad_raw_xy_finger { | ||
| 530 | u8 contact_type; | ||
| 531 | u8 contact_status; | ||
| 532 | u16 x; | ||
| 533 | u16 y; | ||
| 534 | u8 z; | ||
| 535 | u8 area; | ||
| 536 | u8 finger_id; | ||
| 537 | }; | ||
| 538 | |||
| 539 | struct hidpp_touchpad_raw_xy { | ||
| 540 | u16 timestamp; | ||
| 541 | struct hidpp_touchpad_raw_xy_finger fingers[2]; | ||
| 542 | u8 spurious_flag; | ||
| 543 | u8 end_of_frame; | ||
| 544 | u8 finger_count; | ||
| 545 | u8 button; | ||
| 546 | }; | ||
| 547 | |||
| 548 | static int hidpp_touchpad_get_raw_info(struct hidpp_device *hidpp, | ||
| 549 | u8 feature_index, struct hidpp_touchpad_raw_info *raw_info) | ||
| 550 | { | ||
| 551 | struct hidpp_report response; | ||
| 552 | int ret; | ||
| 553 | u8 *params = (u8 *)response.fap.params; | ||
| 554 | |||
| 555 | ret = hidpp_send_fap_command_sync(hidpp, feature_index, | ||
| 556 | CMD_TOUCHPAD_GET_RAW_INFO, NULL, 0, &response); | ||
| 557 | |||
| 558 | if (ret > 0) { | ||
| 559 | hid_err(hidpp->hid_dev, "%s: received protocol error 0x%02x\n", | ||
| 560 | __func__, ret); | ||
| 561 | return -EPROTO; | ||
| 562 | } | ||
| 563 | if (ret) | ||
| 564 | return ret; | ||
| 565 | |||
| 566 | raw_info->x_size = get_unaligned_be16(¶ms[0]); | ||
| 567 | raw_info->y_size = get_unaligned_be16(¶ms[2]); | ||
| 568 | raw_info->z_range = params[4]; | ||
| 569 | raw_info->area_range = params[5]; | ||
| 570 | raw_info->maxcontacts = params[7]; | ||
| 571 | raw_info->origin = params[8]; | ||
| 572 | /* res is given in unit per inch */ | ||
| 573 | raw_info->res = get_unaligned_be16(¶ms[13]) * 2 / 51; | ||
| 574 | |||
| 575 | return ret; | ||
| 576 | } | ||
| 577 | |||
| 578 | static int hidpp_touchpad_set_raw_report_state(struct hidpp_device *hidpp_dev, | ||
| 579 | u8 feature_index, bool send_raw_reports, | ||
| 580 | bool sensor_enhanced_settings) | ||
| 581 | { | ||
| 582 | struct hidpp_report response; | ||
| 583 | |||
| 584 | /* | ||
| 585 | * Params: | ||
| 586 | * bit 0 - enable raw | ||
| 587 | * bit 1 - 16bit Z, no area | ||
| 588 | * bit 2 - enhanced sensitivity | ||
| 589 | * bit 3 - width, height (4 bits each) instead of area | ||
| 590 | * bit 4 - send raw + gestures (degrades smoothness) | ||
| 591 | * remaining bits - reserved | ||
| 592 | */ | ||
| 593 | u8 params = send_raw_reports | (sensor_enhanced_settings << 2); | ||
| 594 | |||
| 595 | return hidpp_send_fap_command_sync(hidpp_dev, feature_index, | ||
| 596 | CMD_TOUCHPAD_SET_RAW_REPORT_STATE, ¶ms, 1, &response); | ||
| 597 | } | ||
| 598 | |||
| 599 | static void hidpp_touchpad_touch_event(u8 *data, | ||
| 600 | struct hidpp_touchpad_raw_xy_finger *finger) | ||
| 601 | { | ||
| 602 | u8 x_m = data[0] << 2; | ||
| 603 | u8 y_m = data[2] << 2; | ||
| 604 | |||
| 605 | finger->x = x_m << 6 | data[1]; | ||
| 606 | finger->y = y_m << 6 | data[3]; | ||
| 607 | |||
| 608 | finger->contact_type = data[0] >> 6; | ||
| 609 | finger->contact_status = data[2] >> 6; | ||
| 610 | |||
| 611 | finger->z = data[4]; | ||
| 612 | finger->area = data[5]; | ||
| 613 | finger->finger_id = data[6] >> 4; | ||
| 614 | } | ||
| 615 | |||
| 616 | static void hidpp_touchpad_raw_xy_event(struct hidpp_device *hidpp_dev, | ||
| 617 | u8 *data, struct hidpp_touchpad_raw_xy *raw_xy) | ||
| 618 | { | ||
| 619 | memset(raw_xy, 0, sizeof(struct hidpp_touchpad_raw_xy)); | ||
| 620 | raw_xy->end_of_frame = data[8] & 0x01; | ||
| 621 | raw_xy->spurious_flag = (data[8] >> 1) & 0x01; | ||
| 622 | raw_xy->finger_count = data[15] & 0x0f; | ||
| 623 | raw_xy->button = (data[8] >> 2) & 0x01; | ||
| 624 | |||
| 625 | if (raw_xy->finger_count) { | ||
| 626 | hidpp_touchpad_touch_event(&data[2], &raw_xy->fingers[0]); | ||
| 627 | hidpp_touchpad_touch_event(&data[9], &raw_xy->fingers[1]); | ||
| 628 | } | ||
| 629 | } | ||
| 630 | |||
| 631 | /* ************************************************************************** */ | ||
| 632 | /* */ | ||
| 633 | /* Device Support */ | ||
| 634 | /* */ | ||
| 635 | /* ************************************************************************** */ | ||
| 636 | |||
| 637 | /* -------------------------------------------------------------------------- */ | ||
| 638 | /* Touchpad HID++ devices */ | ||
| 639 | /* -------------------------------------------------------------------------- */ | ||
| 640 | |||
| 641 | #define WTP_MANUAL_RESOLUTION 39 | ||
| 642 | |||
| 643 | struct wtp_data { | ||
| 644 | struct input_dev *input; | ||
| 645 | u16 x_size, y_size; | ||
| 646 | u8 finger_count; | ||
| 647 | u8 mt_feature_index; | ||
| 648 | u8 button_feature_index; | ||
| 649 | u8 maxcontacts; | ||
| 650 | bool flip_y; | ||
| 651 | unsigned int resolution; | ||
| 652 | }; | ||
| 653 | |||
| 654 | static int wtp_input_mapping(struct hid_device *hdev, struct hid_input *hi, | ||
| 655 | struct hid_field *field, struct hid_usage *usage, | ||
| 656 | unsigned long **bit, int *max) | ||
| 657 | { | ||
| 658 | struct hidpp_device *hidpp = hid_get_drvdata(hdev); | ||
| 659 | |||
| 660 | if ((hidpp->quirks & HIDPP_QUIRK_MULTI_INPUT) && | ||
| 661 | (field->application == HID_GD_KEYBOARD)) | ||
| 662 | return 0; | ||
| 663 | |||
| 664 | return -1; | ||
| 665 | } | ||
| 666 | |||
| 667 | static void wtp_populate_input(struct hidpp_device *hidpp, | ||
| 668 | struct input_dev *input_dev, bool origin_is_hid_core) | ||
| 669 | { | ||
| 670 | struct wtp_data *wd = hidpp->private_data; | ||
| 671 | |||
| 672 | if ((hidpp->quirks & HIDPP_QUIRK_MULTI_INPUT) && origin_is_hid_core) | ||
| 673 | /* this is the generic hid-input call */ | ||
| 674 | return; | ||
| 675 | |||
| 676 | __set_bit(EV_ABS, input_dev->evbit); | ||
| 677 | __set_bit(EV_KEY, input_dev->evbit); | ||
| 678 | __clear_bit(EV_REL, input_dev->evbit); | ||
| 679 | __clear_bit(EV_LED, input_dev->evbit); | ||
| 680 | |||
| 681 | input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, wd->x_size, 0, 0); | ||
| 682 | input_abs_set_res(input_dev, ABS_MT_POSITION_X, wd->resolution); | ||
| 683 | input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, wd->y_size, 0, 0); | ||
| 684 | input_abs_set_res(input_dev, ABS_MT_POSITION_Y, wd->resolution); | ||
| 685 | |||
| 686 | /* Max pressure is not given by the devices, pick one */ | ||
| 687 | input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, 50, 0, 0); | ||
| 688 | |||
| 689 | input_set_capability(input_dev, EV_KEY, BTN_LEFT); | ||
| 690 | |||
| 691 | if (hidpp->quirks & HIDPP_QUIRK_WTP_PHYSICAL_BUTTONS) | ||
| 692 | input_set_capability(input_dev, EV_KEY, BTN_RIGHT); | ||
| 693 | else | ||
| 694 | __set_bit(INPUT_PROP_BUTTONPAD, input_dev->propbit); | ||
| 695 | |||
| 696 | input_mt_init_slots(input_dev, wd->maxcontacts, INPUT_MT_POINTER | | ||
| 697 | INPUT_MT_DROP_UNUSED); | ||
| 698 | |||
| 699 | wd->input = input_dev; | ||
| 700 | } | ||
| 701 | |||
| 702 | static void wtp_touch_event(struct wtp_data *wd, | ||
| 703 | struct hidpp_touchpad_raw_xy_finger *touch_report) | ||
| 704 | { | ||
| 705 | int slot; | ||
| 706 | |||
| 707 | if (!touch_report->finger_id || touch_report->contact_type) | ||
| 708 | /* no actual data */ | ||
| 709 | return; | ||
| 710 | |||
| 711 | slot = input_mt_get_slot_by_key(wd->input, touch_report->finger_id); | ||
| 712 | |||
| 713 | input_mt_slot(wd->input, slot); | ||
| 714 | input_mt_report_slot_state(wd->input, MT_TOOL_FINGER, | ||
| 715 | touch_report->contact_status); | ||
| 716 | if (touch_report->contact_status) { | ||
| 717 | input_event(wd->input, EV_ABS, ABS_MT_POSITION_X, | ||
| 718 | touch_report->x); | ||
| 719 | input_event(wd->input, EV_ABS, ABS_MT_POSITION_Y, | ||
| 720 | wd->flip_y ? wd->y_size - touch_report->y : | ||
| 721 | touch_report->y); | ||
| 722 | input_event(wd->input, EV_ABS, ABS_MT_PRESSURE, | ||
| 723 | touch_report->area); | ||
| 724 | } | ||
| 725 | } | ||
| 726 | |||
| 727 | static void wtp_send_raw_xy_event(struct hidpp_device *hidpp, | ||
| 728 | struct hidpp_touchpad_raw_xy *raw) | ||
| 729 | { | ||
| 730 | struct wtp_data *wd = hidpp->private_data; | ||
| 731 | int i; | ||
| 732 | |||
| 733 | for (i = 0; i < 2; i++) | ||
| 734 | wtp_touch_event(wd, &(raw->fingers[i])); | ||
| 735 | |||
| 736 | if (raw->end_of_frame && | ||
| 737 | !(hidpp->quirks & HIDPP_QUIRK_WTP_PHYSICAL_BUTTONS)) | ||
| 738 | input_event(wd->input, EV_KEY, BTN_LEFT, raw->button); | ||
| 739 | |||
| 740 | if (raw->end_of_frame || raw->finger_count <= 2) { | ||
| 741 | input_mt_sync_frame(wd->input); | ||
| 742 | input_sync(wd->input); | ||
| 743 | } | ||
| 744 | } | ||
| 745 | |||
| 746 | static int wtp_mouse_raw_xy_event(struct hidpp_device *hidpp, u8 *data) | ||
| 747 | { | ||
| 748 | struct wtp_data *wd = hidpp->private_data; | ||
| 749 | u8 c1_area = ((data[7] & 0xf) * (data[7] & 0xf) + | ||
| 750 | (data[7] >> 4) * (data[7] >> 4)) / 2; | ||
| 751 | u8 c2_area = ((data[13] & 0xf) * (data[13] & 0xf) + | ||
| 752 | (data[13] >> 4) * (data[13] >> 4)) / 2; | ||
| 753 | struct hidpp_touchpad_raw_xy raw = { | ||
| 754 | .timestamp = data[1], | ||
| 755 | .fingers = { | ||
| 756 | { | ||
| 757 | .contact_type = 0, | ||
| 758 | .contact_status = !!data[7], | ||
| 759 | .x = get_unaligned_le16(&data[3]), | ||
| 760 | .y = get_unaligned_le16(&data[5]), | ||
| 761 | .z = c1_area, | ||
| 762 | .area = c1_area, | ||
| 763 | .finger_id = data[2], | ||
| 764 | }, { | ||
| 765 | .contact_type = 0, | ||
| 766 | .contact_status = !!data[13], | ||
| 767 | .x = get_unaligned_le16(&data[9]), | ||
| 768 | .y = get_unaligned_le16(&data[11]), | ||
| 769 | .z = c2_area, | ||
| 770 | .area = c2_area, | ||
| 771 | .finger_id = data[8], | ||
| 772 | } | ||
| 773 | }, | ||
| 774 | .finger_count = wd->maxcontacts, | ||
| 775 | .spurious_flag = 0, | ||
| 776 | .end_of_frame = (data[0] >> 7) == 0, | ||
| 777 | .button = data[0] & 0x01, | ||
| 778 | }; | ||
| 779 | |||
| 780 | wtp_send_raw_xy_event(hidpp, &raw); | ||
| 781 | |||
| 782 | return 1; | ||
| 783 | } | ||
| 784 | |||
| 785 | static int wtp_raw_event(struct hid_device *hdev, u8 *data, int size) | ||
| 786 | { | ||
| 787 | struct hidpp_device *hidpp = hid_get_drvdata(hdev); | ||
| 788 | struct wtp_data *wd = hidpp->private_data; | ||
| 789 | struct hidpp_report *report = (struct hidpp_report *)data; | ||
| 790 | struct hidpp_touchpad_raw_xy raw; | ||
| 791 | |||
| 792 | if (!wd || !wd->input) | ||
| 793 | return 1; | ||
| 794 | |||
| 795 | switch (data[0]) { | ||
| 796 | case 0x02: | ||
| 797 | if (hidpp->quirks & HIDPP_QUIRK_WTP_PHYSICAL_BUTTONS) { | ||
| 798 | input_event(wd->input, EV_KEY, BTN_LEFT, | ||
| 799 | !!(data[1] & 0x01)); | ||
| 800 | input_event(wd->input, EV_KEY, BTN_RIGHT, | ||
| 801 | !!(data[1] & 0x02)); | ||
| 802 | input_sync(wd->input); | ||
| 803 | } else { | ||
| 804 | if (size < 21) | ||
| 805 | return 1; | ||
| 806 | return wtp_mouse_raw_xy_event(hidpp, &data[7]); | ||
| 807 | } | ||
| 808 | case REPORT_ID_HIDPP_LONG: | ||
| 809 | if ((report->fap.feature_index != wd->mt_feature_index) || | ||
| 810 | (report->fap.funcindex_clientid != EVENT_TOUCHPAD_RAW_XY)) | ||
| 811 | return 1; | ||
| 812 | hidpp_touchpad_raw_xy_event(hidpp, data + 4, &raw); | ||
| 813 | |||
| 814 | wtp_send_raw_xy_event(hidpp, &raw); | ||
| 815 | return 0; | ||
| 816 | } | ||
| 817 | |||
| 818 | return 0; | ||
| 819 | } | ||
| 820 | |||
| 821 | static int wtp_get_config(struct hidpp_device *hidpp) | ||
| 822 | { | ||
| 823 | struct wtp_data *wd = hidpp->private_data; | ||
| 824 | struct hidpp_touchpad_raw_info raw_info = {0}; | ||
| 825 | u8 feature_type; | ||
| 826 | int ret; | ||
| 827 | |||
| 828 | ret = hidpp_root_get_feature(hidpp, HIDPP_PAGE_TOUCHPAD_RAW_XY, | ||
| 829 | &wd->mt_feature_index, &feature_type); | ||
| 830 | if (ret) | ||
| 831 | /* means that the device is not powered up */ | ||
| 832 | return ret; | ||
| 833 | |||
| 834 | ret = hidpp_touchpad_get_raw_info(hidpp, wd->mt_feature_index, | ||
| 835 | &raw_info); | ||
| 836 | if (ret) | ||
| 837 | return ret; | ||
| 838 | |||
| 839 | wd->x_size = raw_info.x_size; | ||
| 840 | wd->y_size = raw_info.y_size; | ||
| 841 | wd->maxcontacts = raw_info.maxcontacts; | ||
| 842 | wd->flip_y = raw_info.origin == TOUCHPAD_RAW_XY_ORIGIN_LOWER_LEFT; | ||
| 843 | wd->resolution = raw_info.res; | ||
| 844 | if (!wd->resolution) | ||
| 845 | wd->resolution = WTP_MANUAL_RESOLUTION; | ||
| 846 | |||
| 847 | return 0; | ||
| 848 | } | ||
| 849 | |||
| 850 | static int wtp_allocate(struct hid_device *hdev, const struct hid_device_id *id) | ||
| 851 | { | ||
| 852 | struct hidpp_device *hidpp = hid_get_drvdata(hdev); | ||
| 853 | struct wtp_data *wd; | ||
| 854 | |||
| 855 | wd = devm_kzalloc(&hdev->dev, sizeof(struct wtp_data), | ||
| 856 | GFP_KERNEL); | ||
| 857 | if (!wd) | ||
| 858 | return -ENOMEM; | ||
| 859 | |||
| 860 | hidpp->private_data = wd; | ||
| 861 | |||
| 862 | return 0; | ||
| 863 | }; | ||
| 864 | |||
| 865 | static void wtp_connect(struct hid_device *hdev, bool connected) | ||
| 866 | { | ||
| 867 | struct hidpp_device *hidpp = hid_get_drvdata(hdev); | ||
| 868 | struct wtp_data *wd = hidpp->private_data; | ||
| 869 | int ret; | ||
| 870 | |||
| 871 | if (!connected) | ||
| 872 | return; | ||
| 873 | |||
| 874 | if (!wd->x_size) { | ||
| 875 | ret = wtp_get_config(hidpp); | ||
| 876 | if (ret) { | ||
| 877 | hid_err(hdev, "Can not get wtp config: %d\n", ret); | ||
| 878 | return; | ||
| 879 | } | ||
| 880 | } | ||
| 881 | |||
| 882 | hidpp_touchpad_set_raw_report_state(hidpp, wd->mt_feature_index, | ||
| 883 | true, true); | ||
| 884 | } | ||
| 885 | |||
| 886 | /* -------------------------------------------------------------------------- */ | ||
| 887 | /* Generic HID++ devices */ | ||
| 888 | /* -------------------------------------------------------------------------- */ | ||
| 889 | |||
| 890 | static int hidpp_input_mapping(struct hid_device *hdev, struct hid_input *hi, | ||
| 891 | struct hid_field *field, struct hid_usage *usage, | ||
| 892 | unsigned long **bit, int *max) | ||
| 893 | { | ||
| 894 | struct hidpp_device *hidpp = hid_get_drvdata(hdev); | ||
| 895 | |||
| 896 | if (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP) | ||
| 897 | return wtp_input_mapping(hdev, hi, field, usage, bit, max); | ||
| 898 | |||
| 899 | return 0; | ||
| 900 | } | ||
| 901 | |||
| 902 | static void hidpp_populate_input(struct hidpp_device *hidpp, | ||
| 903 | struct input_dev *input, bool origin_is_hid_core) | ||
| 904 | { | ||
| 905 | if (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP) | ||
| 906 | wtp_populate_input(hidpp, input, origin_is_hid_core); | ||
| 907 | } | ||
| 908 | |||
| 909 | static void hidpp_input_configured(struct hid_device *hdev, | ||
| 910 | struct hid_input *hidinput) | ||
| 911 | { | ||
| 912 | struct hidpp_device *hidpp = hid_get_drvdata(hdev); | ||
| 913 | struct input_dev *input = hidinput->input; | ||
| 914 | |||
| 915 | hidpp_populate_input(hidpp, input, true); | ||
| 916 | } | ||
| 917 | |||
| 918 | static int hidpp_raw_hidpp_event(struct hidpp_device *hidpp, u8 *data, | ||
| 919 | int size) | ||
| 920 | { | ||
| 921 | struct hidpp_report *question = hidpp->send_receive_buf; | ||
| 922 | struct hidpp_report *answer = hidpp->send_receive_buf; | ||
| 923 | struct hidpp_report *report = (struct hidpp_report *)data; | ||
| 924 | |||
| 925 | /* | ||
| 926 | * If the mutex is locked then we have a pending answer from a | ||
| 927 | * previoulsly sent command | ||
| 928 | */ | ||
| 929 | if (unlikely(mutex_is_locked(&hidpp->send_mutex))) { | ||
| 930 | /* | ||
| 931 | * Check for a correct hidpp20 answer or the corresponding | ||
| 932 | * error | ||
| 933 | */ | ||
| 934 | if (hidpp_match_answer(question, report) || | ||
| 935 | hidpp_match_error(question, report)) { | ||
| 936 | *answer = *report; | ||
| 937 | hidpp->answer_available = true; | ||
| 938 | wake_up(&hidpp->wait); | ||
| 939 | /* | ||
| 940 | * This was an answer to a command that this driver sent | ||
| 941 | * We return 1 to hid-core to avoid forwarding the | ||
| 942 | * command upstream as it has been treated by the driver | ||
| 943 | */ | ||
| 944 | |||
| 945 | return 1; | ||
| 946 | } | ||
| 947 | } | ||
| 948 | |||
| 949 | if (unlikely(hidpp_report_is_connect_event(report))) { | ||
| 950 | atomic_set(&hidpp->connected, | ||
| 951 | !(report->rap.params[0] & (1 << 6))); | ||
| 952 | if ((hidpp->quirks & HIDPP_QUIRK_DELAYED_INIT) && | ||
| 953 | (schedule_work(&hidpp->work) == 0)) | ||
| 954 | dbg_hid("%s: connect event already queued\n", __func__); | ||
| 955 | return 1; | ||
| 956 | } | ||
| 957 | |||
| 958 | if (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP) | ||
| 959 | return wtp_raw_event(hidpp->hid_dev, data, size); | ||
| 960 | |||
| 961 | return 0; | ||
| 962 | } | ||
| 963 | |||
| 964 | static int hidpp_raw_event(struct hid_device *hdev, struct hid_report *report, | ||
| 965 | u8 *data, int size) | ||
| 966 | { | ||
| 967 | struct hidpp_device *hidpp = hid_get_drvdata(hdev); | ||
| 968 | |||
| 969 | switch (data[0]) { | ||
| 970 | case REPORT_ID_HIDPP_LONG: | ||
| 971 | if (size != HIDPP_REPORT_LONG_LENGTH) { | ||
| 972 | hid_err(hdev, "received hid++ report of bad size (%d)", | ||
| 973 | size); | ||
| 974 | return 1; | ||
| 975 | } | ||
| 976 | return hidpp_raw_hidpp_event(hidpp, data, size); | ||
| 977 | case REPORT_ID_HIDPP_SHORT: | ||
| 978 | if (size != HIDPP_REPORT_SHORT_LENGTH) { | ||
| 979 | hid_err(hdev, "received hid++ report of bad size (%d)", | ||
| 980 | size); | ||
| 981 | return 1; | ||
| 982 | } | ||
| 983 | return hidpp_raw_hidpp_event(hidpp, data, size); | ||
| 984 | } | ||
| 985 | |||
| 986 | if (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP) | ||
| 987 | return wtp_raw_event(hdev, data, size); | ||
| 988 | |||
| 989 | return 0; | ||
| 990 | } | ||
| 991 | |||
| 992 | static void hidpp_overwrite_name(struct hid_device *hdev, bool use_unifying) | ||
| 993 | { | ||
| 994 | struct hidpp_device *hidpp = hid_get_drvdata(hdev); | ||
| 995 | char *name; | ||
| 996 | |||
| 997 | if (use_unifying) | ||
| 998 | /* | ||
| 999 | * the device is connected through an Unifying receiver, and | ||
| 1000 | * might not be already connected. | ||
| 1001 | * Ask the receiver for its name. | ||
| 1002 | */ | ||
| 1003 | name = hidpp_get_unifying_name(hidpp); | ||
| 1004 | else | ||
| 1005 | name = hidpp_get_device_name(hidpp); | ||
| 1006 | |||
| 1007 | if (!name) | ||
| 1008 | hid_err(hdev, "unable to retrieve the name of the device"); | ||
| 1009 | else | ||
| 1010 | snprintf(hdev->name, sizeof(hdev->name), "%s", name); | ||
| 1011 | |||
| 1012 | kfree(name); | ||
| 1013 | } | ||
| 1014 | |||
| 1015 | static int hidpp_input_open(struct input_dev *dev) | ||
| 1016 | { | ||
| 1017 | struct hid_device *hid = input_get_drvdata(dev); | ||
| 1018 | |||
| 1019 | return hid_hw_open(hid); | ||
| 1020 | } | ||
| 1021 | |||
| 1022 | static void hidpp_input_close(struct input_dev *dev) | ||
| 1023 | { | ||
| 1024 | struct hid_device *hid = input_get_drvdata(dev); | ||
| 1025 | |||
| 1026 | hid_hw_close(hid); | ||
| 1027 | } | ||
| 1028 | |||
| 1029 | static struct input_dev *hidpp_allocate_input(struct hid_device *hdev) | ||
| 1030 | { | ||
| 1031 | struct input_dev *input_dev = devm_input_allocate_device(&hdev->dev); | ||
| 1032 | |||
| 1033 | if (!input_dev) | ||
| 1034 | return NULL; | ||
| 1035 | |||
| 1036 | input_set_drvdata(input_dev, hdev); | ||
| 1037 | input_dev->open = hidpp_input_open; | ||
| 1038 | input_dev->close = hidpp_input_close; | ||
| 1039 | |||
| 1040 | input_dev->name = hdev->name; | ||
| 1041 | input_dev->phys = hdev->phys; | ||
| 1042 | input_dev->uniq = hdev->uniq; | ||
| 1043 | input_dev->id.bustype = hdev->bus; | ||
| 1044 | input_dev->id.vendor = hdev->vendor; | ||
| 1045 | input_dev->id.product = hdev->product; | ||
| 1046 | input_dev->id.version = hdev->version; | ||
| 1047 | input_dev->dev.parent = &hdev->dev; | ||
| 1048 | |||
| 1049 | return input_dev; | ||
| 1050 | } | ||
| 1051 | |||
| 1052 | static void hidpp_connect_event(struct hidpp_device *hidpp) | ||
| 1053 | { | ||
| 1054 | struct hid_device *hdev = hidpp->hid_dev; | ||
| 1055 | int ret = 0; | ||
| 1056 | bool connected = atomic_read(&hidpp->connected); | ||
| 1057 | struct input_dev *input; | ||
| 1058 | char *name, *devm_name; | ||
| 1059 | |||
| 1060 | if (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP) | ||
| 1061 | wtp_connect(hdev, connected); | ||
| 1062 | |||
| 1063 | if (!connected || hidpp->delayed_input) | ||
| 1064 | return; | ||
| 1065 | |||
| 1066 | if (!hidpp->protocol_major) { | ||
| 1067 | ret = !hidpp_is_connected(hidpp); | ||
| 1068 | if (ret) { | ||
| 1069 | hid_err(hdev, "Can not get the protocol version.\n"); | ||
| 1070 | return; | ||
| 1071 | } | ||
| 1072 | } | ||
| 1073 | |||
| 1074 | /* the device is already connected, we can ask for its name and | ||
| 1075 | * protocol */ | ||
| 1076 | hid_info(hdev, "HID++ %u.%u device connected.\n", | ||
| 1077 | hidpp->protocol_major, hidpp->protocol_minor); | ||
| 1078 | |||
| 1079 | input = hidpp_allocate_input(hdev); | ||
| 1080 | if (!input) { | ||
| 1081 | hid_err(hdev, "cannot allocate new input device: %d\n", ret); | ||
| 1082 | return; | ||
| 1083 | } | ||
| 1084 | |||
| 1085 | name = hidpp_get_device_name(hidpp); | ||
| 1086 | if (!name) { | ||
| 1087 | hid_err(hdev, "unable to retrieve the name of the device"); | ||
| 1088 | } else { | ||
| 1089 | devm_name = devm_kasprintf(&hdev->dev, GFP_KERNEL, "%s", name); | ||
| 1090 | if (devm_name) | ||
| 1091 | input->name = devm_name; | ||
| 1092 | kfree(name); | ||
| 1093 | } | ||
| 1094 | |||
| 1095 | hidpp_populate_input(hidpp, input, false); | ||
| 1096 | |||
| 1097 | ret = input_register_device(input); | ||
| 1098 | if (ret) | ||
| 1099 | input_free_device(input); | ||
| 1100 | |||
| 1101 | hidpp->delayed_input = input; | ||
| 1102 | } | ||
| 1103 | |||
| 1104 | static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) | ||
| 1105 | { | ||
| 1106 | struct hidpp_device *hidpp; | ||
| 1107 | int ret; | ||
| 1108 | bool connected; | ||
| 1109 | unsigned int connect_mask = HID_CONNECT_DEFAULT; | ||
| 1110 | |||
| 1111 | hidpp = devm_kzalloc(&hdev->dev, sizeof(struct hidpp_device), | ||
| 1112 | GFP_KERNEL); | ||
| 1113 | if (!hidpp) | ||
| 1114 | return -ENOMEM; | ||
| 1115 | |||
| 1116 | hidpp->hid_dev = hdev; | ||
| 1117 | hid_set_drvdata(hdev, hidpp); | ||
| 1118 | |||
| 1119 | hidpp->quirks = id->driver_data; | ||
| 1120 | |||
| 1121 | if (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP) { | ||
| 1122 | ret = wtp_allocate(hdev, id); | ||
| 1123 | if (ret) | ||
| 1124 | goto wtp_allocate_fail; | ||
| 1125 | } | ||
| 1126 | |||
| 1127 | INIT_WORK(&hidpp->work, delayed_work_cb); | ||
| 1128 | mutex_init(&hidpp->send_mutex); | ||
| 1129 | init_waitqueue_head(&hidpp->wait); | ||
| 1130 | |||
| 1131 | ret = hid_parse(hdev); | ||
| 1132 | if (ret) { | ||
| 1133 | hid_err(hdev, "%s:parse failed\n", __func__); | ||
| 1134 | goto hid_parse_fail; | ||
| 1135 | } | ||
| 1136 | |||
| 1137 | /* Allow incoming packets */ | ||
| 1138 | hid_device_io_start(hdev); | ||
| 1139 | |||
| 1140 | connected = hidpp_is_connected(hidpp); | ||
| 1141 | if (id->group != HID_GROUP_LOGITECH_DJ_DEVICE) { | ||
| 1142 | if (!connected) { | ||
| 1143 | hid_err(hdev, "Device not connected"); | ||
| 1144 | hid_device_io_stop(hdev); | ||
| 1145 | goto hid_parse_fail; | ||
| 1146 | } | ||
| 1147 | |||
| 1148 | hid_info(hdev, "HID++ %u.%u device connected.\n", | ||
| 1149 | hidpp->protocol_major, hidpp->protocol_minor); | ||
| 1150 | } | ||
| 1151 | |||
| 1152 | hidpp_overwrite_name(hdev, id->group == HID_GROUP_LOGITECH_DJ_DEVICE); | ||
| 1153 | atomic_set(&hidpp->connected, connected); | ||
| 1154 | |||
| 1155 | if (connected && (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP)) { | ||
| 1156 | ret = wtp_get_config(hidpp); | ||
| 1157 | if (ret) | ||
| 1158 | goto hid_parse_fail; | ||
| 1159 | } | ||
| 1160 | |||
| 1161 | /* Block incoming packets */ | ||
| 1162 | hid_device_io_stop(hdev); | ||
| 1163 | |||
| 1164 | if (hidpp->quirks & HIDPP_QUIRK_DELAYED_INIT) | ||
| 1165 | connect_mask &= ~HID_CONNECT_HIDINPUT; | ||
| 1166 | |||
| 1167 | /* Re-enable hidinput for multi-input devices */ | ||
| 1168 | if (hidpp->quirks & HIDPP_QUIRK_MULTI_INPUT) | ||
| 1169 | connect_mask |= HID_CONNECT_HIDINPUT; | ||
| 1170 | |||
| 1171 | ret = hid_hw_start(hdev, connect_mask); | ||
| 1172 | if (ret) { | ||
| 1173 | hid_err(hdev, "%s:hid_hw_start returned error\n", __func__); | ||
| 1174 | goto hid_hw_start_fail; | ||
| 1175 | } | ||
| 1176 | |||
| 1177 | if (hidpp->quirks & HIDPP_QUIRK_DELAYED_INIT) { | ||
| 1178 | /* Allow incoming packets */ | ||
| 1179 | hid_device_io_start(hdev); | ||
| 1180 | |||
| 1181 | hidpp_connect_event(hidpp); | ||
| 1182 | } | ||
| 1183 | |||
| 1184 | return ret; | ||
| 1185 | |||
| 1186 | hid_hw_start_fail: | ||
| 1187 | hid_parse_fail: | ||
| 1188 | cancel_work_sync(&hidpp->work); | ||
| 1189 | mutex_destroy(&hidpp->send_mutex); | ||
| 1190 | wtp_allocate_fail: | ||
| 1191 | hid_set_drvdata(hdev, NULL); | ||
| 1192 | return ret; | ||
| 1193 | } | ||
| 1194 | |||
| 1195 | static void hidpp_remove(struct hid_device *hdev) | ||
| 1196 | { | ||
| 1197 | struct hidpp_device *hidpp = hid_get_drvdata(hdev); | ||
| 1198 | |||
| 1199 | cancel_work_sync(&hidpp->work); | ||
| 1200 | mutex_destroy(&hidpp->send_mutex); | ||
| 1201 | hid_hw_stop(hdev); | ||
| 1202 | } | ||
| 1203 | |||
| 1204 | static const struct hid_device_id hidpp_devices[] = { | ||
| 1205 | { /* wireless touchpad */ | ||
| 1206 | HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE, | ||
| 1207 | USB_VENDOR_ID_LOGITECH, 0x4011), | ||
| 1208 | .driver_data = HIDPP_QUIRK_CLASS_WTP | HIDPP_QUIRK_DELAYED_INIT | | ||
| 1209 | HIDPP_QUIRK_WTP_PHYSICAL_BUTTONS }, | ||
| 1210 | { /* wireless touchpad T650 */ | ||
| 1211 | HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE, | ||
| 1212 | USB_VENDOR_ID_LOGITECH, 0x4101), | ||
| 1213 | .driver_data = HIDPP_QUIRK_CLASS_WTP | HIDPP_QUIRK_DELAYED_INIT }, | ||
| 1214 | { /* wireless touchpad T651 */ | ||
| 1215 | HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, | ||
| 1216 | USB_DEVICE_ID_LOGITECH_T651), | ||
| 1217 | .driver_data = HIDPP_QUIRK_CLASS_WTP }, | ||
| 1218 | { /* Keyboard TK820 */ | ||
| 1219 | HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE, | ||
| 1220 | USB_VENDOR_ID_LOGITECH, 0x4102), | ||
| 1221 | .driver_data = HIDPP_QUIRK_DELAYED_INIT | HIDPP_QUIRK_MULTI_INPUT | | ||
| 1222 | HIDPP_QUIRK_CLASS_WTP }, | ||
| 1223 | |||
| 1224 | { HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE, | ||
| 1225 | USB_VENDOR_ID_LOGITECH, HID_ANY_ID)}, | ||
| 1226 | {} | ||
| 1227 | }; | ||
| 1228 | |||
| 1229 | MODULE_DEVICE_TABLE(hid, hidpp_devices); | ||
| 1230 | |||
| 1231 | static struct hid_driver hidpp_driver = { | ||
| 1232 | .name = "logitech-hidpp-device", | ||
| 1233 | .id_table = hidpp_devices, | ||
| 1234 | .probe = hidpp_probe, | ||
| 1235 | .remove = hidpp_remove, | ||
| 1236 | .raw_event = hidpp_raw_event, | ||
| 1237 | .input_configured = hidpp_input_configured, | ||
| 1238 | .input_mapping = hidpp_input_mapping, | ||
| 1239 | }; | ||
| 1240 | |||
| 1241 | module_hid_driver(hidpp_driver); | ||
diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c index 8ba17a946f2a..cacda43f6a6f 100644 --- a/drivers/hid/hid-microsoft.c +++ b/drivers/hid/hid-microsoft.c | |||
| @@ -274,6 +274,8 @@ static const struct hid_device_id ms_devices[] = { | |||
| 274 | .driver_data = MS_NOGET }, | 274 | .driver_data = MS_NOGET }, |
| 275 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500), | 275 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500), |
| 276 | .driver_data = MS_DUPLICATE_USAGES }, | 276 | .driver_data = MS_DUPLICATE_USAGES }, |
| 277 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3), | ||
| 278 | .driver_data = MS_HIDINPUT }, | ||
| 277 | 279 | ||
| 278 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT), | 280 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT), |
| 279 | .driver_data = MS_PRESENTER }, | 281 | .driver_data = MS_PRESENTER }, |
diff --git a/drivers/hid/hid-plantronics.c b/drivers/hid/hid-plantronics.c new file mode 100644 index 000000000000..2180e0789b76 --- /dev/null +++ b/drivers/hid/hid-plantronics.c | |||
| @@ -0,0 +1,55 @@ | |||
| 1 | /* | ||
| 2 | * Plantronics USB HID Driver | ||
| 3 | * | ||
| 4 | * Copyright (c) 2014 JD Cole <jd.cole@plantronics.com> | ||
| 5 | * Copyright (c) 2014 Terry Junge <terry.junge@plantronics.com> | ||
| 6 | */ | ||
| 7 | |||
| 8 | /* | ||
| 9 | * This program is free software; you can redistribute it and/or modify it | ||
| 10 | * under the terms of the GNU General Public License as published by the Free | ||
| 11 | * Software Foundation; either version 2 of the License, or (at your option) | ||
| 12 | * any later version. | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include "hid-ids.h" | ||
| 16 | |||
| 17 | #include <linux/hid.h> | ||
| 18 | #include <linux/module.h> | ||
| 19 | |||
| 20 | static int plantronics_input_mapping(struct hid_device *hdev, | ||
| 21 | struct hid_input *hi, | ||
| 22 | struct hid_field *field, | ||
| 23 | struct hid_usage *usage, | ||
| 24 | unsigned long **bit, int *max) | ||
| 25 | { | ||
| 26 | if (field->application == HID_CP_CONSUMERCONTROL | ||
| 27 | && (usage->hid & HID_USAGE_PAGE) == HID_UP_CONSUMER) { | ||
| 28 | hid_dbg(hdev, "usage: %08x (appl: %08x) - defaulted\n", | ||
| 29 | usage->hid, field->application); | ||
| 30 | return 0; | ||
| 31 | } | ||
| 32 | |||
| 33 | hid_dbg(hdev, "usage: %08x (appl: %08x) - ignored\n", | ||
| 34 | usage->hid, field->application); | ||
| 35 | |||
| 36 | return -1; | ||
| 37 | } | ||
| 38 | |||
| 39 | static const struct hid_device_id plantronics_devices[] = { | ||
| 40 | { HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS, HID_ANY_ID) }, | ||
| 41 | { } | ||
| 42 | }; | ||
| 43 | MODULE_DEVICE_TABLE(hid, plantronics_devices); | ||
| 44 | |||
| 45 | static struct hid_driver plantronics_driver = { | ||
| 46 | .name = "plantronics", | ||
| 47 | .id_table = plantronics_devices, | ||
| 48 | .input_mapping = plantronics_input_mapping, | ||
| 49 | }; | ||
| 50 | module_hid_driver(plantronics_driver); | ||
| 51 | |||
| 52 | MODULE_AUTHOR("JD Cole <jd.cole@plantronics.com>"); | ||
| 53 | MODULE_AUTHOR("Terry Junge <terry.junge@plantronics.com>"); | ||
| 54 | MODULE_DESCRIPTION("Plantronics USB HID Driver"); | ||
| 55 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/hid/hid-rmi.c b/drivers/hid/hid-rmi.c index 3cccff73b9b9..b51200fe2f33 100644 --- a/drivers/hid/hid-rmi.c +++ b/drivers/hid/hid-rmi.c | |||
| @@ -584,11 +584,15 @@ static int rmi_populate_f11(struct hid_device *hdev) | |||
| 584 | bool has_query10 = false; | 584 | bool has_query10 = false; |
| 585 | bool has_query11; | 585 | bool has_query11; |
| 586 | bool has_query12; | 586 | bool has_query12; |
| 587 | bool has_query27; | ||
| 588 | bool has_query28; | ||
| 589 | bool has_query36 = false; | ||
| 587 | bool has_physical_props; | 590 | bool has_physical_props; |
| 588 | bool has_gestures; | 591 | bool has_gestures; |
| 589 | bool has_rel; | 592 | bool has_rel; |
| 593 | bool has_data40 = false; | ||
| 590 | unsigned x_size, y_size; | 594 | unsigned x_size, y_size; |
| 591 | u16 query12_offset; | 595 | u16 query_offset; |
| 592 | 596 | ||
| 593 | if (!data->f11.query_base_addr) { | 597 | if (!data->f11.query_base_addr) { |
| 594 | hid_err(hdev, "No 2D sensor found, giving up.\n"); | 598 | hid_err(hdev, "No 2D sensor found, giving up.\n"); |
| @@ -604,6 +608,8 @@ static int rmi_populate_f11(struct hid_device *hdev) | |||
| 604 | has_query9 = !!(buf[0] & BIT(3)); | 608 | has_query9 = !!(buf[0] & BIT(3)); |
| 605 | has_query11 = !!(buf[0] & BIT(4)); | 609 | has_query11 = !!(buf[0] & BIT(4)); |
| 606 | has_query12 = !!(buf[0] & BIT(5)); | 610 | has_query12 = !!(buf[0] & BIT(5)); |
| 611 | has_query27 = !!(buf[0] & BIT(6)); | ||
| 612 | has_query28 = !!(buf[0] & BIT(7)); | ||
| 607 | 613 | ||
| 608 | /* query 1 to get the max number of fingers */ | 614 | /* query 1 to get the max number of fingers */ |
| 609 | ret = rmi_read(hdev, data->f11.query_base_addr + 1, buf); | 615 | ret = rmi_read(hdev, data->f11.query_base_addr + 1, buf); |
| @@ -626,43 +632,43 @@ static int rmi_populate_f11(struct hid_device *hdev) | |||
| 626 | has_rel = !!(buf[0] & BIT(3)); | 632 | has_rel = !!(buf[0] & BIT(3)); |
| 627 | has_gestures = !!(buf[0] & BIT(5)); | 633 | has_gestures = !!(buf[0] & BIT(5)); |
| 628 | 634 | ||
| 635 | /* | ||
| 636 | * At least 4 queries are guaranteed to be present in F11 | ||
| 637 | * +1 for query 5 which is present since absolute events are | ||
| 638 | * reported and +1 for query 12. | ||
| 639 | */ | ||
| 640 | query_offset = 6; | ||
| 641 | |||
| 642 | if (has_rel) | ||
| 643 | ++query_offset; /* query 6 is present */ | ||
| 644 | |||
| 629 | if (has_gestures) { | 645 | if (has_gestures) { |
| 630 | /* query 8 to find out if query 10 exists */ | 646 | /* query 8 to find out if query 10 exists */ |
| 631 | ret = rmi_read(hdev, data->f11.query_base_addr + 8, buf); | 647 | ret = rmi_read(hdev, |
| 648 | data->f11.query_base_addr + query_offset + 1, buf); | ||
| 632 | if (ret) { | 649 | if (ret) { |
| 633 | hid_err(hdev, "can not read gesture information: %d.\n", | 650 | hid_err(hdev, "can not read gesture information: %d.\n", |
| 634 | ret); | 651 | ret); |
| 635 | return ret; | 652 | return ret; |
| 636 | } | 653 | } |
| 637 | has_query10 = !!(buf[0] & BIT(2)); | 654 | has_query10 = !!(buf[0] & BIT(2)); |
| 638 | } | ||
| 639 | 655 | ||
| 640 | /* | 656 | query_offset += 2; /* query 7 and 8 are present */ |
| 641 | * At least 4 queries are guaranteed to be present in F11 | 657 | } |
| 642 | * +1 for query 5 which is present since absolute events are | ||
| 643 | * reported and +1 for query 12. | ||
| 644 | */ | ||
| 645 | query12_offset = 6; | ||
| 646 | |||
| 647 | if (has_rel) | ||
| 648 | ++query12_offset; /* query 6 is present */ | ||
| 649 | |||
| 650 | if (has_gestures) | ||
| 651 | query12_offset += 2; /* query 7 and 8 are present */ | ||
| 652 | 658 | ||
| 653 | if (has_query9) | 659 | if (has_query9) |
| 654 | ++query12_offset; | 660 | ++query_offset; |
| 655 | 661 | ||
| 656 | if (has_query10) | 662 | if (has_query10) |
| 657 | ++query12_offset; | 663 | ++query_offset; |
| 658 | 664 | ||
| 659 | if (has_query11) | 665 | if (has_query11) |
| 660 | ++query12_offset; | 666 | ++query_offset; |
| 661 | 667 | ||
| 662 | /* query 12 to know if the physical properties are reported */ | 668 | /* query 12 to know if the physical properties are reported */ |
| 663 | if (has_query12) { | 669 | if (has_query12) { |
| 664 | ret = rmi_read(hdev, data->f11.query_base_addr | 670 | ret = rmi_read(hdev, data->f11.query_base_addr |
| 665 | + query12_offset, buf); | 671 | + query_offset, buf); |
| 666 | if (ret) { | 672 | if (ret) { |
| 667 | hid_err(hdev, "can not get query 12: %d.\n", ret); | 673 | hid_err(hdev, "can not get query 12: %d.\n", ret); |
| 668 | return ret; | 674 | return ret; |
| @@ -670,9 +676,10 @@ static int rmi_populate_f11(struct hid_device *hdev) | |||
| 670 | has_physical_props = !!(buf[0] & BIT(5)); | 676 | has_physical_props = !!(buf[0] & BIT(5)); |
| 671 | 677 | ||
| 672 | if (has_physical_props) { | 678 | if (has_physical_props) { |
| 679 | query_offset += 1; | ||
| 673 | ret = rmi_read_block(hdev, | 680 | ret = rmi_read_block(hdev, |
| 674 | data->f11.query_base_addr | 681 | data->f11.query_base_addr |
| 675 | + query12_offset + 1, buf, 4); | 682 | + query_offset, buf, 4); |
| 676 | if (ret) { | 683 | if (ret) { |
| 677 | hid_err(hdev, "can not read query 15-18: %d.\n", | 684 | hid_err(hdev, "can not read query 15-18: %d.\n", |
| 678 | ret); | 685 | ret); |
| @@ -687,9 +694,45 @@ static int rmi_populate_f11(struct hid_device *hdev) | |||
| 687 | 694 | ||
| 688 | hid_info(hdev, "%s: size in mm: %d x %d\n", | 695 | hid_info(hdev, "%s: size in mm: %d x %d\n", |
| 689 | __func__, data->x_size_mm, data->y_size_mm); | 696 | __func__, data->x_size_mm, data->y_size_mm); |
| 697 | |||
| 698 | /* | ||
| 699 | * query 15 - 18 contain the size of the sensor | ||
| 700 | * and query 19 - 26 contain bezel dimensions | ||
| 701 | */ | ||
| 702 | query_offset += 12; | ||
| 703 | } | ||
| 704 | } | ||
| 705 | |||
| 706 | if (has_query27) | ||
| 707 | ++query_offset; | ||
| 708 | |||
| 709 | if (has_query28) { | ||
| 710 | ret = rmi_read(hdev, data->f11.query_base_addr | ||
| 711 | + query_offset, buf); | ||
| 712 | if (ret) { | ||
| 713 | hid_err(hdev, "can not get query 28: %d.\n", ret); | ||
| 714 | return ret; | ||
| 715 | } | ||
| 716 | |||
| 717 | has_query36 = !!(buf[0] & BIT(6)); | ||
| 718 | } | ||
| 719 | |||
| 720 | if (has_query36) { | ||
| 721 | query_offset += 2; | ||
| 722 | ret = rmi_read(hdev, data->f11.query_base_addr | ||
| 723 | + query_offset, buf); | ||
| 724 | if (ret) { | ||
| 725 | hid_err(hdev, "can not get query 36: %d.\n", ret); | ||
| 726 | return ret; | ||
| 690 | } | 727 | } |
| 728 | |||
| 729 | has_data40 = !!(buf[0] & BIT(5)); | ||
| 691 | } | 730 | } |
| 692 | 731 | ||
| 732 | |||
| 733 | if (has_data40) | ||
| 734 | data->f11.report_size += data->max_fingers * 2; | ||
| 735 | |||
| 693 | /* | 736 | /* |
| 694 | * retrieve the ctrl registers | 737 | * retrieve the ctrl registers |
| 695 | * the ctrl register has a size of 20 but a fw bug split it into 16 + 4, | 738 | * the ctrl register has a size of 20 but a fw bug split it into 16 + 4, |
diff --git a/drivers/hid/hid-roccat-kone.c b/drivers/hid/hid-roccat-kone.c index 6101816a7ddd..c29265055ac1 100644 --- a/drivers/hid/hid-roccat-kone.c +++ b/drivers/hid/hid-roccat-kone.c | |||
| @@ -46,6 +46,7 @@ static void kone_profile_activated(struct kone_device *kone, uint new_profile) | |||
| 46 | static void kone_profile_report(struct kone_device *kone, uint new_profile) | 46 | static void kone_profile_report(struct kone_device *kone, uint new_profile) |
| 47 | { | 47 | { |
| 48 | struct kone_roccat_report roccat_report; | 48 | struct kone_roccat_report roccat_report; |
| 49 | |||
| 49 | roccat_report.event = kone_mouse_event_switch_profile; | 50 | roccat_report.event = kone_mouse_event_switch_profile; |
| 50 | roccat_report.value = new_profile; | 51 | roccat_report.value = new_profile; |
| 51 | roccat_report.key = 0; | 52 | roccat_report.key = 0; |
| @@ -163,6 +164,7 @@ static int kone_set_settings(struct usb_device *usb_dev, | |||
| 163 | struct kone_settings const *settings) | 164 | struct kone_settings const *settings) |
| 164 | { | 165 | { |
| 165 | int retval; | 166 | int retval; |
| 167 | |||
| 166 | retval = kone_send(usb_dev, kone_command_settings, | 168 | retval = kone_send(usb_dev, kone_command_settings, |
| 167 | settings, sizeof(struct kone_settings)); | 169 | settings, sizeof(struct kone_settings)); |
| 168 | if (retval) | 170 | if (retval) |
| @@ -387,7 +389,7 @@ static struct bin_attribute bin_attr_profile##number = { \ | |||
| 387 | .read = kone_sysfs_read_profilex, \ | 389 | .read = kone_sysfs_read_profilex, \ |
| 388 | .write = kone_sysfs_write_profilex, \ | 390 | .write = kone_sysfs_write_profilex, \ |
| 389 | .private = &profile_numbers[number-1], \ | 391 | .private = &profile_numbers[number-1], \ |
| 390 | }; | 392 | } |
| 391 | PROFILE_ATTR(1); | 393 | PROFILE_ATTR(1); |
| 392 | PROFILE_ATTR(2); | 394 | PROFILE_ATTR(2); |
| 393 | PROFILE_ATTR(3); | 395 | PROFILE_ATTR(3); |
| @@ -456,6 +458,7 @@ static ssize_t kone_sysfs_show_tcu(struct device *dev, | |||
| 456 | static int kone_tcu_command(struct usb_device *usb_dev, int number) | 458 | static int kone_tcu_command(struct usb_device *usb_dev, int number) |
| 457 | { | 459 | { |
| 458 | unsigned char value; | 460 | unsigned char value; |
| 461 | |||
| 459 | value = number; | 462 | value = number; |
| 460 | return kone_send(usb_dev, kone_command_calibrate, &value, 1); | 463 | return kone_send(usb_dev, kone_command_calibrate, &value, 1); |
| 461 | } | 464 | } |
| @@ -697,10 +700,8 @@ static int kone_init_specials(struct hid_device *hdev) | |||
| 697 | == USB_INTERFACE_PROTOCOL_MOUSE) { | 700 | == USB_INTERFACE_PROTOCOL_MOUSE) { |
| 698 | 701 | ||
| 699 | kone = kzalloc(sizeof(*kone), GFP_KERNEL); | 702 | kone = kzalloc(sizeof(*kone), GFP_KERNEL); |
| 700 | if (!kone) { | 703 | if (!kone) |
| 701 | hid_err(hdev, "can't alloc device descriptor\n"); | ||
| 702 | return -ENOMEM; | 704 | return -ENOMEM; |
| 703 | } | ||
| 704 | hid_set_drvdata(hdev, kone); | 705 | hid_set_drvdata(hdev, kone); |
| 705 | 706 | ||
| 706 | retval = kone_init_kone_device_struct(usb_dev, kone); | 707 | retval = kone_init_kone_device_struct(usb_dev, kone); |
diff --git a/drivers/hid/hid-saitek.c b/drivers/hid/hid-saitek.c index 69cca1476a0c..5632c54eadf0 100644 --- a/drivers/hid/hid-saitek.c +++ b/drivers/hid/hid-saitek.c | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | * (This module is based on "hid-ortek".) | 7 | * (This module is based on "hid-ortek".) |
| 8 | * Copyright (c) 2012 Andreas Hübner | 8 | * Copyright (c) 2012 Andreas Hübner |
| 9 | * | 9 | * |
| 10 | * R.A.T.7, M.M.O.7 (USB gaming mice): | 10 | * R.A.T.7, R.A.T.9, M.M.O.7 (USB gaming mice): |
| 11 | * Fixes the mode button which cycles through three constantly pressed | 11 | * Fixes the mode button which cycles through three constantly pressed |
| 12 | * buttons. All three press events are mapped to one button and the | 12 | * buttons. All three press events are mapped to one button and the |
| 13 | * missing release event is generated immediately. | 13 | * missing release event is generated immediately. |
| @@ -179,6 +179,8 @@ static const struct hid_device_id saitek_devices[] = { | |||
| 179 | .driver_data = SAITEK_FIX_PS1000 }, | 179 | .driver_data = SAITEK_FIX_PS1000 }, |
| 180 | { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT7), | 180 | { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT7), |
| 181 | .driver_data = SAITEK_RELEASE_MODE_RAT7 }, | 181 | .driver_data = SAITEK_RELEASE_MODE_RAT7 }, |
| 182 | { HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_RAT9), | ||
| 183 | .driver_data = SAITEK_RELEASE_MODE_RAT7 }, | ||
| 182 | { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_MMO7), | 184 | { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_MMO7), |
| 183 | .driver_data = SAITEK_RELEASE_MODE_MMO7 }, | 185 | .driver_data = SAITEK_RELEASE_MODE_MMO7 }, |
| 184 | { } | 186 | { } |
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index bc4269e559f1..31e9d2561106 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c | |||
| @@ -798,6 +798,12 @@ union sixaxis_output_report_01 { | |||
| 798 | __u8 buf[36]; | 798 | __u8 buf[36]; |
| 799 | }; | 799 | }; |
| 800 | 800 | ||
| 801 | #define DS4_REPORT_0x02_SIZE 37 | ||
| 802 | #define DS4_REPORT_0x05_SIZE 32 | ||
| 803 | #define DS4_REPORT_0x11_SIZE 78 | ||
| 804 | #define DS4_REPORT_0x81_SIZE 7 | ||
| 805 | #define SIXAXIS_REPORT_0xF2_SIZE 18 | ||
| 806 | |||
| 801 | static spinlock_t sony_dev_list_lock; | 807 | static spinlock_t sony_dev_list_lock; |
| 802 | static LIST_HEAD(sony_device_list); | 808 | static LIST_HEAD(sony_device_list); |
| 803 | static DEFINE_IDA(sony_device_id_allocator); | 809 | static DEFINE_IDA(sony_device_id_allocator); |
| @@ -811,6 +817,7 @@ struct sony_sc { | |||
| 811 | struct work_struct state_worker; | 817 | struct work_struct state_worker; |
| 812 | struct power_supply battery; | 818 | struct power_supply battery; |
| 813 | int device_id; | 819 | int device_id; |
| 820 | __u8 *output_report_dmabuf; | ||
| 814 | 821 | ||
| 815 | #ifdef CONFIG_SONY_FF | 822 | #ifdef CONFIG_SONY_FF |
| 816 | __u8 left; | 823 | __u8 left; |
| @@ -1142,9 +1149,20 @@ static int sixaxis_set_operational_usb(struct hid_device *hdev) | |||
| 1142 | 1149 | ||
| 1143 | static int sixaxis_set_operational_bt(struct hid_device *hdev) | 1150 | static int sixaxis_set_operational_bt(struct hid_device *hdev) |
| 1144 | { | 1151 | { |
| 1145 | unsigned char buf[] = { 0xf4, 0x42, 0x03, 0x00, 0x00 }; | 1152 | static const __u8 report[] = { 0xf4, 0x42, 0x03, 0x00, 0x00 }; |
| 1146 | return hid_hw_raw_request(hdev, buf[0], buf, sizeof(buf), | 1153 | __u8 *buf; |
| 1154 | int ret; | ||
| 1155 | |||
| 1156 | buf = kmemdup(report, sizeof(report), GFP_KERNEL); | ||
| 1157 | if (!buf) | ||
| 1158 | return -ENOMEM; | ||
| 1159 | |||
| 1160 | ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(report), | ||
| 1147 | HID_FEATURE_REPORT, HID_REQ_SET_REPORT); | 1161 | HID_FEATURE_REPORT, HID_REQ_SET_REPORT); |
| 1162 | |||
| 1163 | kfree(buf); | ||
| 1164 | |||
| 1165 | return ret; | ||
| 1148 | } | 1166 | } |
| 1149 | 1167 | ||
| 1150 | /* | 1168 | /* |
| @@ -1153,10 +1171,19 @@ static int sixaxis_set_operational_bt(struct hid_device *hdev) | |||
| 1153 | */ | 1171 | */ |
| 1154 | static int dualshock4_set_operational_bt(struct hid_device *hdev) | 1172 | static int dualshock4_set_operational_bt(struct hid_device *hdev) |
| 1155 | { | 1173 | { |
| 1156 | __u8 buf[37] = { 0 }; | 1174 | __u8 *buf; |
| 1175 | int ret; | ||
| 1176 | |||
| 1177 | buf = kmalloc(DS4_REPORT_0x02_SIZE, GFP_KERNEL); | ||
| 1178 | if (!buf) | ||
| 1179 | return -ENOMEM; | ||
| 1157 | 1180 | ||
| 1158 | return hid_hw_raw_request(hdev, 0x02, buf, sizeof(buf), | 1181 | ret = hid_hw_raw_request(hdev, 0x02, buf, DS4_REPORT_0x02_SIZE, |
| 1159 | HID_FEATURE_REPORT, HID_REQ_GET_REPORT); | 1182 | HID_FEATURE_REPORT, HID_REQ_GET_REPORT); |
| 1183 | |||
| 1184 | kfree(buf); | ||
| 1185 | |||
| 1186 | return ret; | ||
| 1160 | } | 1187 | } |
| 1161 | 1188 | ||
| 1162 | static void sixaxis_set_leds_from_id(int id, __u8 values[MAX_LEDS]) | 1189 | static void sixaxis_set_leds_from_id(int id, __u8 values[MAX_LEDS]) |
| @@ -1471,9 +1498,7 @@ error_leds: | |||
| 1471 | 1498 | ||
| 1472 | static void sixaxis_state_worker(struct work_struct *work) | 1499 | static void sixaxis_state_worker(struct work_struct *work) |
| 1473 | { | 1500 | { |
| 1474 | struct sony_sc *sc = container_of(work, struct sony_sc, state_worker); | 1501 | static const union sixaxis_output_report_01 default_report = { |
| 1475 | int n; | ||
| 1476 | union sixaxis_output_report_01 report = { | ||
| 1477 | .buf = { | 1502 | .buf = { |
| 1478 | 0x01, | 1503 | 0x01, |
| 1479 | 0x00, 0xff, 0x00, 0xff, 0x00, | 1504 | 0x00, 0xff, 0x00, 0xff, 0x00, |
| @@ -1485,20 +1510,27 @@ static void sixaxis_state_worker(struct work_struct *work) | |||
| 1485 | 0x00, 0x00, 0x00, 0x00, 0x00 | 1510 | 0x00, 0x00, 0x00, 0x00, 0x00 |
| 1486 | } | 1511 | } |
| 1487 | }; | 1512 | }; |
| 1513 | struct sony_sc *sc = container_of(work, struct sony_sc, state_worker); | ||
| 1514 | struct sixaxis_output_report *report = | ||
| 1515 | (struct sixaxis_output_report *)sc->output_report_dmabuf; | ||
| 1516 | int n; | ||
| 1517 | |||
| 1518 | /* Initialize the report with default values */ | ||
| 1519 | memcpy(report, &default_report, sizeof(struct sixaxis_output_report)); | ||
| 1488 | 1520 | ||
| 1489 | #ifdef CONFIG_SONY_FF | 1521 | #ifdef CONFIG_SONY_FF |
| 1490 | report.data.rumble.right_motor_on = sc->right ? 1 : 0; | 1522 | report->rumble.right_motor_on = sc->right ? 1 : 0; |
| 1491 | report.data.rumble.left_motor_force = sc->left; | 1523 | report->rumble.left_motor_force = sc->left; |
| 1492 | #endif | 1524 | #endif |
| 1493 | 1525 | ||
| 1494 | report.data.leds_bitmap |= sc->led_state[0] << 1; | 1526 | report->leds_bitmap |= sc->led_state[0] << 1; |
| 1495 | report.data.leds_bitmap |= sc->led_state[1] << 2; | 1527 | report->leds_bitmap |= sc->led_state[1] << 2; |
| 1496 | report.data.leds_bitmap |= sc->led_state[2] << 3; | 1528 | report->leds_bitmap |= sc->led_state[2] << 3; |
| 1497 | report.data.leds_bitmap |= sc->led_state[3] << 4; | 1529 | report->leds_bitmap |= sc->led_state[3] << 4; |
| 1498 | 1530 | ||
| 1499 | /* Set flag for all leds off, required for 3rd party INTEC controller */ | 1531 | /* Set flag for all leds off, required for 3rd party INTEC controller */ |
| 1500 | if ((report.data.leds_bitmap & 0x1E) == 0) | 1532 | if ((report->leds_bitmap & 0x1E) == 0) |
| 1501 | report.data.leds_bitmap |= 0x20; | 1533 | report->leds_bitmap |= 0x20; |
| 1502 | 1534 | ||
| 1503 | /* | 1535 | /* |
| 1504 | * The LEDs in the report are indexed in reverse order to their | 1536 | * The LEDs in the report are indexed in reverse order to their |
| @@ -1511,28 +1543,30 @@ static void sixaxis_state_worker(struct work_struct *work) | |||
| 1511 | */ | 1543 | */ |
| 1512 | for (n = 0; n < 4; n++) { | 1544 | for (n = 0; n < 4; n++) { |
| 1513 | if (sc->led_delay_on[n] || sc->led_delay_off[n]) { | 1545 | if (sc->led_delay_on[n] || sc->led_delay_off[n]) { |
| 1514 | report.data.led[3 - n].duty_off = sc->led_delay_off[n]; | 1546 | report->led[3 - n].duty_off = sc->led_delay_off[n]; |
| 1515 | report.data.led[3 - n].duty_on = sc->led_delay_on[n]; | 1547 | report->led[3 - n].duty_on = sc->led_delay_on[n]; |
| 1516 | } | 1548 | } |
| 1517 | } | 1549 | } |
| 1518 | 1550 | ||
| 1519 | hid_hw_raw_request(sc->hdev, report.data.report_id, report.buf, | 1551 | hid_hw_raw_request(sc->hdev, report->report_id, (__u8 *)report, |
| 1520 | sizeof(report), HID_OUTPUT_REPORT, HID_REQ_SET_REPORT); | 1552 | sizeof(struct sixaxis_output_report), |
| 1553 | HID_OUTPUT_REPORT, HID_REQ_SET_REPORT); | ||
| 1521 | } | 1554 | } |
| 1522 | 1555 | ||
| 1523 | static void dualshock4_state_worker(struct work_struct *work) | 1556 | static void dualshock4_state_worker(struct work_struct *work) |
| 1524 | { | 1557 | { |
| 1525 | struct sony_sc *sc = container_of(work, struct sony_sc, state_worker); | 1558 | struct sony_sc *sc = container_of(work, struct sony_sc, state_worker); |
| 1526 | struct hid_device *hdev = sc->hdev; | 1559 | struct hid_device *hdev = sc->hdev; |
| 1560 | __u8 *buf = sc->output_report_dmabuf; | ||
| 1527 | int offset; | 1561 | int offset; |
| 1528 | 1562 | ||
| 1529 | __u8 buf[78] = { 0 }; | ||
| 1530 | |||
| 1531 | if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) { | 1563 | if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) { |
| 1564 | memset(buf, 0, DS4_REPORT_0x05_SIZE); | ||
| 1532 | buf[0] = 0x05; | 1565 | buf[0] = 0x05; |
| 1533 | buf[1] = 0xFF; | 1566 | buf[1] = 0xFF; |
| 1534 | offset = 4; | 1567 | offset = 4; |
| 1535 | } else { | 1568 | } else { |
| 1569 | memset(buf, 0, DS4_REPORT_0x11_SIZE); | ||
| 1536 | buf[0] = 0x11; | 1570 | buf[0] = 0x11; |
| 1537 | buf[1] = 0xB0; | 1571 | buf[1] = 0xB0; |
| 1538 | buf[3] = 0x0F; | 1572 | buf[3] = 0x0F; |
| @@ -1560,12 +1594,33 @@ static void dualshock4_state_worker(struct work_struct *work) | |||
| 1560 | buf[offset++] = sc->led_delay_off[3]; | 1594 | buf[offset++] = sc->led_delay_off[3]; |
| 1561 | 1595 | ||
| 1562 | if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) | 1596 | if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) |
| 1563 | hid_hw_output_report(hdev, buf, 32); | 1597 | hid_hw_output_report(hdev, buf, DS4_REPORT_0x05_SIZE); |
| 1564 | else | 1598 | else |
| 1565 | hid_hw_raw_request(hdev, 0x11, buf, 78, | 1599 | hid_hw_raw_request(hdev, 0x11, buf, DS4_REPORT_0x11_SIZE, |
| 1566 | HID_OUTPUT_REPORT, HID_REQ_SET_REPORT); | 1600 | HID_OUTPUT_REPORT, HID_REQ_SET_REPORT); |
| 1567 | } | 1601 | } |
| 1568 | 1602 | ||
| 1603 | static int sony_allocate_output_report(struct sony_sc *sc) | ||
| 1604 | { | ||
| 1605 | if (sc->quirks & SIXAXIS_CONTROLLER) | ||
| 1606 | sc->output_report_dmabuf = | ||
| 1607 | kmalloc(sizeof(union sixaxis_output_report_01), | ||
| 1608 | GFP_KERNEL); | ||
| 1609 | else if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) | ||
| 1610 | sc->output_report_dmabuf = kmalloc(DS4_REPORT_0x11_SIZE, | ||
| 1611 | GFP_KERNEL); | ||
| 1612 | else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) | ||
| 1613 | sc->output_report_dmabuf = kmalloc(DS4_REPORT_0x05_SIZE, | ||
| 1614 | GFP_KERNEL); | ||
| 1615 | else | ||
| 1616 | return 0; | ||
| 1617 | |||
| 1618 | if (!sc->output_report_dmabuf) | ||
| 1619 | return -ENOMEM; | ||
| 1620 | |||
| 1621 | return 0; | ||
| 1622 | } | ||
| 1623 | |||
| 1569 | #ifdef CONFIG_SONY_FF | 1624 | #ifdef CONFIG_SONY_FF |
| 1570 | static int sony_play_effect(struct input_dev *dev, void *data, | 1625 | static int sony_play_effect(struct input_dev *dev, void *data, |
| 1571 | struct ff_effect *effect) | 1626 | struct ff_effect *effect) |
| @@ -1754,6 +1809,7 @@ static int sony_get_bt_devaddr(struct sony_sc *sc) | |||
| 1754 | 1809 | ||
| 1755 | static int sony_check_add(struct sony_sc *sc) | 1810 | static int sony_check_add(struct sony_sc *sc) |
| 1756 | { | 1811 | { |
| 1812 | __u8 *buf = NULL; | ||
| 1757 | int n, ret; | 1813 | int n, ret; |
| 1758 | 1814 | ||
| 1759 | if ((sc->quirks & DUALSHOCK4_CONTROLLER_BT) || | 1815 | if ((sc->quirks & DUALSHOCK4_CONTROLLER_BT) || |
| @@ -1769,36 +1825,44 @@ static int sony_check_add(struct sony_sc *sc) | |||
| 1769 | return 0; | 1825 | return 0; |
| 1770 | } | 1826 | } |
| 1771 | } else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) { | 1827 | } else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) { |
| 1772 | __u8 buf[7]; | 1828 | buf = kmalloc(DS4_REPORT_0x81_SIZE, GFP_KERNEL); |
| 1829 | if (!buf) | ||
| 1830 | return -ENOMEM; | ||
| 1773 | 1831 | ||
| 1774 | /* | 1832 | /* |
| 1775 | * The MAC address of a DS4 controller connected via USB can be | 1833 | * The MAC address of a DS4 controller connected via USB can be |
| 1776 | * retrieved with feature report 0x81. The address begins at | 1834 | * retrieved with feature report 0x81. The address begins at |
| 1777 | * offset 1. | 1835 | * offset 1. |
| 1778 | */ | 1836 | */ |
| 1779 | ret = hid_hw_raw_request(sc->hdev, 0x81, buf, sizeof(buf), | 1837 | ret = hid_hw_raw_request(sc->hdev, 0x81, buf, |
| 1780 | HID_FEATURE_REPORT, HID_REQ_GET_REPORT); | 1838 | DS4_REPORT_0x81_SIZE, HID_FEATURE_REPORT, |
| 1839 | HID_REQ_GET_REPORT); | ||
| 1781 | 1840 | ||
| 1782 | if (ret != 7) { | 1841 | if (ret != DS4_REPORT_0x81_SIZE) { |
| 1783 | hid_err(sc->hdev, "failed to retrieve feature report 0x81 with the DualShock 4 MAC address\n"); | 1842 | hid_err(sc->hdev, "failed to retrieve feature report 0x81 with the DualShock 4 MAC address\n"); |
| 1784 | return ret < 0 ? ret : -EINVAL; | 1843 | ret = ret < 0 ? ret : -EINVAL; |
| 1844 | goto out_free; | ||
| 1785 | } | 1845 | } |
| 1786 | 1846 | ||
| 1787 | memcpy(sc->mac_address, &buf[1], sizeof(sc->mac_address)); | 1847 | memcpy(sc->mac_address, &buf[1], sizeof(sc->mac_address)); |
| 1788 | } else if (sc->quirks & SIXAXIS_CONTROLLER_USB) { | 1848 | } else if (sc->quirks & SIXAXIS_CONTROLLER_USB) { |
| 1789 | __u8 buf[18]; | 1849 | buf = kmalloc(SIXAXIS_REPORT_0xF2_SIZE, GFP_KERNEL); |
| 1850 | if (!buf) | ||
| 1851 | return -ENOMEM; | ||
| 1790 | 1852 | ||
| 1791 | /* | 1853 | /* |
| 1792 | * The MAC address of a Sixaxis controller connected via USB can | 1854 | * The MAC address of a Sixaxis controller connected via USB can |
| 1793 | * be retrieved with feature report 0xf2. The address begins at | 1855 | * be retrieved with feature report 0xf2. The address begins at |
| 1794 | * offset 4. | 1856 | * offset 4. |
| 1795 | */ | 1857 | */ |
| 1796 | ret = hid_hw_raw_request(sc->hdev, 0xf2, buf, sizeof(buf), | 1858 | ret = hid_hw_raw_request(sc->hdev, 0xf2, buf, |
| 1797 | HID_FEATURE_REPORT, HID_REQ_GET_REPORT); | 1859 | SIXAXIS_REPORT_0xF2_SIZE, HID_FEATURE_REPORT, |
| 1860 | HID_REQ_GET_REPORT); | ||
| 1798 | 1861 | ||
| 1799 | if (ret != 18) { | 1862 | if (ret != SIXAXIS_REPORT_0xF2_SIZE) { |
| 1800 | hid_err(sc->hdev, "failed to retrieve feature report 0xf2 with the Sixaxis MAC address\n"); | 1863 | hid_err(sc->hdev, "failed to retrieve feature report 0xf2 with the Sixaxis MAC address\n"); |
| 1801 | return ret < 0 ? ret : -EINVAL; | 1864 | ret = ret < 0 ? ret : -EINVAL; |
| 1865 | goto out_free; | ||
| 1802 | } | 1866 | } |
| 1803 | 1867 | ||
| 1804 | /* | 1868 | /* |
| @@ -1811,7 +1875,13 @@ static int sony_check_add(struct sony_sc *sc) | |||
| 1811 | return 0; | 1875 | return 0; |
| 1812 | } | 1876 | } |
| 1813 | 1877 | ||
| 1814 | return sony_check_add_dev_list(sc); | 1878 | ret = sony_check_add_dev_list(sc); |
| 1879 | |||
| 1880 | out_free: | ||
| 1881 | |||
| 1882 | kfree(buf); | ||
| 1883 | |||
| 1884 | return ret; | ||
| 1815 | } | 1885 | } |
| 1816 | 1886 | ||
| 1817 | static int sony_set_device_id(struct sony_sc *sc) | 1887 | static int sony_set_device_id(struct sony_sc *sc) |
| @@ -1895,6 +1965,12 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
| 1895 | return ret; | 1965 | return ret; |
| 1896 | } | 1966 | } |
| 1897 | 1967 | ||
| 1968 | ret = sony_allocate_output_report(sc); | ||
| 1969 | if (ret < 0) { | ||
| 1970 | hid_err(hdev, "failed to allocate the output report buffer\n"); | ||
| 1971 | goto err_stop; | ||
| 1972 | } | ||
| 1973 | |||
| 1898 | ret = sony_set_device_id(sc); | 1974 | ret = sony_set_device_id(sc); |
| 1899 | if (ret < 0) { | 1975 | if (ret < 0) { |
| 1900 | hid_err(hdev, "failed to allocate the device id\n"); | 1976 | hid_err(hdev, "failed to allocate the device id\n"); |
| @@ -1984,6 +2060,7 @@ err_stop: | |||
| 1984 | if (sc->quirks & SONY_BATTERY_SUPPORT) | 2060 | if (sc->quirks & SONY_BATTERY_SUPPORT) |
| 1985 | sony_battery_remove(sc); | 2061 | sony_battery_remove(sc); |
| 1986 | sony_cancel_work_sync(sc); | 2062 | sony_cancel_work_sync(sc); |
| 2063 | kfree(sc->output_report_dmabuf); | ||
| 1987 | sony_remove_dev_list(sc); | 2064 | sony_remove_dev_list(sc); |
| 1988 | sony_release_device_id(sc); | 2065 | sony_release_device_id(sc); |
| 1989 | hid_hw_stop(hdev); | 2066 | hid_hw_stop(hdev); |
| @@ -2004,6 +2081,8 @@ static void sony_remove(struct hid_device *hdev) | |||
| 2004 | 2081 | ||
| 2005 | sony_cancel_work_sync(sc); | 2082 | sony_cancel_work_sync(sc); |
| 2006 | 2083 | ||
| 2084 | kfree(sc->output_report_dmabuf); | ||
| 2085 | |||
| 2007 | sony_remove_dev_list(sc); | 2086 | sony_remove_dev_list(sc); |
| 2008 | 2087 | ||
| 2009 | sony_release_device_id(sc); | 2088 | sony_release_device_id(sc); |
| @@ -2034,6 +2113,9 @@ static const struct hid_device_id sony_devices[] = { | |||
| 2034 | /* Logitech Harmony Adapter for PS3 */ | 2113 | /* Logitech Harmony Adapter for PS3 */ |
| 2035 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3), | 2114 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3), |
| 2036 | .driver_data = PS3REMOTE }, | 2115 | .driver_data = PS3REMOTE }, |
| 2116 | /* SMK-Link PS3 BD Remote Control */ | ||
| 2117 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SMK, USB_DEVICE_ID_SMK_PS3_BDREMOTE), | ||
| 2118 | .driver_data = PS3REMOTE }, | ||
| 2037 | /* Sony Dualshock 4 controllers for PS4 */ | 2119 | /* Sony Dualshock 4 controllers for PS4 */ |
| 2038 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER), | 2120 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER), |
| 2039 | .driver_data = DUALSHOCK4_CONTROLLER_USB }, | 2121 | .driver_data = DUALSHOCK4_CONTROLLER_USB }, |
diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c index 747d54421e73..fbd07812f2d9 100644 --- a/drivers/hid/i2c-hid/i2c-hid.c +++ b/drivers/hid/i2c-hid/i2c-hid.c | |||
| @@ -137,6 +137,7 @@ struct i2c_hid { | |||
| 137 | * descriptor. */ | 137 | * descriptor. */ |
| 138 | unsigned int bufsize; /* i2c buffer size */ | 138 | unsigned int bufsize; /* i2c buffer size */ |
| 139 | char *inbuf; /* Input buffer */ | 139 | char *inbuf; /* Input buffer */ |
| 140 | char *rawbuf; /* Raw Input buffer */ | ||
| 140 | char *cmdbuf; /* Command buffer */ | 141 | char *cmdbuf; /* Command buffer */ |
| 141 | char *argsbuf; /* Command arguments buffer */ | 142 | char *argsbuf; /* Command arguments buffer */ |
| 142 | 143 | ||
| @@ -369,7 +370,7 @@ static int i2c_hid_hwreset(struct i2c_client *client) | |||
| 369 | static void i2c_hid_get_input(struct i2c_hid *ihid) | 370 | static void i2c_hid_get_input(struct i2c_hid *ihid) |
| 370 | { | 371 | { |
| 371 | int ret, ret_size; | 372 | int ret, ret_size; |
| 372 | int size = le16_to_cpu(ihid->hdesc.wMaxInputLength); | 373 | int size = ihid->bufsize; |
| 373 | 374 | ||
| 374 | ret = i2c_master_recv(ihid->client, ihid->inbuf, size); | 375 | ret = i2c_master_recv(ihid->client, ihid->inbuf, size); |
| 375 | if (ret != size) { | 376 | if (ret != size) { |
| @@ -437,7 +438,7 @@ static void i2c_hid_init_report(struct hid_report *report, u8 *buffer, | |||
| 437 | report->id, buffer, size)) | 438 | report->id, buffer, size)) |
| 438 | return; | 439 | return; |
| 439 | 440 | ||
| 440 | i2c_hid_dbg(ihid, "report (len=%d): %*ph\n", size, size, ihid->inbuf); | 441 | i2c_hid_dbg(ihid, "report (len=%d): %*ph\n", size, size, buffer); |
| 441 | 442 | ||
| 442 | ret_size = buffer[0] | (buffer[1] << 8); | 443 | ret_size = buffer[0] | (buffer[1] << 8); |
| 443 | 444 | ||
| @@ -504,9 +505,11 @@ static void i2c_hid_find_max_report(struct hid_device *hid, unsigned int type, | |||
| 504 | static void i2c_hid_free_buffers(struct i2c_hid *ihid) | 505 | static void i2c_hid_free_buffers(struct i2c_hid *ihid) |
| 505 | { | 506 | { |
| 506 | kfree(ihid->inbuf); | 507 | kfree(ihid->inbuf); |
| 508 | kfree(ihid->rawbuf); | ||
| 507 | kfree(ihid->argsbuf); | 509 | kfree(ihid->argsbuf); |
| 508 | kfree(ihid->cmdbuf); | 510 | kfree(ihid->cmdbuf); |
| 509 | ihid->inbuf = NULL; | 511 | ihid->inbuf = NULL; |
| 512 | ihid->rawbuf = NULL; | ||
| 510 | ihid->cmdbuf = NULL; | 513 | ihid->cmdbuf = NULL; |
| 511 | ihid->argsbuf = NULL; | 514 | ihid->argsbuf = NULL; |
| 512 | ihid->bufsize = 0; | 515 | ihid->bufsize = 0; |
| @@ -522,10 +525,11 @@ static int i2c_hid_alloc_buffers(struct i2c_hid *ihid, size_t report_size) | |||
| 522 | report_size; /* report */ | 525 | report_size; /* report */ |
| 523 | 526 | ||
| 524 | ihid->inbuf = kzalloc(report_size, GFP_KERNEL); | 527 | ihid->inbuf = kzalloc(report_size, GFP_KERNEL); |
| 528 | ihid->rawbuf = kzalloc(report_size, GFP_KERNEL); | ||
| 525 | ihid->argsbuf = kzalloc(args_len, GFP_KERNEL); | 529 | ihid->argsbuf = kzalloc(args_len, GFP_KERNEL); |
| 526 | ihid->cmdbuf = kzalloc(sizeof(union command) + args_len, GFP_KERNEL); | 530 | ihid->cmdbuf = kzalloc(sizeof(union command) + args_len, GFP_KERNEL); |
| 527 | 531 | ||
| 528 | if (!ihid->inbuf || !ihid->argsbuf || !ihid->cmdbuf) { | 532 | if (!ihid->inbuf || !ihid->rawbuf || !ihid->argsbuf || !ihid->cmdbuf) { |
| 529 | i2c_hid_free_buffers(ihid); | 533 | i2c_hid_free_buffers(ihid); |
| 530 | return -ENOMEM; | 534 | return -ENOMEM; |
| 531 | } | 535 | } |
| @@ -552,12 +556,12 @@ static int i2c_hid_get_raw_report(struct hid_device *hid, | |||
| 552 | 556 | ||
| 553 | ret = i2c_hid_get_report(client, | 557 | ret = i2c_hid_get_report(client, |
| 554 | report_type == HID_FEATURE_REPORT ? 0x03 : 0x01, | 558 | report_type == HID_FEATURE_REPORT ? 0x03 : 0x01, |
| 555 | report_number, ihid->inbuf, ask_count); | 559 | report_number, ihid->rawbuf, ask_count); |
| 556 | 560 | ||
| 557 | if (ret < 0) | 561 | if (ret < 0) |
| 558 | return ret; | 562 | return ret; |
| 559 | 563 | ||
| 560 | ret_count = ihid->inbuf[0] | (ihid->inbuf[1] << 8); | 564 | ret_count = ihid->rawbuf[0] | (ihid->rawbuf[1] << 8); |
| 561 | 565 | ||
| 562 | if (ret_count <= 2) | 566 | if (ret_count <= 2) |
| 563 | return 0; | 567 | return 0; |
| @@ -566,7 +570,7 @@ static int i2c_hid_get_raw_report(struct hid_device *hid, | |||
| 566 | 570 | ||
| 567 | /* The query buffer contains the size, dropping it in the reply */ | 571 | /* The query buffer contains the size, dropping it in the reply */ |
| 568 | count = min(count, ret_count - 2); | 572 | count = min(count, ret_count - 2); |
| 569 | memcpy(buf, ihid->inbuf + 2, count); | 573 | memcpy(buf, ihid->rawbuf + 2, count); |
| 570 | 574 | ||
| 571 | return count; | 575 | return count; |
| 572 | } | 576 | } |
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index b6cb7a5e4b27..bfbe1bedda7f 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c | |||
| @@ -278,18 +278,20 @@ static void hid_irq_in(struct urb *urb) | |||
| 278 | usbhid->retry_delay = 0; | 278 | usbhid->retry_delay = 0; |
| 279 | if ((hid->quirks & HID_QUIRK_ALWAYS_POLL) && !hid->open) | 279 | if ((hid->quirks & HID_QUIRK_ALWAYS_POLL) && !hid->open) |
| 280 | break; | 280 | break; |
| 281 | hid_input_report(urb->context, HID_INPUT_REPORT, | 281 | if (!test_bit(HID_RESUME_RUNNING, &usbhid->iofl)) { |
| 282 | urb->transfer_buffer, | 282 | hid_input_report(urb->context, HID_INPUT_REPORT, |
| 283 | urb->actual_length, 1); | 283 | urb->transfer_buffer, |
| 284 | /* | 284 | urb->actual_length, 1); |
| 285 | * autosuspend refused while keys are pressed | 285 | /* |
| 286 | * because most keyboards don't wake up when | 286 | * autosuspend refused while keys are pressed |
| 287 | * a key is released | 287 | * because most keyboards don't wake up when |
| 288 | */ | 288 | * a key is released |
| 289 | if (hid_check_keys_pressed(hid)) | 289 | */ |
| 290 | set_bit(HID_KEYS_PRESSED, &usbhid->iofl); | 290 | if (hid_check_keys_pressed(hid)) |
| 291 | else | 291 | set_bit(HID_KEYS_PRESSED, &usbhid->iofl); |
| 292 | clear_bit(HID_KEYS_PRESSED, &usbhid->iofl); | 292 | else |
| 293 | clear_bit(HID_KEYS_PRESSED, &usbhid->iofl); | ||
| 294 | } | ||
| 293 | break; | 295 | break; |
| 294 | case -EPIPE: /* stall */ | 296 | case -EPIPE: /* stall */ |
| 295 | usbhid_mark_busy(usbhid); | 297 | usbhid_mark_busy(usbhid); |
| @@ -687,6 +689,7 @@ int usbhid_open(struct hid_device *hid) | |||
| 687 | goto done; | 689 | goto done; |
| 688 | } | 690 | } |
| 689 | usbhid->intf->needs_remote_wakeup = 1; | 691 | usbhid->intf->needs_remote_wakeup = 1; |
| 692 | set_bit(HID_RESUME_RUNNING, &usbhid->iofl); | ||
| 690 | res = hid_start_in(hid); | 693 | res = hid_start_in(hid); |
| 691 | if (res) { | 694 | if (res) { |
| 692 | if (res != -ENOSPC) { | 695 | if (res != -ENOSPC) { |
| @@ -700,6 +703,15 @@ int usbhid_open(struct hid_device *hid) | |||
| 700 | } | 703 | } |
| 701 | } | 704 | } |
| 702 | usb_autopm_put_interface(usbhid->intf); | 705 | usb_autopm_put_interface(usbhid->intf); |
| 706 | |||
| 707 | /* | ||
| 708 | * In case events are generated while nobody was listening, | ||
| 709 | * some are released when the device is re-opened. | ||
| 710 | * Wait 50 msec for the queue to empty before allowing events | ||
| 711 | * to go through hid. | ||
| 712 | */ | ||
| 713 | msleep(50); | ||
| 714 | clear_bit(HID_RESUME_RUNNING, &usbhid->iofl); | ||
| 703 | } | 715 | } |
| 704 | done: | 716 | done: |
| 705 | mutex_unlock(&hid_open_mut); | 717 | mutex_unlock(&hid_open_mut); |
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 552671ee7c5d..dc89be90b35e 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c | |||
| @@ -73,11 +73,13 @@ static const struct hid_blacklist { | |||
| 73 | { USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN, HID_QUIRK_ALWAYS_POLL }, | 73 | { USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN, HID_QUIRK_ALWAYS_POLL }, |
| 74 | { USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN_009B, HID_QUIRK_ALWAYS_POLL }, | 74 | { USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN_009B, HID_QUIRK_ALWAYS_POLL }, |
| 75 | { USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN_0103, HID_QUIRK_ALWAYS_POLL }, | 75 | { USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN_0103, HID_QUIRK_ALWAYS_POLL }, |
| 76 | { USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN_010c, HID_QUIRK_ALWAYS_POLL }, | ||
| 76 | { USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN_016F, HID_QUIRK_ALWAYS_POLL }, | 77 | { USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN_016F, HID_QUIRK_ALWAYS_POLL }, |
| 77 | { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET }, | 78 | { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET }, |
| 78 | { USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER, HID_QUIRK_NO_INIT_REPORTS }, | 79 | { USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER, HID_QUIRK_NO_INIT_REPORTS }, |
| 79 | { USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET }, | 80 | { USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET }, |
| 80 | { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET }, | 81 | { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET }, |
| 82 | { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3, HID_QUIRK_NO_INIT_REPORTS }, | ||
| 81 | { USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL, HID_QUIRK_NO_INIT_REPORTS }, | 83 | { USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL, HID_QUIRK_NO_INIT_REPORTS }, |
| 82 | { USB_VENDOR_ID_NEXIO, USB_DEVICE_ID_NEXIO_MULTITOUCH_PTI0750, HID_QUIRK_NO_INIT_REPORTS }, | 84 | { USB_VENDOR_ID_NEXIO, USB_DEVICE_ID_NEXIO_MULTITOUCH_PTI0750, HID_QUIRK_NO_INIT_REPORTS }, |
| 83 | { USB_VENDOR_ID_NOVATEK, USB_DEVICE_ID_NOVATEK_MOUSE, HID_QUIRK_NO_INIT_REPORTS }, | 85 | { USB_VENDOR_ID_NOVATEK, USB_DEVICE_ID_NOVATEK_MOUSE, HID_QUIRK_NO_INIT_REPORTS }, |
diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h index f633c24ce28b..807922b49aa4 100644 --- a/drivers/hid/usbhid/usbhid.h +++ b/drivers/hid/usbhid/usbhid.h | |||
| @@ -52,6 +52,7 @@ struct usb_interface *usbhid_find_interface(int minor); | |||
| 52 | #define HID_STARTED 8 | 52 | #define HID_STARTED 8 |
| 53 | #define HID_KEYS_PRESSED 10 | 53 | #define HID_KEYS_PRESSED 10 |
| 54 | #define HID_NO_BANDWIDTH 11 | 54 | #define HID_NO_BANDWIDTH 11 |
| 55 | #define HID_RESUME_RUNNING 12 | ||
| 55 | 56 | ||
| 56 | /* | 57 | /* |
| 57 | * USB-specific HID struct, to be pointed to | 58 | * USB-specific HID struct, to be pointed to |
diff --git a/drivers/hid/wacom.h b/drivers/hid/wacom.h index 0cc53440543a..7db432809e9e 100644 --- a/drivers/hid/wacom.h +++ b/drivers/hid/wacom.h | |||
| @@ -140,7 +140,7 @@ extern const struct hid_device_id wacom_ids[]; | |||
| 140 | 140 | ||
| 141 | void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len); | 141 | void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len); |
| 142 | void wacom_setup_device_quirks(struct wacom_features *features); | 142 | void wacom_setup_device_quirks(struct wacom_features *features); |
| 143 | int wacom_setup_input_capabilities(struct input_dev *input_dev, | 143 | int wacom_setup_pentouch_input_capabilities(struct input_dev *input_dev, |
| 144 | struct wacom_wac *wacom_wac); | 144 | struct wacom_wac *wacom_wac); |
| 145 | int wacom_setup_pad_input_capabilities(struct input_dev *input_dev, | 145 | int wacom_setup_pad_input_capabilities(struct input_dev *input_dev, |
| 146 | struct wacom_wac *wacom_wac); | 146 | struct wacom_wac *wacom_wac); |
diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index 8e02a4a6fde0..654202941d30 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | 13 | ||
| 14 | #include "wacom_wac.h" | 14 | #include "wacom_wac.h" |
| 15 | #include "wacom.h" | 15 | #include "wacom.h" |
| 16 | #include <linux/input/mt.h> | ||
| 16 | 17 | ||
| 17 | #define WAC_MSG_RETRIES 5 | 18 | #define WAC_MSG_RETRIES 5 |
| 18 | 19 | ||
| @@ -70,22 +71,15 @@ static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report, | |||
| 70 | static int wacom_open(struct input_dev *dev) | 71 | static int wacom_open(struct input_dev *dev) |
| 71 | { | 72 | { |
| 72 | struct wacom *wacom = input_get_drvdata(dev); | 73 | struct wacom *wacom = input_get_drvdata(dev); |
| 73 | int retval; | ||
| 74 | |||
| 75 | mutex_lock(&wacom->lock); | ||
| 76 | retval = hid_hw_open(wacom->hdev); | ||
| 77 | mutex_unlock(&wacom->lock); | ||
| 78 | 74 | ||
| 79 | return retval; | 75 | return hid_hw_open(wacom->hdev); |
| 80 | } | 76 | } |
| 81 | 77 | ||
| 82 | static void wacom_close(struct input_dev *dev) | 78 | static void wacom_close(struct input_dev *dev) |
| 83 | { | 79 | { |
| 84 | struct wacom *wacom = input_get_drvdata(dev); | 80 | struct wacom *wacom = input_get_drvdata(dev); |
| 85 | 81 | ||
| 86 | mutex_lock(&wacom->lock); | ||
| 87 | hid_hw_close(wacom->hdev); | 82 | hid_hw_close(wacom->hdev); |
| 88 | mutex_unlock(&wacom->lock); | ||
| 89 | } | 83 | } |
| 90 | 84 | ||
| 91 | /* | 85 | /* |
| @@ -192,9 +186,15 @@ static void wacom_usage_mapping(struct hid_device *hdev, | |||
| 192 | if (!pen && !finger) | 186 | if (!pen && !finger) |
| 193 | return; | 187 | return; |
| 194 | 188 | ||
| 195 | if (finger && !features->touch_max) | 189 | /* |
| 196 | /* touch device at least supports one touch point */ | 190 | * Bamboo models do not support HID_DG_CONTACTMAX. |
| 197 | features->touch_max = 1; | 191 | * And, Bamboo Pen only descriptor contains touch. |
| 192 | */ | ||
| 193 | if (features->type != BAMBOO_PT) { | ||
| 194 | /* ISDv4 touch devices at least supports one touch point */ | ||
| 195 | if (finger && !features->touch_max) | ||
| 196 | features->touch_max = 1; | ||
| 197 | } | ||
| 198 | 198 | ||
| 199 | switch (usage->hid) { | 199 | switch (usage->hid) { |
| 200 | case HID_GD_X: | 200 | case HID_GD_X: |
| @@ -230,6 +230,21 @@ static void wacom_usage_mapping(struct hid_device *hdev, | |||
| 230 | wacom_wac_usage_mapping(hdev, field, usage); | 230 | wacom_wac_usage_mapping(hdev, field, usage); |
| 231 | } | 231 | } |
| 232 | 232 | ||
| 233 | static void wacom_post_parse_hid(struct hid_device *hdev, | ||
| 234 | struct wacom_features *features) | ||
| 235 | { | ||
| 236 | struct wacom *wacom = hid_get_drvdata(hdev); | ||
| 237 | struct wacom_wac *wacom_wac = &wacom->wacom_wac; | ||
| 238 | |||
| 239 | if (features->type == HID_GENERIC) { | ||
| 240 | /* Any last-minute generic device setup */ | ||
| 241 | if (features->touch_max > 1) { | ||
| 242 | input_mt_init_slots(wacom_wac->input, wacom_wac->features.touch_max, | ||
| 243 | INPUT_MT_DIRECT); | ||
| 244 | } | ||
| 245 | } | ||
| 246 | } | ||
| 247 | |||
| 233 | static void wacom_parse_hid(struct hid_device *hdev, | 248 | static void wacom_parse_hid(struct hid_device *hdev, |
| 234 | struct wacom_features *features) | 249 | struct wacom_features *features) |
| 235 | { | 250 | { |
| @@ -264,6 +279,8 @@ static void wacom_parse_hid(struct hid_device *hdev, | |||
| 264 | wacom_usage_mapping(hdev, hreport->field[i], | 279 | wacom_usage_mapping(hdev, hreport->field[i], |
| 265 | hreport->field[i]->usage + j); | 280 | hreport->field[i]->usage + j); |
| 266 | } | 281 | } |
| 282 | |||
| 283 | wacom_post_parse_hid(hdev, features); | ||
| 267 | } | 284 | } |
| 268 | 285 | ||
| 269 | static int wacom_hid_set_device_mode(struct hid_device *hdev) | 286 | static int wacom_hid_set_device_mode(struct hid_device *hdev) |
| @@ -1129,7 +1146,7 @@ static void wacom_clean_inputs(struct wacom *wacom) | |||
| 1129 | input_free_device(wacom->wacom_wac.input); | 1146 | input_free_device(wacom->wacom_wac.input); |
| 1130 | } | 1147 | } |
| 1131 | if (wacom->wacom_wac.pad_input) { | 1148 | if (wacom->wacom_wac.pad_input) { |
| 1132 | if (wacom->wacom_wac.input_registered) | 1149 | if (wacom->wacom_wac.pad_registered) |
| 1133 | input_unregister_device(wacom->wacom_wac.pad_input); | 1150 | input_unregister_device(wacom->wacom_wac.pad_input); |
| 1134 | else | 1151 | else |
| 1135 | input_free_device(wacom->wacom_wac.pad_input); | 1152 | input_free_device(wacom->wacom_wac.pad_input); |
| @@ -1151,13 +1168,13 @@ static int wacom_register_inputs(struct wacom *wacom) | |||
| 1151 | if (!input_dev || !pad_input_dev) | 1168 | if (!input_dev || !pad_input_dev) |
| 1152 | return -EINVAL; | 1169 | return -EINVAL; |
| 1153 | 1170 | ||
| 1154 | error = wacom_setup_input_capabilities(input_dev, wacom_wac); | 1171 | error = wacom_setup_pentouch_input_capabilities(input_dev, wacom_wac); |
| 1155 | if (error) | 1172 | if (!error) { |
| 1156 | return error; | 1173 | error = input_register_device(input_dev); |
| 1157 | 1174 | if (error) | |
| 1158 | error = input_register_device(input_dev); | 1175 | return error; |
| 1159 | if (error) | 1176 | wacom_wac->input_registered = true; |
| 1160 | return error; | 1177 | } |
| 1161 | 1178 | ||
| 1162 | error = wacom_setup_pad_input_capabilities(pad_input_dev, wacom_wac); | 1179 | error = wacom_setup_pad_input_capabilities(pad_input_dev, wacom_wac); |
| 1163 | if (error) { | 1180 | if (error) { |
| @@ -1169,22 +1186,23 @@ static int wacom_register_inputs(struct wacom *wacom) | |||
| 1169 | error = input_register_device(pad_input_dev); | 1186 | error = input_register_device(pad_input_dev); |
| 1170 | if (error) | 1187 | if (error) |
| 1171 | goto fail_register_pad_input; | 1188 | goto fail_register_pad_input; |
| 1189 | wacom_wac->pad_registered = true; | ||
| 1172 | 1190 | ||
| 1173 | error = wacom_initialize_leds(wacom); | 1191 | error = wacom_initialize_leds(wacom); |
| 1174 | if (error) | 1192 | if (error) |
| 1175 | goto fail_leds; | 1193 | goto fail_leds; |
| 1176 | } | 1194 | } |
| 1177 | 1195 | ||
| 1178 | wacom_wac->input_registered = true; | ||
| 1179 | |||
| 1180 | return 0; | 1196 | return 0; |
| 1181 | 1197 | ||
| 1182 | fail_leds: | 1198 | fail_leds: |
| 1183 | input_unregister_device(pad_input_dev); | 1199 | input_unregister_device(pad_input_dev); |
| 1184 | pad_input_dev = NULL; | 1200 | pad_input_dev = NULL; |
| 1201 | wacom_wac->pad_registered = false; | ||
| 1185 | fail_register_pad_input: | 1202 | fail_register_pad_input: |
| 1186 | input_unregister_device(input_dev); | 1203 | input_unregister_device(input_dev); |
| 1187 | wacom_wac->input = NULL; | 1204 | wacom_wac->input = NULL; |
| 1205 | wacom_wac->input_registered = false; | ||
| 1188 | return error; | 1206 | return error; |
| 1189 | } | 1207 | } |
| 1190 | 1208 | ||
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 586b2405b0d4..ac7447c7b82e 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c | |||
| @@ -25,6 +25,10 @@ | |||
| 25 | #define WACOM_INTUOS_RES 100 | 25 | #define WACOM_INTUOS_RES 100 |
| 26 | #define WACOM_INTUOS3_RES 200 | 26 | #define WACOM_INTUOS3_RES 200 |
| 27 | 27 | ||
| 28 | /* Newer Cintiq and DTU have an offset between tablet and screen areas */ | ||
| 29 | #define WACOM_DTU_OFFSET 200 | ||
| 30 | #define WACOM_CINTIQ_OFFSET 400 | ||
| 31 | |||
| 28 | /* | 32 | /* |
| 29 | * Scale factor relating reported contact size to logical contact area. | 33 | * Scale factor relating reported contact size to logical contact area. |
| 30 | * 2^14/pi is a good approximation on Intuos5 and 3rd-gen Bamboo | 34 | * 2^14/pi is a good approximation on Intuos5 and 3rd-gen Bamboo |
| @@ -600,8 +604,8 @@ static void wacom_intuos_general(struct wacom_wac *wacom) | |||
| 600 | } | 604 | } |
| 601 | input_report_abs(input, ABS_PRESSURE, t); | 605 | input_report_abs(input, ABS_PRESSURE, t); |
| 602 | input_report_abs(input, ABS_TILT_X, | 606 | input_report_abs(input, ABS_TILT_X, |
| 603 | ((data[7] << 1) & 0x7e) | (data[8] >> 7)); | 607 | (((data[7] << 1) & 0x7e) | (data[8] >> 7)) - 64); |
| 604 | input_report_abs(input, ABS_TILT_Y, data[8] & 0x7f); | 608 | input_report_abs(input, ABS_TILT_Y, (data[8] & 0x7f) - 64); |
| 605 | input_report_key(input, BTN_STYLUS, data[1] & 2); | 609 | input_report_key(input, BTN_STYLUS, data[1] & 2); |
| 606 | input_report_key(input, BTN_STYLUS2, data[1] & 4); | 610 | input_report_key(input, BTN_STYLUS2, data[1] & 4); |
| 607 | input_report_key(input, BTN_TOUCH, t > 10); | 611 | input_report_key(input, BTN_TOUCH, t > 10); |
| @@ -612,8 +616,8 @@ static void wacom_intuos_general(struct wacom_wac *wacom) | |||
| 612 | input_report_abs(input, ABS_WHEEL, | 616 | input_report_abs(input, ABS_WHEEL, |
| 613 | (data[6] << 2) | ((data[7] >> 6) & 3)); | 617 | (data[6] << 2) | ((data[7] >> 6) & 3)); |
| 614 | input_report_abs(input, ABS_TILT_X, | 618 | input_report_abs(input, ABS_TILT_X, |
| 615 | ((data[7] << 1) & 0x7e) | (data[8] >> 7)); | 619 | (((data[7] << 1) & 0x7e) | (data[8] >> 7)) - 64); |
| 616 | input_report_abs(input, ABS_TILT_Y, data[8] & 0x7f); | 620 | input_report_abs(input, ABS_TILT_Y, (data[8] & 0x7f) - 64); |
| 617 | } | 621 | } |
| 618 | } | 622 | } |
| 619 | 623 | ||
| @@ -915,8 +919,8 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) | |||
| 915 | input_report_key(input, BTN_EXTRA, data[6] & 0x10); | 919 | input_report_key(input, BTN_EXTRA, data[6] & 0x10); |
| 916 | 920 | ||
| 917 | input_report_abs(input, ABS_TILT_X, | 921 | input_report_abs(input, ABS_TILT_X, |
| 918 | ((data[7] << 1) & 0x7e) | (data[8] >> 7)); | 922 | (((data[7] << 1) & 0x7e) | (data[8] >> 7)) - 64); |
| 919 | input_report_abs(input, ABS_TILT_Y, data[8] & 0x7f); | 923 | input_report_abs(input, ABS_TILT_Y, (data[8] & 0x7f) - 64); |
| 920 | } else { | 924 | } else { |
| 921 | /* 2D mouse packet */ | 925 | /* 2D mouse packet */ |
| 922 | input_report_key(input, BTN_LEFT, data[8] & 0x04); | 926 | input_report_key(input, BTN_LEFT, data[8] & 0x04); |
| @@ -1377,11 +1381,12 @@ static void wacom_wac_finger_usage_mapping(struct hid_device *hdev, | |||
| 1377 | { | 1381 | { |
| 1378 | struct wacom *wacom = hid_get_drvdata(hdev); | 1382 | struct wacom *wacom = hid_get_drvdata(hdev); |
| 1379 | struct wacom_wac *wacom_wac = &wacom->wacom_wac; | 1383 | struct wacom_wac *wacom_wac = &wacom->wacom_wac; |
| 1380 | struct input_dev *input = wacom_wac->input; | 1384 | struct wacom_features *features = &wacom_wac->features; |
| 1381 | unsigned touch_max = wacom_wac->features.touch_max; | 1385 | unsigned touch_max = wacom_wac->features.touch_max; |
| 1382 | 1386 | ||
| 1383 | switch (usage->hid) { | 1387 | switch (usage->hid) { |
| 1384 | case HID_GD_X: | 1388 | case HID_GD_X: |
| 1389 | features->last_slot_field = usage->hid; | ||
| 1385 | if (touch_max == 1) | 1390 | if (touch_max == 1) |
| 1386 | wacom_map_usage(wacom, usage, field, EV_ABS, ABS_X, 4); | 1391 | wacom_map_usage(wacom, usage, field, EV_ABS, ABS_X, 4); |
| 1387 | else | 1392 | else |
| @@ -1389,6 +1394,7 @@ static void wacom_wac_finger_usage_mapping(struct hid_device *hdev, | |||
| 1389 | ABS_MT_POSITION_X, 4); | 1394 | ABS_MT_POSITION_X, 4); |
| 1390 | break; | 1395 | break; |
| 1391 | case HID_GD_Y: | 1396 | case HID_GD_Y: |
| 1397 | features->last_slot_field = usage->hid; | ||
| 1392 | if (touch_max == 1) | 1398 | if (touch_max == 1) |
| 1393 | wacom_map_usage(wacom, usage, field, EV_ABS, ABS_Y, 4); | 1399 | wacom_map_usage(wacom, usage, field, EV_ABS, ABS_Y, 4); |
| 1394 | else | 1400 | else |
| @@ -1396,19 +1402,48 @@ static void wacom_wac_finger_usage_mapping(struct hid_device *hdev, | |||
| 1396 | ABS_MT_POSITION_Y, 4); | 1402 | ABS_MT_POSITION_Y, 4); |
| 1397 | break; | 1403 | break; |
| 1398 | case HID_DG_CONTACTID: | 1404 | case HID_DG_CONTACTID: |
| 1399 | input_mt_init_slots(input, wacom_wac->features.touch_max, | 1405 | features->last_slot_field = usage->hid; |
| 1400 | INPUT_MT_DIRECT); | ||
| 1401 | break; | 1406 | break; |
| 1402 | case HID_DG_INRANGE: | 1407 | case HID_DG_INRANGE: |
| 1408 | features->last_slot_field = usage->hid; | ||
| 1403 | break; | 1409 | break; |
| 1404 | case HID_DG_INVERT: | 1410 | case HID_DG_INVERT: |
| 1411 | features->last_slot_field = usage->hid; | ||
| 1405 | break; | 1412 | break; |
| 1406 | case HID_DG_TIPSWITCH: | 1413 | case HID_DG_TIPSWITCH: |
| 1414 | features->last_slot_field = usage->hid; | ||
| 1407 | wacom_map_usage(wacom, usage, field, EV_KEY, BTN_TOUCH, 0); | 1415 | wacom_map_usage(wacom, usage, field, EV_KEY, BTN_TOUCH, 0); |
| 1408 | break; | 1416 | break; |
| 1409 | } | 1417 | } |
| 1410 | } | 1418 | } |
| 1411 | 1419 | ||
| 1420 | static void wacom_wac_finger_slot(struct wacom_wac *wacom_wac, | ||
| 1421 | struct input_dev *input) | ||
| 1422 | { | ||
| 1423 | struct hid_data *hid_data = &wacom_wac->hid_data; | ||
| 1424 | bool mt = wacom_wac->features.touch_max > 1; | ||
| 1425 | bool prox = hid_data->tipswitch && | ||
| 1426 | !wacom_wac->shared->stylus_in_proximity; | ||
| 1427 | |||
| 1428 | if (mt) { | ||
| 1429 | int slot; | ||
| 1430 | |||
| 1431 | slot = input_mt_get_slot_by_key(input, hid_data->id); | ||
| 1432 | input_mt_slot(input, slot); | ||
| 1433 | input_mt_report_slot_state(input, MT_TOOL_FINGER, prox); | ||
| 1434 | } | ||
| 1435 | else { | ||
| 1436 | input_report_key(input, BTN_TOUCH, prox); | ||
| 1437 | } | ||
| 1438 | |||
| 1439 | if (prox) { | ||
| 1440 | input_report_abs(input, mt ? ABS_MT_POSITION_X : ABS_X, | ||
| 1441 | hid_data->x); | ||
| 1442 | input_report_abs(input, mt ? ABS_MT_POSITION_Y : ABS_Y, | ||
| 1443 | hid_data->y); | ||
| 1444 | } | ||
| 1445 | } | ||
| 1446 | |||
| 1412 | static int wacom_wac_finger_event(struct hid_device *hdev, | 1447 | static int wacom_wac_finger_event(struct hid_device *hdev, |
| 1413 | struct hid_field *field, struct hid_usage *usage, __s32 value) | 1448 | struct hid_field *field, struct hid_usage *usage, __s32 value) |
| 1414 | { | 1449 | { |
| @@ -1431,36 +1466,35 @@ static int wacom_wac_finger_event(struct hid_device *hdev, | |||
| 1431 | } | 1466 | } |
| 1432 | 1467 | ||
| 1433 | 1468 | ||
| 1469 | if (usage->usage_index + 1 == field->report_count) { | ||
| 1470 | if (usage->hid == wacom_wac->features.last_slot_field) | ||
| 1471 | wacom_wac_finger_slot(wacom_wac, wacom_wac->input); | ||
| 1472 | } | ||
| 1473 | |||
| 1434 | return 0; | 1474 | return 0; |
| 1435 | } | 1475 | } |
| 1436 | 1476 | ||
| 1437 | static void wacom_wac_finger_mt_report(struct wacom_wac *wacom_wac, | 1477 | static int wacom_wac_finger_count_touches(struct hid_device *hdev) |
| 1438 | struct input_dev *input, bool touch) | ||
| 1439 | { | 1478 | { |
| 1440 | int slot; | 1479 | struct wacom *wacom = hid_get_drvdata(hdev); |
| 1441 | struct hid_data *hid_data = &wacom_wac->hid_data; | 1480 | struct wacom_wac *wacom_wac = &wacom->wacom_wac; |
| 1481 | struct input_dev *input = wacom_wac->input; | ||
| 1482 | unsigned touch_max = wacom_wac->features.touch_max; | ||
| 1483 | int count = 0; | ||
| 1484 | int i; | ||
| 1442 | 1485 | ||
| 1443 | slot = input_mt_get_slot_by_key(input, hid_data->id); | 1486 | if (touch_max == 1) |
| 1487 | return wacom_wac->hid_data.tipswitch && | ||
| 1488 | !wacom_wac->shared->stylus_in_proximity; | ||
| 1444 | 1489 | ||
| 1445 | input_mt_slot(input, slot); | 1490 | for (i = 0; i < input->mt->num_slots; i++) { |
| 1446 | input_mt_report_slot_state(input, MT_TOOL_FINGER, touch); | 1491 | struct input_mt_slot *ps = &input->mt->slots[i]; |
| 1447 | if (touch) { | 1492 | int id = input_mt_get_value(ps, ABS_MT_TRACKING_ID); |
| 1448 | input_report_abs(input, ABS_MT_POSITION_X, hid_data->x); | 1493 | if (id >= 0) |
| 1449 | input_report_abs(input, ABS_MT_POSITION_Y, hid_data->y); | 1494 | count++; |
| 1450 | } | 1495 | } |
| 1451 | input_mt_sync_frame(input); | ||
| 1452 | } | ||
| 1453 | 1496 | ||
| 1454 | static void wacom_wac_finger_single_touch_report(struct wacom_wac *wacom_wac, | 1497 | return count; |
| 1455 | struct input_dev *input, bool touch) | ||
| 1456 | { | ||
| 1457 | struct hid_data *hid_data = &wacom_wac->hid_data; | ||
| 1458 | |||
| 1459 | if (touch) { | ||
| 1460 | input_report_abs(input, ABS_X, hid_data->x); | ||
| 1461 | input_report_abs(input, ABS_Y, hid_data->y); | ||
| 1462 | } | ||
| 1463 | input_report_key(input, BTN_TOUCH, touch); | ||
| 1464 | } | 1498 | } |
| 1465 | 1499 | ||
| 1466 | static void wacom_wac_finger_report(struct hid_device *hdev, | 1500 | static void wacom_wac_finger_report(struct hid_device *hdev, |
| @@ -1469,24 +1503,23 @@ static void wacom_wac_finger_report(struct hid_device *hdev, | |||
| 1469 | struct wacom *wacom = hid_get_drvdata(hdev); | 1503 | struct wacom *wacom = hid_get_drvdata(hdev); |
| 1470 | struct wacom_wac *wacom_wac = &wacom->wacom_wac; | 1504 | struct wacom_wac *wacom_wac = &wacom->wacom_wac; |
| 1471 | struct input_dev *input = wacom_wac->input; | 1505 | struct input_dev *input = wacom_wac->input; |
| 1472 | bool touch = wacom_wac->hid_data.tipswitch && | ||
| 1473 | !wacom_wac->shared->stylus_in_proximity; | ||
| 1474 | unsigned touch_max = wacom_wac->features.touch_max; | 1506 | unsigned touch_max = wacom_wac->features.touch_max; |
| 1475 | 1507 | ||
| 1476 | if (touch_max > 1) | 1508 | if (touch_max > 1) |
| 1477 | wacom_wac_finger_mt_report(wacom_wac, input, touch); | 1509 | input_mt_sync_frame(input); |
| 1478 | else | 1510 | |
| 1479 | wacom_wac_finger_single_touch_report(wacom_wac, input, touch); | ||
| 1480 | input_sync(input); | 1511 | input_sync(input); |
| 1481 | 1512 | ||
| 1482 | /* keep touch state for pen event */ | 1513 | /* keep touch state for pen event */ |
| 1483 | wacom_wac->shared->touch_down = touch; | 1514 | wacom_wac->shared->touch_down = wacom_wac_finger_count_touches(hdev); |
| 1484 | } | 1515 | } |
| 1485 | 1516 | ||
| 1486 | #define WACOM_PEN_FIELD(f) (((f)->logical == HID_DG_STYLUS) || \ | 1517 | #define WACOM_PEN_FIELD(f) (((f)->logical == HID_DG_STYLUS) || \ |
| 1487 | ((f)->physical == HID_DG_STYLUS)) | 1518 | ((f)->physical == HID_DG_STYLUS) || \ |
| 1519 | ((f)->application == HID_DG_PEN)) | ||
| 1488 | #define WACOM_FINGER_FIELD(f) (((f)->logical == HID_DG_FINGER) || \ | 1520 | #define WACOM_FINGER_FIELD(f) (((f)->logical == HID_DG_FINGER) || \ |
| 1489 | ((f)->physical == HID_DG_FINGER)) | 1521 | ((f)->physical == HID_DG_FINGER) || \ |
| 1522 | ((f)->application == HID_DG_TOUCHSCREEN)) | ||
| 1490 | 1523 | ||
| 1491 | void wacom_wac_usage_mapping(struct hid_device *hdev, | 1524 | void wacom_wac_usage_mapping(struct hid_device *hdev, |
| 1492 | struct hid_field *field, struct hid_usage *usage) | 1525 | struct hid_field *field, struct hid_usage *usage) |
| @@ -1681,7 +1714,9 @@ static int wacom_bpt_pen(struct wacom_wac *wacom) | |||
| 1681 | return 0; | 1714 | return 0; |
| 1682 | 1715 | ||
| 1683 | if (data[0] == WACOM_REPORT_USB) { | 1716 | if (data[0] == WACOM_REPORT_USB) { |
| 1684 | if (features->type == INTUOSHT && features->touch_max) { | 1717 | if (features->type == INTUOSHT && |
| 1718 | wacom->shared->touch_input && | ||
| 1719 | features->touch_max) { | ||
| 1685 | input_report_switch(wacom->shared->touch_input, | 1720 | input_report_switch(wacom->shared->touch_input, |
| 1686 | SW_MUTE_DEVICE, data[8] & 0x40); | 1721 | SW_MUTE_DEVICE, data[8] & 0x40); |
| 1687 | input_sync(wacom->shared->touch_input); | 1722 | input_sync(wacom->shared->touch_input); |
| @@ -1774,7 +1809,8 @@ static int wacom_wireless_irq(struct wacom_wac *wacom, size_t len) | |||
| 1774 | int pid, battery, ps_connected; | 1809 | int pid, battery, ps_connected; |
| 1775 | 1810 | ||
| 1776 | if ((wacom->shared->type == INTUOSHT) && | 1811 | if ((wacom->shared->type == INTUOSHT) && |
| 1777 | wacom->shared->touch_max) { | 1812 | wacom->shared->touch_input && |
| 1813 | wacom->shared->touch_max) { | ||
| 1778 | input_report_switch(wacom->shared->touch_input, | 1814 | input_report_switch(wacom->shared->touch_input, |
| 1779 | SW_MUTE_DEVICE, data[5] & 0x40); | 1815 | SW_MUTE_DEVICE, data[5] & 0x40); |
| 1780 | input_sync(wacom->shared->touch_input); | 1816 | input_sync(wacom->shared->touch_input); |
| @@ -1838,6 +1874,7 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) | |||
| 1838 | break; | 1874 | break; |
| 1839 | 1875 | ||
| 1840 | case DTUS: | 1876 | case DTUS: |
| 1877 | case DTUSX: | ||
| 1841 | sync = wacom_dtus_irq(wacom_wac); | 1878 | sync = wacom_dtus_irq(wacom_wac); |
| 1842 | break; | 1879 | break; |
| 1843 | 1880 | ||
| @@ -1926,8 +1963,10 @@ static void wacom_setup_cintiq(struct wacom_wac *wacom_wac) | |||
| 1926 | input_set_abs_params(input_dev, ABS_DISTANCE, | 1963 | input_set_abs_params(input_dev, ABS_DISTANCE, |
| 1927 | 0, wacom_wac->features.distance_max, 0, 0); | 1964 | 0, wacom_wac->features.distance_max, 0, 0); |
| 1928 | input_set_abs_params(input_dev, ABS_WHEEL, 0, 1023, 0, 0); | 1965 | input_set_abs_params(input_dev, ABS_WHEEL, 0, 1023, 0, 0); |
| 1929 | input_set_abs_params(input_dev, ABS_TILT_X, 0, 127, 0, 0); | 1966 | input_set_abs_params(input_dev, ABS_TILT_X, -64, 63, 0, 0); |
| 1930 | input_set_abs_params(input_dev, ABS_TILT_Y, 0, 127, 0, 0); | 1967 | input_abs_set_res(input_dev, ABS_TILT_X, 57); |
| 1968 | input_set_abs_params(input_dev, ABS_TILT_Y, -64, 63, 0, 0); | ||
| 1969 | input_abs_set_res(input_dev, ABS_TILT_Y, 57); | ||
| 1931 | } | 1970 | } |
| 1932 | 1971 | ||
| 1933 | static void wacom_setup_intuos(struct wacom_wac *wacom_wac) | 1972 | static void wacom_setup_intuos(struct wacom_wac *wacom_wac) |
| @@ -1947,6 +1986,7 @@ static void wacom_setup_intuos(struct wacom_wac *wacom_wac) | |||
| 1947 | __set_bit(BTN_TOOL_LENS, input_dev->keybit); | 1986 | __set_bit(BTN_TOOL_LENS, input_dev->keybit); |
| 1948 | 1987 | ||
| 1949 | input_set_abs_params(input_dev, ABS_RZ, -900, 899, 0, 0); | 1988 | input_set_abs_params(input_dev, ABS_RZ, -900, 899, 0, 0); |
| 1989 | input_abs_set_res(input_dev, ABS_RZ, 287); | ||
| 1950 | input_set_abs_params(input_dev, ABS_THROTTLE, -1023, 1023, 0, 0); | 1990 | input_set_abs_params(input_dev, ABS_THROTTLE, -1023, 1023, 0, 0); |
| 1951 | } | 1991 | } |
| 1952 | 1992 | ||
| @@ -2029,7 +2069,7 @@ static void wacom_abs_set_axis(struct input_dev *input_dev, | |||
| 2029 | } | 2069 | } |
| 2030 | } | 2070 | } |
| 2031 | 2071 | ||
| 2032 | int wacom_setup_input_capabilities(struct input_dev *input_dev, | 2072 | int wacom_setup_pentouch_input_capabilities(struct input_dev *input_dev, |
| 2033 | struct wacom_wac *wacom_wac) | 2073 | struct wacom_wac *wacom_wac) |
| 2034 | { | 2074 | { |
| 2035 | struct wacom_features *features = &wacom_wac->features; | 2075 | struct wacom_features *features = &wacom_wac->features; |
| @@ -2047,9 +2087,6 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, | |||
| 2047 | 2087 | ||
| 2048 | switch (features->type) { | 2088 | switch (features->type) { |
| 2049 | case WACOM_MO: | 2089 | case WACOM_MO: |
| 2050 | input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0); | ||
| 2051 | /* fall through */ | ||
| 2052 | |||
| 2053 | case WACOM_G4: | 2090 | case WACOM_G4: |
| 2054 | /* fall through */ | 2091 | /* fall through */ |
| 2055 | 2092 | ||
| @@ -2092,6 +2129,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, | |||
| 2092 | 2129 | ||
| 2093 | case WACOM_24HD: | 2130 | case WACOM_24HD: |
| 2094 | input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); | 2131 | input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); |
| 2132 | input_abs_set_res(input_dev, ABS_Z, 287); | ||
| 2095 | input_set_abs_params(input_dev, ABS_THROTTLE, 0, 71, 0, 0); | 2133 | input_set_abs_params(input_dev, ABS_THROTTLE, 0, 71, 0, 0); |
| 2096 | /* fall through */ | 2134 | /* fall through */ |
| 2097 | 2135 | ||
| @@ -2106,6 +2144,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, | |||
| 2106 | case WACOM_BEE: | 2144 | case WACOM_BEE: |
| 2107 | case CINTIQ: | 2145 | case CINTIQ: |
| 2108 | input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); | 2146 | input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); |
| 2147 | input_abs_set_res(input_dev, ABS_Z, 287); | ||
| 2109 | 2148 | ||
| 2110 | __set_bit(INPUT_PROP_DIRECT, input_dev->propbit); | 2149 | __set_bit(INPUT_PROP_DIRECT, input_dev->propbit); |
| 2111 | 2150 | ||
| @@ -2114,6 +2153,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, | |||
| 2114 | 2153 | ||
| 2115 | case WACOM_13HD: | 2154 | case WACOM_13HD: |
| 2116 | input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); | 2155 | input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); |
| 2156 | input_abs_set_res(input_dev, ABS_Z, 287); | ||
| 2117 | __set_bit(INPUT_PROP_DIRECT, input_dev->propbit); | 2157 | __set_bit(INPUT_PROP_DIRECT, input_dev->propbit); |
| 2118 | wacom_setup_cintiq(wacom_wac); | 2158 | wacom_setup_cintiq(wacom_wac); |
| 2119 | break; | 2159 | break; |
| @@ -2122,6 +2162,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, | |||
| 2122 | case INTUOS3L: | 2162 | case INTUOS3L: |
| 2123 | case INTUOS3S: | 2163 | case INTUOS3S: |
| 2124 | input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); | 2164 | input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); |
| 2165 | input_abs_set_res(input_dev, ABS_Z, 287); | ||
| 2125 | /* fall through */ | 2166 | /* fall through */ |
| 2126 | 2167 | ||
| 2127 | case INTUOS: | 2168 | case INTUOS: |
| @@ -2144,6 +2185,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, | |||
| 2144 | 0, 0); | 2185 | 0, 0); |
| 2145 | 2186 | ||
| 2146 | input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); | 2187 | input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); |
| 2188 | input_abs_set_res(input_dev, ABS_Z, 287); | ||
| 2147 | 2189 | ||
| 2148 | wacom_setup_intuos(wacom_wac); | 2190 | wacom_setup_intuos(wacom_wac); |
| 2149 | } else if (features->device_type == BTN_TOOL_FINGER) { | 2191 | } else if (features->device_type == BTN_TOOL_FINGER) { |
| @@ -2162,6 +2204,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, | |||
| 2162 | case INTUOS4L: | 2204 | case INTUOS4L: |
| 2163 | case INTUOS4S: | 2205 | case INTUOS4S: |
| 2164 | input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); | 2206 | input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); |
| 2207 | input_abs_set_res(input_dev, ABS_Z, 287); | ||
| 2165 | wacom_setup_intuos(wacom_wac); | 2208 | wacom_setup_intuos(wacom_wac); |
| 2166 | 2209 | ||
| 2167 | __set_bit(INPUT_PROP_POINTER, input_dev->propbit); | 2210 | __set_bit(INPUT_PROP_POINTER, input_dev->propbit); |
| @@ -2196,6 +2239,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, | |||
| 2196 | /* fall through */ | 2239 | /* fall through */ |
| 2197 | 2240 | ||
| 2198 | case DTUS: | 2241 | case DTUS: |
| 2242 | case DTUSX: | ||
| 2199 | case PL: | 2243 | case PL: |
| 2200 | case DTU: | 2244 | case DTU: |
| 2201 | __set_bit(BTN_TOOL_PEN, input_dev->keybit); | 2245 | __set_bit(BTN_TOOL_PEN, input_dev->keybit); |
| @@ -2246,6 +2290,9 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, | |||
| 2246 | __clear_bit(ABS_X, input_dev->absbit); | 2290 | __clear_bit(ABS_X, input_dev->absbit); |
| 2247 | __clear_bit(ABS_Y, input_dev->absbit); | 2291 | __clear_bit(ABS_Y, input_dev->absbit); |
| 2248 | __clear_bit(BTN_TOUCH, input_dev->keybit); | 2292 | __clear_bit(BTN_TOUCH, input_dev->keybit); |
| 2293 | |||
| 2294 | /* PAD is setup by wacom_setup_pad_input_capabilities later */ | ||
| 2295 | return 1; | ||
| 2249 | } | 2296 | } |
| 2250 | } else if (features->device_type == BTN_TOOL_PEN) { | 2297 | } else if (features->device_type == BTN_TOOL_PEN) { |
| 2251 | __set_bit(INPUT_PROP_POINTER, input_dev->propbit); | 2298 | __set_bit(INPUT_PROP_POINTER, input_dev->propbit); |
| @@ -2261,6 +2308,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, | |||
| 2261 | 2308 | ||
| 2262 | case CINTIQ_HYBRID: | 2309 | case CINTIQ_HYBRID: |
| 2263 | input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); | 2310 | input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); |
| 2311 | input_abs_set_res(input_dev, ABS_Z, 287); | ||
| 2264 | __set_bit(INPUT_PROP_DIRECT, input_dev->propbit); | 2312 | __set_bit(INPUT_PROP_DIRECT, input_dev->propbit); |
| 2265 | 2313 | ||
| 2266 | wacom_setup_cintiq(wacom_wac); | 2314 | wacom_setup_cintiq(wacom_wac); |
| @@ -2303,9 +2351,7 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev, | |||
| 2303 | 2351 | ||
| 2304 | case WACOM_G4: | 2352 | case WACOM_G4: |
| 2305 | __set_bit(BTN_BACK, input_dev->keybit); | 2353 | __set_bit(BTN_BACK, input_dev->keybit); |
| 2306 | __set_bit(BTN_LEFT, input_dev->keybit); | ||
| 2307 | __set_bit(BTN_FORWARD, input_dev->keybit); | 2354 | __set_bit(BTN_FORWARD, input_dev->keybit); |
| 2308 | __set_bit(BTN_RIGHT, input_dev->keybit); | ||
| 2309 | input_set_capability(input_dev, EV_REL, REL_WHEEL); | 2355 | input_set_capability(input_dev, EV_REL, REL_WHEEL); |
| 2310 | break; | 2356 | break; |
| 2311 | 2357 | ||
| @@ -2402,7 +2448,7 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev, | |||
| 2402 | case INTUOSPS: | 2448 | case INTUOSPS: |
| 2403 | /* touch interface does not have the pad device */ | 2449 | /* touch interface does not have the pad device */ |
| 2404 | if (features->device_type != BTN_TOOL_PEN) | 2450 | if (features->device_type != BTN_TOOL_PEN) |
| 2405 | return 1; | 2451 | return -ENODEV; |
| 2406 | 2452 | ||
| 2407 | for (i = 0; i < 7; i++) | 2453 | for (i = 0; i < 7; i++) |
| 2408 | __set_bit(BTN_0 + i, input_dev->keybit); | 2454 | __set_bit(BTN_0 + i, input_dev->keybit); |
| @@ -2446,8 +2492,10 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev, | |||
| 2446 | case INTUOSHT: | 2492 | case INTUOSHT: |
| 2447 | case BAMBOO_PT: | 2493 | case BAMBOO_PT: |
| 2448 | /* pad device is on the touch interface */ | 2494 | /* pad device is on the touch interface */ |
| 2449 | if (features->device_type != BTN_TOOL_FINGER) | 2495 | if ((features->device_type != BTN_TOOL_FINGER) || |
| 2450 | return 1; | 2496 | /* Bamboo Pen only tablet does not have pad */ |
| 2497 | ((features->type == BAMBOO_PT) && !features->touch_max)) | ||
| 2498 | return -ENODEV; | ||
| 2451 | 2499 | ||
| 2452 | __clear_bit(ABS_MISC, input_dev->absbit); | 2500 | __clear_bit(ABS_MISC, input_dev->absbit); |
| 2453 | 2501 | ||
| @@ -2460,7 +2508,7 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev, | |||
| 2460 | 2508 | ||
| 2461 | default: | 2509 | default: |
| 2462 | /* no pad supported */ | 2510 | /* no pad supported */ |
| 2463 | return 1; | 2511 | return -ENODEV; |
| 2464 | } | 2512 | } |
| 2465 | return 0; | 2513 | return 0; |
| 2466 | } | 2514 | } |
| @@ -2664,11 +2712,13 @@ static const struct wacom_features wacom_features_0x317 = | |||
| 2664 | INTUOSPL, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, .touch_max = 16, | 2712 | INTUOSPL, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, .touch_max = 16, |
| 2665 | .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; | 2713 | .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; |
| 2666 | static const struct wacom_features wacom_features_0xF4 = | 2714 | static const struct wacom_features wacom_features_0xF4 = |
| 2667 | { "Wacom Cintiq 24HD", 104280, 65400, 2047, 63, | 2715 | { "Wacom Cintiq 24HD", 104080, 65200, 2047, 63, |
| 2668 | WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200 }; | 2716 | WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, |
| 2717 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET }; | ||
| 2669 | static const struct wacom_features wacom_features_0xF8 = | 2718 | static const struct wacom_features wacom_features_0xF8 = |
| 2670 | { "Wacom Cintiq 24HD touch", 104280, 65400, 2047, 63, /* Pen */ | 2719 | { "Wacom Cintiq 24HD touch", 104080, 65200, 2047, 63, /* Pen */ |
| 2671 | WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200, | 2720 | WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, |
| 2721 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, | ||
| 2672 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf6 }; | 2722 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf6 }; |
| 2673 | static const struct wacom_features wacom_features_0xF6 = | 2723 | static const struct wacom_features wacom_features_0xF6 = |
| 2674 | { "Wacom Cintiq 24HD touch", .type = WACOM_24HDT, /* Touch */ | 2724 | { "Wacom Cintiq 24HD touch", .type = WACOM_24HDT, /* Touch */ |
| @@ -2684,8 +2734,9 @@ static const struct wacom_features wacom_features_0xC6 = | |||
| 2684 | { "Wacom Cintiq 12WX", 53020, 33440, 1023, 63, | 2734 | { "Wacom Cintiq 12WX", 53020, 33440, 1023, 63, |
| 2685 | WACOM_BEE, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; | 2735 | WACOM_BEE, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; |
| 2686 | static const struct wacom_features wacom_features_0x304 = | 2736 | static const struct wacom_features wacom_features_0x304 = |
| 2687 | { "Wacom Cintiq 13HD", 59352, 33648, 1023, 63, | 2737 | { "Wacom Cintiq 13HD", 59152, 33448, 1023, 63, |
| 2688 | WACOM_13HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200 }; | 2738 | WACOM_13HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, |
| 2739 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET }; | ||
| 2689 | static const struct wacom_features wacom_features_0xC7 = | 2740 | static const struct wacom_features wacom_features_0xC7 = |
| 2690 | { "Wacom DTU1931", 37832, 30305, 511, 0, | 2741 | { "Wacom DTU1931", 37832, 30305, 511, 0, |
| 2691 | PL, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | 2742 | PL, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
| @@ -2697,28 +2748,38 @@ static const struct wacom_features wacom_features_0xF0 = | |||
| 2697 | { "Wacom DTU1631", 34623, 19553, 511, 0, | 2748 | { "Wacom DTU1631", 34623, 19553, 511, 0, |
| 2698 | DTU, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | 2749 | DTU, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
| 2699 | static const struct wacom_features wacom_features_0xFB = | 2750 | static const struct wacom_features wacom_features_0xFB = |
| 2700 | { "Wacom DTU1031", 22096, 13960, 511, 0, | 2751 | { "Wacom DTU1031", 21896, 13760, 511, 0, |
| 2701 | DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | 2752 | DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES, |
| 2753 | WACOM_DTU_OFFSET, WACOM_DTU_OFFSET }; | ||
| 2754 | static const struct wacom_features wacom_features_0x32F = | ||
| 2755 | { "Wacom DTU1031X", 22472, 12728, 511, 0, | ||
| 2756 | DTUSX, WACOM_INTUOS_RES, WACOM_INTUOS_RES, | ||
| 2757 | WACOM_DTU_OFFSET, WACOM_DTU_OFFSET }; | ||
| 2702 | static const struct wacom_features wacom_features_0x57 = | 2758 | static const struct wacom_features wacom_features_0x57 = |
| 2703 | { "Wacom DTK2241", 95640, 54060, 2047, 63, | 2759 | { "Wacom DTK2241", 95640, 54060, 2047, 63, |
| 2704 | DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200 }; | 2760 | DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, |
| 2761 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET }; | ||
| 2705 | static const struct wacom_features wacom_features_0x59 = /* Pen */ | 2762 | static const struct wacom_features wacom_features_0x59 = /* Pen */ |
| 2706 | { "Wacom DTH2242", 95640, 54060, 2047, 63, | 2763 | { "Wacom DTH2242", 95640, 54060, 2047, 63, |
| 2707 | DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200, | 2764 | DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, |
| 2765 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, | ||
| 2708 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x5D }; | 2766 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x5D }; |
| 2709 | static const struct wacom_features wacom_features_0x5D = /* Touch */ | 2767 | static const struct wacom_features wacom_features_0x5D = /* Touch */ |
| 2710 | { "Wacom DTH2242", .type = WACOM_24HDT, | 2768 | { "Wacom DTH2242", .type = WACOM_24HDT, |
| 2711 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x59, .touch_max = 10, | 2769 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x59, .touch_max = 10, |
| 2712 | .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; | 2770 | .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; |
| 2713 | static const struct wacom_features wacom_features_0xCC = | 2771 | static const struct wacom_features wacom_features_0xCC = |
| 2714 | { "Wacom Cintiq 21UX2", 87000, 65400, 2047, 63, | 2772 | { "Wacom Cintiq 21UX2", 86800, 65200, 2047, 63, |
| 2715 | WACOM_21UX2, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200 }; | 2773 | WACOM_21UX2, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, |
| 2774 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET }; | ||
| 2716 | static const struct wacom_features wacom_features_0xFA = | 2775 | static const struct wacom_features wacom_features_0xFA = |
| 2717 | { "Wacom Cintiq 22HD", 95640, 54060, 2047, 63, | 2776 | { "Wacom Cintiq 22HD", 95440, 53860, 2047, 63, |
| 2718 | WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200 }; | 2777 | WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, |
| 2778 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET }; | ||
| 2719 | static const struct wacom_features wacom_features_0x5B = | 2779 | static const struct wacom_features wacom_features_0x5B = |
| 2720 | { "Wacom Cintiq 22HDT", 95640, 54060, 2047, 63, | 2780 | { "Wacom Cintiq 22HDT", 95440, 53860, 2047, 63, |
| 2721 | WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200, | 2781 | WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, |
| 2782 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, | ||
| 2722 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x5e }; | 2783 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x5e }; |
| 2723 | static const struct wacom_features wacom_features_0x5E = | 2784 | static const struct wacom_features wacom_features_0x5E = |
| 2724 | { "Wacom Cintiq 22HDT", .type = WACOM_24HDT, | 2785 | { "Wacom Cintiq 22HDT", .type = WACOM_24HDT, |
| @@ -2863,21 +2924,27 @@ static const struct wacom_features wacom_features_0x6004 = | |||
| 2863 | { "ISD-V4", 12800, 8000, 255, 0, | 2924 | { "ISD-V4", 12800, 8000, 255, 0, |
| 2864 | TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | 2925 | TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
| 2865 | static const struct wacom_features wacom_features_0x307 = | 2926 | static const struct wacom_features wacom_features_0x307 = |
| 2866 | { "Wacom ISDv5 307", 59352, 33648, 2047, 63, | 2927 | { "Wacom ISDv5 307", 59152, 33448, 2047, 63, |
| 2867 | CINTIQ_HYBRID, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200, | 2928 | CINTIQ_HYBRID, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, |
| 2929 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, | ||
| 2868 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x309 }; | 2930 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x309 }; |
| 2869 | static const struct wacom_features wacom_features_0x309 = | 2931 | static const struct wacom_features wacom_features_0x309 = |
| 2870 | { "Wacom ISDv5 309", .type = WACOM_24HDT, /* Touch */ | 2932 | { "Wacom ISDv5 309", .type = WACOM_24HDT, /* Touch */ |
| 2871 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x0307, .touch_max = 10, | 2933 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x0307, .touch_max = 10, |
| 2872 | .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; | 2934 | .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; |
| 2873 | static const struct wacom_features wacom_features_0x30A = | 2935 | static const struct wacom_features wacom_features_0x30A = |
| 2874 | { "Wacom ISDv5 30A", 59352, 33648, 2047, 63, | 2936 | { "Wacom ISDv5 30A", 59152, 33448, 2047, 63, |
| 2875 | CINTIQ_HYBRID, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200, | 2937 | CINTIQ_HYBRID, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, |
| 2938 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, | ||
| 2876 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x30C }; | 2939 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x30C }; |
| 2877 | static const struct wacom_features wacom_features_0x30C = | 2940 | static const struct wacom_features wacom_features_0x30C = |
| 2878 | { "Wacom ISDv5 30C", .type = WACOM_24HDT, /* Touch */ | 2941 | { "Wacom ISDv5 30C", .type = WACOM_24HDT, /* Touch */ |
| 2879 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x30A, .touch_max = 10, | 2942 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x30A, .touch_max = 10, |
| 2880 | .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; | 2943 | .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; |
| 2944 | static const struct wacom_features wacom_features_0x323 = | ||
| 2945 | { "Wacom Intuos P M", 21600, 13500, 1023, 31, | ||
| 2946 | INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, | ||
| 2947 | .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; | ||
| 2881 | 2948 | ||
| 2882 | static const struct wacom_features wacom_features_HID_ANY_ID = | 2949 | static const struct wacom_features wacom_features_HID_ANY_ID = |
| 2883 | { "Wacom HID", .type = HID_GENERIC }; | 2950 | { "Wacom HID", .type = HID_GENERIC }; |
| @@ -3022,10 +3089,13 @@ const struct hid_device_id wacom_ids[] = { | |||
| 3022 | { USB_DEVICE_WACOM(0x314) }, | 3089 | { USB_DEVICE_WACOM(0x314) }, |
| 3023 | { USB_DEVICE_WACOM(0x315) }, | 3090 | { USB_DEVICE_WACOM(0x315) }, |
| 3024 | { USB_DEVICE_WACOM(0x317) }, | 3091 | { USB_DEVICE_WACOM(0x317) }, |
| 3092 | { USB_DEVICE_WACOM(0x323) }, | ||
| 3093 | { USB_DEVICE_WACOM(0x32F) }, | ||
| 3025 | { USB_DEVICE_WACOM(0x4001) }, | 3094 | { USB_DEVICE_WACOM(0x4001) }, |
| 3026 | { USB_DEVICE_WACOM(0x4004) }, | 3095 | { USB_DEVICE_WACOM(0x4004) }, |
| 3027 | { USB_DEVICE_WACOM(0x5000) }, | 3096 | { USB_DEVICE_WACOM(0x5000) }, |
| 3028 | { USB_DEVICE_WACOM(0x5002) }, | 3097 | { USB_DEVICE_WACOM(0x5002) }, |
| 3098 | { USB_DEVICE_LENOVO(0x6004) }, | ||
| 3029 | 3099 | ||
| 3030 | { USB_DEVICE_WACOM(HID_ANY_ID) }, | 3100 | { USB_DEVICE_WACOM(HID_ANY_ID) }, |
| 3031 | { } | 3101 | { } |
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h index 0f0b85ec1322..bfad815cda8a 100644 --- a/drivers/hid/wacom_wac.h +++ b/drivers/hid/wacom_wac.h | |||
| @@ -80,6 +80,7 @@ enum { | |||
| 80 | PL, | 80 | PL, |
| 81 | DTU, | 81 | DTU, |
| 82 | DTUS, | 82 | DTUS, |
| 83 | DTUSX, | ||
| 83 | INTUOS, | 84 | INTUOS, |
| 84 | INTUOS3S, | 85 | INTUOS3S, |
| 85 | INTUOS3, | 86 | INTUOS3, |
| @@ -144,6 +145,7 @@ struct wacom_features { | |||
| 144 | int pktlen; | 145 | int pktlen; |
| 145 | bool check_for_hid_type; | 146 | bool check_for_hid_type; |
| 146 | int hid_type; | 147 | int hid_type; |
| 148 | int last_slot_field; | ||
| 147 | }; | 149 | }; |
| 148 | 150 | ||
| 149 | struct wacom_shared { | 151 | struct wacom_shared { |
| @@ -183,6 +185,7 @@ struct wacom_wac { | |||
| 183 | struct input_dev *input; | 185 | struct input_dev *input; |
| 184 | struct input_dev *pad_input; | 186 | struct input_dev *pad_input; |
| 185 | bool input_registered; | 187 | bool input_registered; |
| 188 | bool pad_registered; | ||
| 186 | int pid; | 189 | int pid; |
| 187 | int battery_capacity; | 190 | int battery_capacity; |
| 188 | int num_contacts_left; | 191 | int num_contacts_left; |
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index 39b4081b632d..8e8bc4f9d2f0 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c | |||
| @@ -100,6 +100,9 @@ static const struct usb_device_id usb_quirk_list[] = { | |||
| 100 | { USB_DEVICE(0x04f3, 0x009b), .driver_info = | 100 | { USB_DEVICE(0x04f3, 0x009b), .driver_info = |
| 101 | USB_QUIRK_DEVICE_QUALIFIER }, | 101 | USB_QUIRK_DEVICE_QUALIFIER }, |
| 102 | 102 | ||
| 103 | { USB_DEVICE(0x04f3, 0x010c), .driver_info = | ||
| 104 | USB_QUIRK_DEVICE_QUALIFIER }, | ||
| 105 | |||
| 103 | { USB_DEVICE(0x04f3, 0x016f), .driver_info = | 106 | { USB_DEVICE(0x04f3, 0x016f), .driver_info = |
| 104 | USB_QUIRK_DEVICE_QUALIFIER }, | 107 | USB_QUIRK_DEVICE_QUALIFIER }, |
| 105 | 108 | ||
diff --git a/include/linux/hid.h b/include/linux/hid.h index 2366fda010c8..06c4607744f6 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h | |||
| @@ -234,6 +234,33 @@ struct hid_item { | |||
| 234 | #define HID_DG_BARRELSWITCH 0x000d0044 | 234 | #define HID_DG_BARRELSWITCH 0x000d0044 |
| 235 | #define HID_DG_ERASER 0x000d0045 | 235 | #define HID_DG_ERASER 0x000d0045 |
| 236 | #define HID_DG_TABLETPICK 0x000d0046 | 236 | #define HID_DG_TABLETPICK 0x000d0046 |
| 237 | |||
| 238 | #define HID_CP_CONSUMERCONTROL 0x000c0001 | ||
| 239 | #define HID_CP_NUMERICKEYPAD 0x000c0002 | ||
| 240 | #define HID_CP_PROGRAMMABLEBUTTONS 0x000c0003 | ||
| 241 | #define HID_CP_MICROPHONE 0x000c0004 | ||
| 242 | #define HID_CP_HEADPHONE 0x000c0005 | ||
| 243 | #define HID_CP_GRAPHICEQUALIZER 0x000c0006 | ||
| 244 | #define HID_CP_FUNCTIONBUTTONS 0x000c0036 | ||
| 245 | #define HID_CP_SELECTION 0x000c0080 | ||
| 246 | #define HID_CP_MEDIASELECTION 0x000c0087 | ||
| 247 | #define HID_CP_SELECTDISC 0x000c00ba | ||
| 248 | #define HID_CP_PLAYBACKSPEED 0x000c00f1 | ||
| 249 | #define HID_CP_PROXIMITY 0x000c0109 | ||
| 250 | #define HID_CP_SPEAKERSYSTEM 0x000c0160 | ||
| 251 | #define HID_CP_CHANNELLEFT 0x000c0161 | ||
| 252 | #define HID_CP_CHANNELRIGHT 0x000c0162 | ||
| 253 | #define HID_CP_CHANNELCENTER 0x000c0163 | ||
| 254 | #define HID_CP_CHANNELFRONT 0x000c0164 | ||
| 255 | #define HID_CP_CHANNELCENTERFRONT 0x000c0165 | ||
| 256 | #define HID_CP_CHANNELSIDE 0x000c0166 | ||
| 257 | #define HID_CP_CHANNELSURROUND 0x000c0167 | ||
| 258 | #define HID_CP_CHANNELLOWFREQUENCYENHANCEMENT 0x000c0168 | ||
| 259 | #define HID_CP_CHANNELTOP 0x000c0169 | ||
| 260 | #define HID_CP_CHANNELUNKNOWN 0x000c016a | ||
| 261 | #define HID_CP_APPLICATIONLAUNCHBUTTONS 0x000c0180 | ||
| 262 | #define HID_CP_GENERICGUIAPPLICATIONCONTROLS 0x000c0200 | ||
| 263 | |||
| 237 | #define HID_DG_CONFIDENCE 0x000d0047 | 264 | #define HID_DG_CONFIDENCE 0x000d0047 |
| 238 | #define HID_DG_WIDTH 0x000d0048 | 265 | #define HID_DG_WIDTH 0x000d0048 |
| 239 | #define HID_DG_HEIGHT 0x000d0049 | 266 | #define HID_DG_HEIGHT 0x000d0049 |
| @@ -312,11 +339,8 @@ struct hid_item { | |||
| 312 | * Vendor specific HID device groups | 339 | * Vendor specific HID device groups |
| 313 | */ | 340 | */ |
| 314 | #define HID_GROUP_RMI 0x0100 | 341 | #define HID_GROUP_RMI 0x0100 |
| 315 | |||
| 316 | /* | ||
| 317 | * Vendor specific HID device groups | ||
| 318 | */ | ||
| 319 | #define HID_GROUP_WACOM 0x0101 | 342 | #define HID_GROUP_WACOM 0x0101 |
| 343 | #define HID_GROUP_LOGITECH_DJ_DEVICE 0x0102 | ||
| 320 | 344 | ||
| 321 | /* | 345 | /* |
| 322 | * This is the global environment of the parser. This information is | 346 | * This is the global environment of the parser. This information is |
