diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-10 13:48:28 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-10 13:48:28 -0500 |
| commit | f62f61917d72c1fb0101ad405664f6fc868d676b (patch) | |
| tree | cedeb85a8d1c97dc3be0b667734b0fe4e0dd84b6 | |
| parent | d04baa157d1b35cbd27c87b4a13111d9675b61f3 (diff) | |
| parent | 420174afdc7023c000e5b5b1b6fe9e028470c713 (diff) | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid: (68 commits)
hid-input/battery: add FEATURE quirk
hid-input/battery: remove battery_val
hid-input/battery: power-supply type really *is* a battery
hid-input/battery: make the battery setup common for INPUTs and FEATUREs
hid-input/battery: deal with both FEATURE and INPUT report batteries
hid-input/battery: add quirks for battery
hid-input/battery: remove apparently redundant kmalloc
hid-input: add support for HID devices reporting Battery Strength
HID: hid-multitouch: add support 9 new Xiroku devices
HID: multitouch: add support for 3M 32"
HID: multitouch: add support of Atmel multitouch panels
HID: usbhid: defer LED setting to a workqueue
HID: usbhid: hid-core: submit queued urbs before suspend
HID: usbhid: remove LED_ON
HID: emsff: use symbolic name instead of hardcoded PID constant
HID: Enable HID_QUIRK_MULTI_INPUT for Trio Linker Plus II
HID: Kconfig: fix syntax
HID: introduce proper dependency of HID_BATTERY on POWER_SUPPLY
HID: multitouch: support PixArt optical touch screen
HID: make parser more verbose about parsing errors by default
...
Fix up rename/delete conflict in drivers/hid/hid-hyperv.c (removed in
staging, moved in this branch) and similarly for the rules for same file
in drivers/staging/hv/{Kconfig,Makefile}.
30 files changed, 3592 insertions, 631 deletions
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-multitouch b/Documentation/ABI/testing/sysfs-driver-hid-multitouch new file mode 100644 index 000000000000..f79839d1af37 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-driver-hid-multitouch | |||
| @@ -0,0 +1,9 @@ | |||
| 1 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/quirks | ||
| 2 | Date: November 2011 | ||
| 3 | Contact: Benjamin Tissoires <benjamin.tissoires@gmail.com> | ||
| 4 | Description: The integer value of this attribute corresponds to the | ||
| 5 | quirks actually in place to handle the device's protocol. | ||
| 6 | When read, this attribute returns the current settings (see | ||
| 7 | MT_QUIRKS_* in hid-multitouch.c). | ||
| 8 | When written this attribute change on the fly the quirks, then | ||
| 9 | the protocol to handle the device. | ||
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-isku b/Documentation/ABI/testing/sysfs-driver-hid-roccat-isku new file mode 100644 index 000000000000..189dc43891bf --- /dev/null +++ b/Documentation/ABI/testing/sysfs-driver-hid-roccat-isku | |||
| @@ -0,0 +1,135 @@ | |||
| 1 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/isku/roccatisku<minor>/actual_profile | ||
| 2 | Date: June 2011 | ||
| 3 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 4 | Description: The integer value of this attribute ranges from 0-4. | ||
| 5 | When read, this attribute returns the number of the actual | ||
| 6 | profile. This value is persistent, so its equivalent to the | ||
| 7 | profile that's active when the device is powered on next time. | ||
| 8 | When written, this file sets the number of the startup profile | ||
| 9 | and the device activates this profile immediately. | ||
| 10 | Users: http://roccat.sourceforge.net | ||
| 11 | |||
| 12 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/isku/roccatisku<minor>/info | ||
| 13 | Date: June 2011 | ||
| 14 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 15 | Description: When read, this file returns general data like firmware version. | ||
| 16 | The data is 6 bytes long. | ||
| 17 | This file is readonly. | ||
| 18 | Users: http://roccat.sourceforge.net | ||
| 19 | |||
| 20 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/isku/roccatisku<minor>/key_mask | ||
| 21 | Date: June 2011 | ||
| 22 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 23 | Description: When written, this file lets one deactivate certain keys like | ||
| 24 | windows and application keys, to prevent accidental presses. | ||
| 25 | Profile number for which this settings occur is included in | ||
| 26 | written data. The data has to be 6 bytes long. | ||
| 27 | Before reading this file, control has to be written to select | ||
| 28 | which profile to read. | ||
| 29 | Users: http://roccat.sourceforge.net | ||
| 30 | |||
| 31 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/isku/roccatisku<minor>/keys_capslock | ||
| 32 | Date: June 2011 | ||
| 33 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 34 | Description: When written, this file lets one set the function of the | ||
| 35 | capslock key for a specific profile. Profile number is included | ||
| 36 | in written data. The data has to be 6 bytes long. | ||
| 37 | Before reading this file, control has to be written to select | ||
| 38 | which profile to read. | ||
| 39 | Users: http://roccat.sourceforge.net | ||
| 40 | |||
| 41 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/isku/roccatisku<minor>/keys_easyzone | ||
| 42 | Date: June 2011 | ||
| 43 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 44 | Description: When written, this file lets one set the function of the | ||
| 45 | easyzone keys for a specific profile. Profile number is included | ||
| 46 | in written data. The data has to be 65 bytes long. | ||
| 47 | Before reading this file, control has to be written to select | ||
| 48 | which profile to read. | ||
| 49 | Users: http://roccat.sourceforge.net | ||
| 50 | |||
| 51 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/isku/roccatisku<minor>/keys_function | ||
| 52 | Date: June 2011 | ||
| 53 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 54 | Description: When written, this file lets one set the function of the | ||
| 55 | function keys for a specific profile. Profile number is included | ||
| 56 | in written data. The data has to be 41 bytes long. | ||
| 57 | Before reading this file, control has to be written to select | ||
| 58 | which profile to read. | ||
| 59 | Users: http://roccat.sourceforge.net | ||
| 60 | |||
| 61 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/isku/roccatisku<minor>/keys_macro | ||
| 62 | Date: June 2011 | ||
| 63 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 64 | Description: When written, this file lets one set the function of the macro | ||
| 65 | keys for a specific profile. Profile number is included in | ||
| 66 | written data. The data has to be 35 bytes long. | ||
| 67 | Before reading this file, control has to be written to select | ||
| 68 | which profile to read. | ||
| 69 | Users: http://roccat.sourceforge.net | ||
| 70 | |||
| 71 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/isku/roccatisku<minor>/keys_media | ||
| 72 | Date: June 2011 | ||
| 73 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 74 | Description: When written, this file lets one set the function of the media | ||
| 75 | keys for a specific profile. Profile number is included in | ||
| 76 | written data. The data has to be 29 bytes long. | ||
| 77 | Before reading this file, control has to be written to select | ||
| 78 | which profile to read. | ||
| 79 | Users: http://roccat.sourceforge.net | ||
| 80 | |||
| 81 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/isku/roccatisku<minor>/keys_thumbster | ||
| 82 | Date: June 2011 | ||
| 83 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 84 | Description: When written, this file lets one set the function of the | ||
| 85 | thumbster keys for a specific profile. Profile number is included | ||
| 86 | in written data. The data has to be 23 bytes long. | ||
| 87 | Before reading this file, control has to be written to select | ||
| 88 | which profile to read. | ||
| 89 | Users: http://roccat.sourceforge.net | ||
| 90 | |||
| 91 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/isku/roccatisku<minor>/last_set | ||
| 92 | Date: June 2011 | ||
| 93 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 94 | Description: When written, this file lets one set the time in secs since | ||
| 95 | epoch in which the last configuration took place. | ||
| 96 | The data has to be 20 bytes long. | ||
| 97 | Users: http://roccat.sourceforge.net | ||
| 98 | |||
| 99 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/isku/roccatisku<minor>/light | ||
| 100 | Date: June 2011 | ||
| 101 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 102 | Description: When written, this file lets one set the backlight intensity for | ||
| 103 | a specific profile. Profile number is included in written data. | ||
| 104 | The data has to be 10 bytes long. | ||
| 105 | Before reading this file, control has to be written to select | ||
| 106 | which profile to read. | ||
| 107 | Users: http://roccat.sourceforge.net | ||
| 108 | |||
| 109 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/isku/roccatisku<minor>/macro | ||
| 110 | Date: June 2011 | ||
| 111 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 112 | Description: When written, this file lets one store macros with max 500 | ||
| 113 | keystrokes for a specific button for a specific profile. | ||
| 114 | Button and profile numbers are included in written data. | ||
| 115 | The data has to be 2083 bytes long. | ||
| 116 | Before reading this file, control has to be written to select | ||
| 117 | which profile and key to read. | ||
| 118 | Users: http://roccat.sourceforge.net | ||
| 119 | |||
| 120 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/isku/roccatisku<minor>/control | ||
| 121 | Date: June 2011 | ||
| 122 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 123 | Description: When written, this file lets one select which data from which | ||
| 124 | profile will be read next. The data has to be 3 bytes long. | ||
| 125 | This file is writeonly. | ||
| 126 | Users: http://roccat.sourceforge.net | ||
| 127 | |||
| 128 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/isku/roccatisku<minor>/talk | ||
| 129 | Date: June 2011 | ||
| 130 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 131 | Description: When written, this file lets one trigger easyshift functionality | ||
| 132 | from the host. | ||
| 133 | The data has to be 16 bytes long. | ||
| 134 | This file is writeonly. | ||
| 135 | Users: http://roccat.sourceforge.net | ||
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-wiimote b/Documentation/ABI/testing/sysfs-driver-hid-wiimote index 5d5a16ea57c6..3d98009f447a 100644 --- a/Documentation/ABI/testing/sysfs-driver-hid-wiimote +++ b/Documentation/ABI/testing/sysfs-driver-hid-wiimote | |||
| @@ -8,3 +8,15 @@ Contact: David Herrmann <dh.herrmann@googlemail.com> | |||
| 8 | Description: Make it possible to set/get current led state. Reading from it | 8 | Description: Make it possible to set/get current led state. Reading from it |
| 9 | returns 0 if led is off and 1 if it is on. Writing 0 to it | 9 | returns 0 if led is off and 1 if it is on. Writing 0 to it |
| 10 | disables the led, writing 1 enables it. | 10 | disables the led, writing 1 enables it. |
| 11 | |||
| 12 | What: /sys/bus/hid/drivers/wiimote/<dev>/extension | ||
| 13 | Date: August 2011 | ||
| 14 | KernelVersion: 3.2 | ||
| 15 | Contact: David Herrmann <dh.herrmann@googlemail.com> | ||
| 16 | Description: This file contains the currently connected and initialized | ||
| 17 | extensions. It can be one of: none, motionp, nunchuck, classic, | ||
| 18 | motionp+nunchuck, motionp+classic | ||
| 19 | motionp is the official Nintendo Motion+ extension, nunchuck is | ||
| 20 | the official Nintendo Nunchuck extension and classic is the | ||
| 21 | Nintendo Classic Controller extension. The motionp extension can | ||
| 22 | be combined with the other two. | ||
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 22a4a051f221..a421abdd1ab7 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig | |||
| @@ -31,6 +31,11 @@ config HID | |||
| 31 | 31 | ||
| 32 | If unsure, say Y. | 32 | If unsure, say Y. |
| 33 | 33 | ||
| 34 | config HID_BATTERY_STRENGTH | ||
| 35 | bool | ||
| 36 | depends on HID && POWER_SUPPLY && HID = POWER_SUPPLY | ||
| 37 | default y | ||
| 38 | |||
| 34 | config HIDRAW | 39 | config HIDRAW |
| 35 | bool "/dev/hidraw raw HID device support" | 40 | bool "/dev/hidraw raw HID device support" |
| 36 | depends on HID | 41 | depends on HID |
| @@ -335,6 +340,7 @@ config HID_MULTITOUCH | |||
| 335 | Say Y here if you have one of the following devices: | 340 | Say Y here if you have one of the following devices: |
| 336 | - 3M PCT touch screens | 341 | - 3M PCT touch screens |
| 337 | - ActionStar dual touch panels | 342 | - ActionStar dual touch panels |
| 343 | - Atmel panels | ||
| 338 | - Cando dual touch panels | 344 | - Cando dual touch panels |
| 339 | - Chunghwa panels | 345 | - Chunghwa panels |
| 340 | - CVTouch panels | 346 | - CVTouch panels |
| @@ -349,12 +355,15 @@ config HID_MULTITOUCH | |||
| 349 | - Lumio CrystalTouch panels | 355 | - Lumio CrystalTouch panels |
| 350 | - MosArt dual-touch panels | 356 | - MosArt dual-touch panels |
| 351 | - PenMount dual touch panels | 357 | - PenMount dual touch panels |
| 358 | - PixArt optical touch screen | ||
| 352 | - Pixcir dual touch panels | 359 | - Pixcir dual touch panels |
| 360 | - Quanta panels | ||
| 353 | - eGalax dual-touch panels, including the Joojoo and Wetab tablets | 361 | - eGalax dual-touch panels, including the Joojoo and Wetab tablets |
| 354 | - Stantum multitouch panels | 362 | - Stantum multitouch panels |
| 355 | - Touch International Panels | 363 | - Touch International Panels |
| 356 | - Unitec Panels | 364 | - Unitec Panels |
| 357 | - XAT optical touch panels | 365 | - XAT optical touch panels |
| 366 | - Xiroku optical touch panels | ||
| 358 | 367 | ||
| 359 | If unsure, say N. | 368 | If unsure, say N. |
| 360 | 369 | ||
| @@ -466,12 +475,6 @@ config HID_PRIMAX | |||
| 466 | Support for Primax devices that are not fully compliant with the | 475 | Support for Primax devices that are not fully compliant with the |
| 467 | HID standard. | 476 | HID standard. |
| 468 | 477 | ||
| 469 | config HID_QUANTA | ||
| 470 | tristate "Quanta Optical Touch panels" | ||
| 471 | depends on USB_HID | ||
| 472 | ---help--- | ||
| 473 | Support for Quanta Optical Touch dual-touch panels. | ||
| 474 | |||
| 475 | config HID_ROCCAT | 478 | config HID_ROCCAT |
| 476 | tristate "Roccat special event support" | 479 | tristate "Roccat special event support" |
| 477 | depends on USB_HID | 480 | depends on USB_HID |
| @@ -492,6 +495,13 @@ config HID_ROCCAT_ARVO | |||
| 492 | ---help--- | 495 | ---help--- |
| 493 | Support for Roccat Arvo keyboard. | 496 | Support for Roccat Arvo keyboard. |
| 494 | 497 | ||
| 498 | config HID_ROCCAT_ISKU | ||
| 499 | tristate "Roccat Isku keyboard support" | ||
| 500 | depends on USB_HID | ||
| 501 | depends on HID_ROCCAT | ||
| 502 | ---help--- | ||
| 503 | Support for Roccat Isku keyboard. | ||
| 504 | |||
| 495 | config HID_ROCCAT_KONE | 505 | config HID_ROCCAT_KONE |
| 496 | tristate "Roccat Kone Mouse support" | 506 | tristate "Roccat Kone Mouse support" |
| 497 | depends on USB_HID | 507 | depends on USB_HID |
| @@ -560,6 +570,12 @@ config GREENASIA_FF | |||
| 560 | (like MANTA Warrior MM816 and SpeedLink Strike2 SL-6635) or adapter | 570 | (like MANTA Warrior MM816 and SpeedLink Strike2 SL-6635) or adapter |
| 561 | and want to enable force feedback support for it. | 571 | and want to enable force feedback support for it. |
| 562 | 572 | ||
| 573 | config HID_HYPERV_MOUSE | ||
| 574 | tristate "Microsoft Hyper-V mouse driver" | ||
| 575 | depends on HYPERV | ||
| 576 | ---help--- | ||
| 577 | Select this option to enable the Hyper-V mouse driver. | ||
| 578 | |||
| 563 | config HID_SMARTJOYPLUS | 579 | config HID_SMARTJOYPLUS |
| 564 | tristate "SmartJoy PLUS PS2/USB adapter support" | 580 | tristate "SmartJoy PLUS PS2/USB adapter support" |
| 565 | depends on USB_HID | 581 | depends on USB_HID |
| @@ -620,9 +636,19 @@ config HID_WIIMOTE | |||
| 620 | depends on BT_HIDP | 636 | depends on BT_HIDP |
| 621 | depends on LEDS_CLASS | 637 | depends on LEDS_CLASS |
| 622 | select POWER_SUPPLY | 638 | select POWER_SUPPLY |
| 639 | select INPUT_FF_MEMLESS | ||
| 623 | ---help--- | 640 | ---help--- |
| 624 | Support for the Nintendo Wii Remote bluetooth device. | 641 | Support for the Nintendo Wii Remote bluetooth device. |
| 625 | 642 | ||
| 643 | config HID_WIIMOTE_EXT | ||
| 644 | bool "Nintendo Wii Remote Extension support" | ||
| 645 | depends on HID_WIIMOTE | ||
| 646 | default HID_WIIMOTE | ||
| 647 | ---help--- | ||
| 648 | Support for extension controllers of the Nintendo Wii Remote. Say yes | ||
| 649 | here if you want to use the Nintendo Motion+, Nunchuck or Classic | ||
| 650 | extension controllers with your Wii Remote. | ||
| 651 | |||
| 626 | config HID_ZEROPLUS | 652 | config HID_ZEROPLUS |
| 627 | tristate "Zeroplus based game controller support" | 653 | tristate "Zeroplus based game controller support" |
| 628 | depends on USB_HID | 654 | depends on USB_HID |
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index 1e0d2a638b28..8aefdc963cce 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile | |||
| @@ -25,6 +25,14 @@ ifdef CONFIG_LOGIWHEELS_FF | |||
| 25 | hid-logitech-y += hid-lg4ff.o | 25 | hid-logitech-y += hid-lg4ff.o |
| 26 | endif | 26 | endif |
| 27 | 27 | ||
| 28 | hid-wiimote-y := hid-wiimote-core.o | ||
| 29 | ifdef CONFIG_HID_WIIMOTE_EXT | ||
| 30 | hid-wiimote-y += hid-wiimote-ext.o | ||
| 31 | endif | ||
| 32 | ifdef CONFIG_DEBUG_FS | ||
| 33 | hid-wiimote-y += hid-wiimote-debug.o | ||
| 34 | endif | ||
| 35 | |||
| 28 | obj-$(CONFIG_HID_A4TECH) += hid-a4tech.o | 36 | obj-$(CONFIG_HID_A4TECH) += hid-a4tech.o |
| 29 | obj-$(CONFIG_HID_ACRUX) += hid-axff.o | 37 | obj-$(CONFIG_HID_ACRUX) += hid-axff.o |
| 30 | obj-$(CONFIG_HID_APPLE) += hid-apple.o | 38 | obj-$(CONFIG_HID_APPLE) += hid-apple.o |
| @@ -38,6 +46,7 @@ obj-$(CONFIG_HID_ELECOM) += hid-elecom.o | |||
| 38 | obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o | 46 | obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o |
| 39 | obj-$(CONFIG_HID_GYRATION) += hid-gyration.o | 47 | obj-$(CONFIG_HID_GYRATION) += hid-gyration.o |
| 40 | obj-$(CONFIG_HID_HOLTEK) += hid-holtekff.o | 48 | obj-$(CONFIG_HID_HOLTEK) += hid-holtekff.o |
| 49 | obj-$(CONFIG_HID_HYPERV_MOUSE) += hid-hyperv.o | ||
| 41 | obj-$(CONFIG_HID_KENSINGTON) += hid-kensington.o | 50 | obj-$(CONFIG_HID_KENSINGTON) += hid-kensington.o |
| 42 | obj-$(CONFIG_HID_KEYTOUCH) += hid-keytouch.o | 51 | obj-$(CONFIG_HID_KEYTOUCH) += hid-keytouch.o |
| 43 | obj-$(CONFIG_HID_KYE) += hid-kye.o | 52 | obj-$(CONFIG_HID_KYE) += hid-kye.o |
| @@ -51,7 +60,6 @@ obj-$(CONFIG_HID_MULTITOUCH) += hid-multitouch.o | |||
| 51 | obj-$(CONFIG_HID_NTRIG) += hid-ntrig.o | 60 | obj-$(CONFIG_HID_NTRIG) += hid-ntrig.o |
| 52 | obj-$(CONFIG_HID_ORTEK) += hid-ortek.o | 61 | obj-$(CONFIG_HID_ORTEK) += hid-ortek.o |
| 53 | obj-$(CONFIG_HID_PRODIKEYS) += hid-prodikeys.o | 62 | obj-$(CONFIG_HID_PRODIKEYS) += hid-prodikeys.o |
| 54 | obj-$(CONFIG_HID_QUANTA) += hid-quanta.o | ||
| 55 | obj-$(CONFIG_HID_PANTHERLORD) += hid-pl.o | 63 | obj-$(CONFIG_HID_PANTHERLORD) += hid-pl.o |
| 56 | obj-$(CONFIG_HID_PETALYNX) += hid-petalynx.o | 64 | obj-$(CONFIG_HID_PETALYNX) += hid-petalynx.o |
| 57 | obj-$(CONFIG_HID_PICOLCD) += hid-picolcd.o | 65 | obj-$(CONFIG_HID_PICOLCD) += hid-picolcd.o |
| @@ -59,6 +67,7 @@ obj-$(CONFIG_HID_PRIMAX) += hid-primax.o | |||
| 59 | obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o | 67 | obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o |
| 60 | obj-$(CONFIG_HID_ROCCAT_COMMON) += hid-roccat-common.o | 68 | obj-$(CONFIG_HID_ROCCAT_COMMON) += hid-roccat-common.o |
| 61 | obj-$(CONFIG_HID_ROCCAT_ARVO) += hid-roccat-arvo.o | 69 | obj-$(CONFIG_HID_ROCCAT_ARVO) += hid-roccat-arvo.o |
| 70 | obj-$(CONFIG_HID_ROCCAT_ISKU) += hid-roccat-isku.o | ||
| 62 | obj-$(CONFIG_HID_ROCCAT_KONE) += hid-roccat-kone.o | 71 | obj-$(CONFIG_HID_ROCCAT_KONE) += hid-roccat-kone.o |
| 63 | obj-$(CONFIG_HID_ROCCAT_KONEPLUS) += hid-roccat-koneplus.o | 72 | obj-$(CONFIG_HID_ROCCAT_KONEPLUS) += hid-roccat-koneplus.o |
| 64 | obj-$(CONFIG_HID_ROCCAT_KOVAPLUS) += hid-roccat-kovaplus.o | 73 | obj-$(CONFIG_HID_ROCCAT_KOVAPLUS) += hid-roccat-kovaplus.o |
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index af353842f75f..af08ce7207d9 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
| @@ -90,7 +90,7 @@ static struct hid_field *hid_register_field(struct hid_report *report, unsigned | |||
| 90 | struct hid_field *field; | 90 | struct hid_field *field; |
| 91 | 91 | ||
| 92 | if (report->maxfield == HID_MAX_FIELDS) { | 92 | if (report->maxfield == HID_MAX_FIELDS) { |
| 93 | dbg_hid("too many fields in report\n"); | 93 | hid_err(report->device, "too many fields in report\n"); |
| 94 | return NULL; | 94 | return NULL; |
| 95 | } | 95 | } |
| 96 | 96 | ||
| @@ -121,7 +121,7 @@ static int open_collection(struct hid_parser *parser, unsigned type) | |||
| 121 | usage = parser->local.usage[0]; | 121 | usage = parser->local.usage[0]; |
| 122 | 122 | ||
| 123 | if (parser->collection_stack_ptr == HID_COLLECTION_STACK_SIZE) { | 123 | if (parser->collection_stack_ptr == HID_COLLECTION_STACK_SIZE) { |
| 124 | dbg_hid("collection stack overflow\n"); | 124 | hid_err(parser->device, "collection stack overflow\n"); |
| 125 | return -1; | 125 | return -1; |
| 126 | } | 126 | } |
| 127 | 127 | ||
| @@ -129,7 +129,7 @@ static int open_collection(struct hid_parser *parser, unsigned type) | |||
| 129 | collection = kmalloc(sizeof(struct hid_collection) * | 129 | collection = kmalloc(sizeof(struct hid_collection) * |
| 130 | parser->device->collection_size * 2, GFP_KERNEL); | 130 | parser->device->collection_size * 2, GFP_KERNEL); |
| 131 | if (collection == NULL) { | 131 | if (collection == NULL) { |
| 132 | dbg_hid("failed to reallocate collection array\n"); | 132 | hid_err(parser->device, "failed to reallocate collection array\n"); |
| 133 | return -1; | 133 | return -1; |
| 134 | } | 134 | } |
| 135 | memcpy(collection, parser->device->collection, | 135 | memcpy(collection, parser->device->collection, |
| @@ -165,7 +165,7 @@ static int open_collection(struct hid_parser *parser, unsigned type) | |||
| 165 | static int close_collection(struct hid_parser *parser) | 165 | static int close_collection(struct hid_parser *parser) |
| 166 | { | 166 | { |
| 167 | if (!parser->collection_stack_ptr) { | 167 | if (!parser->collection_stack_ptr) { |
| 168 | dbg_hid("collection stack underflow\n"); | 168 | hid_err(parser->device, "collection stack underflow\n"); |
| 169 | return -1; | 169 | return -1; |
| 170 | } | 170 | } |
| 171 | parser->collection_stack_ptr--; | 171 | parser->collection_stack_ptr--; |
| @@ -197,7 +197,7 @@ static unsigned hid_lookup_collection(struct hid_parser *parser, unsigned type) | |||
| 197 | static int hid_add_usage(struct hid_parser *parser, unsigned usage) | 197 | static int hid_add_usage(struct hid_parser *parser, unsigned usage) |
| 198 | { | 198 | { |
| 199 | if (parser->local.usage_index >= HID_MAX_USAGES) { | 199 | if (parser->local.usage_index >= HID_MAX_USAGES) { |
| 200 | dbg_hid("usage index exceeded\n"); | 200 | hid_err(parser->device, "usage index exceeded\n"); |
| 201 | return -1; | 201 | return -1; |
| 202 | } | 202 | } |
| 203 | parser->local.usage[parser->local.usage_index] = usage; | 203 | parser->local.usage[parser->local.usage_index] = usage; |
| @@ -222,12 +222,13 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign | |||
| 222 | 222 | ||
| 223 | report = hid_register_report(parser->device, report_type, parser->global.report_id); | 223 | report = hid_register_report(parser->device, report_type, parser->global.report_id); |
| 224 | if (!report) { | 224 | if (!report) { |
| 225 | dbg_hid("hid_register_report failed\n"); | 225 | hid_err(parser->device, "hid_register_report failed\n"); |
| 226 | return -1; | 226 | return -1; |
| 227 | } | 227 | } |
| 228 | 228 | ||
| 229 | if (parser->global.logical_maximum < parser->global.logical_minimum) { | 229 | if (parser->global.logical_maximum < parser->global.logical_minimum) { |
| 230 | dbg_hid("logical range invalid %d %d\n", parser->global.logical_minimum, parser->global.logical_maximum); | 230 | hid_err(parser->device, "logical range invalid %d %d\n", |
| 231 | parser->global.logical_minimum, parser->global.logical_maximum); | ||
| 231 | return -1; | 232 | return -1; |
| 232 | } | 233 | } |
| 233 | 234 | ||
| @@ -307,7 +308,7 @@ static int hid_parser_global(struct hid_parser *parser, struct hid_item *item) | |||
| 307 | case HID_GLOBAL_ITEM_TAG_PUSH: | 308 | case HID_GLOBAL_ITEM_TAG_PUSH: |
| 308 | 309 | ||
| 309 | if (parser->global_stack_ptr == HID_GLOBAL_STACK_SIZE) { | 310 | if (parser->global_stack_ptr == HID_GLOBAL_STACK_SIZE) { |
| 310 | dbg_hid("global environment stack overflow\n"); | 311 | hid_err(parser->device, "global environment stack overflow\n"); |
| 311 | return -1; | 312 | return -1; |
| 312 | } | 313 | } |
| 313 | 314 | ||
| @@ -318,7 +319,7 @@ static int hid_parser_global(struct hid_parser *parser, struct hid_item *item) | |||
| 318 | case HID_GLOBAL_ITEM_TAG_POP: | 319 | case HID_GLOBAL_ITEM_TAG_POP: |
| 319 | 320 | ||
| 320 | if (!parser->global_stack_ptr) { | 321 | if (!parser->global_stack_ptr) { |
| 321 | dbg_hid("global environment stack underflow\n"); | 322 | hid_err(parser->device, "global environment stack underflow\n"); |
| 322 | return -1; | 323 | return -1; |
| 323 | } | 324 | } |
| 324 | 325 | ||
| @@ -362,8 +363,8 @@ static int hid_parser_global(struct hid_parser *parser, struct hid_item *item) | |||
| 362 | 363 | ||
| 363 | case HID_GLOBAL_ITEM_TAG_REPORT_SIZE: | 364 | case HID_GLOBAL_ITEM_TAG_REPORT_SIZE: |
| 364 | parser->global.report_size = item_udata(item); | 365 | parser->global.report_size = item_udata(item); |
| 365 | if (parser->global.report_size > 32) { | 366 | if (parser->global.report_size > 96) { |
| 366 | dbg_hid("invalid report_size %d\n", | 367 | hid_err(parser->device, "invalid report_size %d\n", |
| 367 | parser->global.report_size); | 368 | parser->global.report_size); |
| 368 | return -1; | 369 | return -1; |
| 369 | } | 370 | } |
| @@ -372,7 +373,7 @@ static int hid_parser_global(struct hid_parser *parser, struct hid_item *item) | |||
| 372 | case HID_GLOBAL_ITEM_TAG_REPORT_COUNT: | 373 | case HID_GLOBAL_ITEM_TAG_REPORT_COUNT: |
| 373 | parser->global.report_count = item_udata(item); | 374 | parser->global.report_count = item_udata(item); |
| 374 | if (parser->global.report_count > HID_MAX_USAGES) { | 375 | if (parser->global.report_count > HID_MAX_USAGES) { |
| 375 | dbg_hid("invalid report_count %d\n", | 376 | hid_err(parser->device, "invalid report_count %d\n", |
| 376 | parser->global.report_count); | 377 | parser->global.report_count); |
| 377 | return -1; | 378 | return -1; |
| 378 | } | 379 | } |
| @@ -381,13 +382,13 @@ static int hid_parser_global(struct hid_parser *parser, struct hid_item *item) | |||
| 381 | case HID_GLOBAL_ITEM_TAG_REPORT_ID: | 382 | case HID_GLOBAL_ITEM_TAG_REPORT_ID: |
| 382 | parser->global.report_id = item_udata(item); | 383 | parser->global.report_id = item_udata(item); |
| 383 | if (parser->global.report_id == 0) { | 384 | if (parser->global.report_id == 0) { |
| 384 | dbg_hid("report_id 0 is invalid\n"); | 385 | hid_err(parser->device, "report_id 0 is invalid\n"); |
| 385 | return -1; | 386 | return -1; |
| 386 | } | 387 | } |
| 387 | return 0; | 388 | return 0; |
| 388 | 389 | ||
| 389 | default: | 390 | default: |
| 390 | dbg_hid("unknown global tag 0x%x\n", item->tag); | 391 | hid_err(parser->device, "unknown global tag 0x%x\n", item->tag); |
| 391 | return -1; | 392 | return -1; |
| 392 | } | 393 | } |
| 393 | } | 394 | } |
| @@ -414,14 +415,14 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item) | |||
| 414 | * items and the first delimiter set. | 415 | * items and the first delimiter set. |
| 415 | */ | 416 | */ |
| 416 | if (parser->local.delimiter_depth != 0) { | 417 | if (parser->local.delimiter_depth != 0) { |
| 417 | dbg_hid("nested delimiters\n"); | 418 | hid_err(parser->device, "nested delimiters\n"); |
| 418 | return -1; | 419 | return -1; |
| 419 | } | 420 | } |
| 420 | parser->local.delimiter_depth++; | 421 | parser->local.delimiter_depth++; |
| 421 | parser->local.delimiter_branch++; | 422 | parser->local.delimiter_branch++; |
| 422 | } else { | 423 | } else { |
| 423 | if (parser->local.delimiter_depth < 1) { | 424 | if (parser->local.delimiter_depth < 1) { |
| 424 | dbg_hid("bogus close delimiter\n"); | 425 | hid_err(parser->device, "bogus close delimiter\n"); |
| 425 | return -1; | 426 | return -1; |
| 426 | } | 427 | } |
| 427 | parser->local.delimiter_depth--; | 428 | parser->local.delimiter_depth--; |
| @@ -506,7 +507,7 @@ static int hid_parser_main(struct hid_parser *parser, struct hid_item *item) | |||
| 506 | ret = hid_add_field(parser, HID_FEATURE_REPORT, data); | 507 | ret = hid_add_field(parser, HID_FEATURE_REPORT, data); |
| 507 | break; | 508 | break; |
| 508 | default: | 509 | default: |
| 509 | dbg_hid("unknown main item tag 0x%x\n", item->tag); | 510 | hid_err(parser->device, "unknown main item tag 0x%x\n", item->tag); |
| 510 | ret = 0; | 511 | ret = 0; |
| 511 | } | 512 | } |
| 512 | 513 | ||
| @@ -678,12 +679,12 @@ int hid_parse_report(struct hid_device *device, __u8 *start, | |||
| 678 | while ((start = fetch_item(start, end, &item)) != NULL) { | 679 | while ((start = fetch_item(start, end, &item)) != NULL) { |
| 679 | 680 | ||
| 680 | if (item.format != HID_ITEM_FORMAT_SHORT) { | 681 | if (item.format != HID_ITEM_FORMAT_SHORT) { |
| 681 | dbg_hid("unexpected long global item\n"); | 682 | hid_err(device, "unexpected long global item\n"); |
| 682 | goto err; | 683 | goto err; |
| 683 | } | 684 | } |
| 684 | 685 | ||
| 685 | if (dispatch_type[item.type](parser, &item)) { | 686 | if (dispatch_type[item.type](parser, &item)) { |
| 686 | dbg_hid("item %u %u %u %u parsing failed\n", | 687 | hid_err(device, "item %u %u %u %u parsing failed\n", |
| 687 | item.format, (unsigned)item.size, | 688 | item.format, (unsigned)item.size, |
| 688 | (unsigned)item.type, (unsigned)item.tag); | 689 | (unsigned)item.type, (unsigned)item.tag); |
| 689 | goto err; | 690 | goto err; |
| @@ -691,11 +692,11 @@ int hid_parse_report(struct hid_device *device, __u8 *start, | |||
| 691 | 692 | ||
| 692 | if (start == end) { | 693 | if (start == end) { |
| 693 | if (parser->collection_stack_ptr) { | 694 | if (parser->collection_stack_ptr) { |
| 694 | dbg_hid("unbalanced collection at end of report description\n"); | 695 | hid_err(device, "unbalanced collection at end of report description\n"); |
| 695 | goto err; | 696 | goto err; |
| 696 | } | 697 | } |
| 697 | if (parser->local.delimiter_depth) { | 698 | if (parser->local.delimiter_depth) { |
| 698 | dbg_hid("unbalanced delimiter at end of report description\n"); | 699 | hid_err(device, "unbalanced delimiter at end of report description\n"); |
| 699 | goto err; | 700 | goto err; |
| 700 | } | 701 | } |
| 701 | vfree(parser); | 702 | vfree(parser); |
| @@ -703,7 +704,7 @@ int hid_parse_report(struct hid_device *device, __u8 *start, | |||
| 703 | } | 704 | } |
| 704 | } | 705 | } |
| 705 | 706 | ||
| 706 | dbg_hid("item fetching failed at offset %d\n", (int)(end - start)); | 707 | hid_err(device, "item fetching failed at offset %d\n", (int)(end - start)); |
| 707 | err: | 708 | err: |
| 708 | vfree(parser); | 709 | vfree(parser); |
| 709 | return ret; | 710 | return ret; |
| @@ -873,7 +874,7 @@ static void hid_process_event(struct hid_device *hid, struct hid_field *field, | |||
| 873 | ret = hdrv->event(hid, field, usage, value); | 874 | ret = hdrv->event(hid, field, usage, value); |
| 874 | if (ret != 0) { | 875 | if (ret != 0) { |
| 875 | if (ret < 0) | 876 | if (ret < 0) |
| 876 | dbg_hid("%s's event failed with %d\n", | 877 | hid_err(hid, "%s's event failed with %d\n", |
| 877 | hdrv->name, ret); | 878 | hdrv->name, ret); |
| 878 | return; | 879 | return; |
| 879 | } | 880 | } |
| @@ -995,12 +996,13 @@ int hid_set_field(struct hid_field *field, unsigned offset, __s32 value) | |||
| 995 | hid_dump_input(field->report->device, field->usage + offset, value); | 996 | hid_dump_input(field->report->device, field->usage + offset, value); |
| 996 | 997 | ||
| 997 | if (offset >= field->report_count) { | 998 | if (offset >= field->report_count) { |
| 998 | dbg_hid("offset (%d) exceeds report_count (%d)\n", offset, field->report_count); | 999 | hid_err(field->report->device, "offset (%d) exceeds report_count (%d)\n", |
| 1000 | offset, field->report_count); | ||
| 999 | return -1; | 1001 | return -1; |
| 1000 | } | 1002 | } |
| 1001 | if (field->logical_minimum < 0) { | 1003 | if (field->logical_minimum < 0) { |
| 1002 | if (value != snto32(s32ton(value, size), size)) { | 1004 | if (value != snto32(s32ton(value, size), size)) { |
| 1003 | dbg_hid("value %d is out of range\n", value); | 1005 | hid_err(field->report->device, "value %d is out of range\n", value); |
| 1004 | return -1; | 1006 | return -1; |
| 1005 | } | 1007 | } |
| 1006 | } | 1008 | } |
| @@ -1157,7 +1159,7 @@ static bool hid_match_one_id(struct hid_device *hdev, | |||
| 1157 | (id->product == HID_ANY_ID || id->product == hdev->product); | 1159 | (id->product == HID_ANY_ID || id->product == hdev->product); |
| 1158 | } | 1160 | } |
| 1159 | 1161 | ||
| 1160 | static const struct hid_device_id *hid_match_id(struct hid_device *hdev, | 1162 | const struct hid_device_id *hid_match_id(struct hid_device *hdev, |
| 1161 | const struct hid_device_id *id) | 1163 | const struct hid_device_id *id) |
| 1162 | { | 1164 | { |
| 1163 | for (; id->bus; id++) | 1165 | for (; id->bus; id++) |
| @@ -1404,11 +1406,13 @@ static const struct hid_device_id hid_have_special_driver[] = { | |||
| 1404 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_TRUETOUCH) }, | 1406 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_TRUETOUCH) }, |
| 1405 | { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) }, | 1407 | { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) }, |
| 1406 | { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0011) }, | 1408 | { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0011) }, |
| 1407 | { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH) }, | 1409 | { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480D) }, |
| 1408 | { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1) }, | 1410 | { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480E) }, |
| 1409 | { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH2) }, | 1411 | { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_720C) }, |
| 1410 | { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH3) }, | 1412 | { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_726B) }, |
| 1411 | { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH4) }, | 1413 | { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72A1) }, |
| 1414 | { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7302) }, | ||
| 1415 | { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001) }, | ||
| 1412 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) }, | 1416 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) }, |
| 1413 | { HID_USB_DEVICE(USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2515) }, | 1417 | { HID_USB_DEVICE(USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2515) }, |
| 1414 | { HID_USB_DEVICE(USB_VENDOR_ID_EMS, USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II) }, | 1418 | { HID_USB_DEVICE(USB_VENDOR_ID_EMS, USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II) }, |
| @@ -1423,6 +1427,7 @@ static const struct hid_device_id hid_have_special_driver[] = { | |||
| 1423 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) }, | 1427 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) }, |
| 1424 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) }, | 1428 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) }, |
| 1425 | { HID_USB_DEVICE(USB_VENDOR_ID_HANVON, USB_DEVICE_ID_HANVON_MULTITOUCH) }, | 1429 | { HID_USB_DEVICE(USB_VENDOR_ID_HANVON, USB_DEVICE_ID_HANVON_MULTITOUCH) }, |
| 1430 | { HID_USB_DEVICE(USB_VENDOR_ID_HANVON_ALT, USB_DEVICE_ID_HANVON_ALT_MULTITOUCH) }, | ||
| 1426 | { HID_USB_DEVICE(USB_VENDOR_ID_IDEACOM, USB_DEVICE_ID_IDEACOM_IDC6650) }, | 1431 | { HID_USB_DEVICE(USB_VENDOR_ID_IDEACOM, USB_DEVICE_ID_IDEACOM_IDC6650) }, |
| 1427 | { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK, USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP) }, | 1432 | { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK, USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP) }, |
| 1428 | { HID_USB_DEVICE(USB_VENDOR_ID_ILITEK, USB_DEVICE_ID_ILITEK_MULTITOUCH) }, | 1433 | { HID_USB_DEVICE(USB_VENDOR_ID_ILITEK, USB_DEVICE_ID_ILITEK_MULTITOUCH) }, |
| @@ -1498,11 +1503,15 @@ static const struct hid_device_id hid_have_special_driver[] = { | |||
| 1498 | { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) }, | 1503 | { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) }, |
| 1499 | { HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_PCI) }, | 1504 | { HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_PCI) }, |
| 1500 | { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) }, | 1505 | { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) }, |
| 1506 | { HID_USB_DEVICE(USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN) }, | ||
| 1507 | { HID_USB_DEVICE(USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1) }, | ||
| 1508 | { HID_USB_DEVICE(USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2) }, | ||
| 1501 | { HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_KEYBOARD) }, | 1509 | { HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_KEYBOARD) }, |
| 1502 | { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) }, | 1510 | { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) }, |
| 1503 | { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN) }, | 1511 | { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN) }, |
| 1504 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONE) }, | 1512 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONE) }, |
| 1505 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ARVO) }, | 1513 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ARVO) }, |
| 1514 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKU) }, | ||
| 1506 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) }, | 1515 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) }, |
| 1507 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KOVAPLUS) }, | 1516 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KOVAPLUS) }, |
| 1508 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRED) }, | 1517 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRED) }, |
| @@ -1544,11 +1553,21 @@ static const struct hid_device_id hid_have_special_driver[] = { | |||
| 1544 | { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_DUAL_BOX_PRO) }, | 1553 | { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_DUAL_BOX_PRO) }, |
| 1545 | { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_5_PRO) }, | 1554 | { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_5_PRO) }, |
| 1546 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) }, | 1555 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) }, |
| 1556 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH) }, | ||
| 1547 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH) }, | 1557 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH) }, |
| 1548 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_12_1_INCH) }, | 1558 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_12_1_INCH) }, |
| 1549 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH) }, | 1559 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH) }, |
| 1550 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH) }, | 1560 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH) }, |
| 1551 | { HID_USB_DEVICE(USB_VENDOR_ID_XAT, USB_DEVICE_ID_XAT_CSR) }, | 1561 | { HID_USB_DEVICE(USB_VENDOR_ID_XAT, USB_DEVICE_ID_XAT_CSR) }, |
| 1562 | { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_SPX) }, | ||
| 1563 | { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_MPX) }, | ||
| 1564 | { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_CSR) }, | ||
| 1565 | { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_SPX1) }, | ||
| 1566 | { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_MPX1) }, | ||
| 1567 | { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_CSR1) }, | ||
| 1568 | { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_SPX2) }, | ||
| 1569 | { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_MPX2) }, | ||
| 1570 | { HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, USB_DEVICE_ID_XIROKU_CSR2) }, | ||
| 1552 | { HID_USB_DEVICE(USB_VENDOR_ID_X_TENSIONS, USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE) }, | 1571 | { HID_USB_DEVICE(USB_VENDOR_ID_X_TENSIONS, USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE) }, |
| 1553 | { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) }, | 1572 | { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) }, |
| 1554 | { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) }, | 1573 | { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) }, |
| @@ -1768,6 +1787,7 @@ static const struct hid_device_id hid_ignore_list[] = { | |||
| 1768 | { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE) }, | 1787 | { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE) }, |
| 1769 | { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20) }, | 1788 | { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20) }, |
| 1770 | { HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, 0x0004) }, | 1789 | { HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, 0x0004) }, |
| 1790 | { HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, 0x000a) }, | ||
| 1771 | { HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) }, | 1791 | { HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) }, |
| 1772 | { HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC5UH) }, | 1792 | { HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC5UH) }, |
| 1773 | { HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC4UM) }, | 1793 | { HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC4UM) }, |
diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c index ee80d733801d..01dd9a7daf7a 100644 --- a/drivers/hid/hid-debug.c +++ b/drivers/hid/hid-debug.c | |||
| @@ -114,6 +114,14 @@ static const struct hid_usage_entry hid_usage_table[] = { | |||
| 114 | {0, 0xbd, "FlareRelease"}, | 114 | {0, 0xbd, "FlareRelease"}, |
| 115 | {0, 0xbe, "LandingGear"}, | 115 | {0, 0xbe, "LandingGear"}, |
| 116 | {0, 0xbf, "ToeBrake"}, | 116 | {0, 0xbf, "ToeBrake"}, |
| 117 | { 6, 0, "GenericDeviceControls" }, | ||
| 118 | {0, 0x20, "BatteryStrength" }, | ||
| 119 | {0, 0x21, "WirelessChannel" }, | ||
| 120 | {0, 0x22, "WirelessID" }, | ||
| 121 | {0, 0x23, "DiscoverWirelessControl" }, | ||
| 122 | {0, 0x24, "SecurityCodeCharacterEntered" }, | ||
| 123 | {0, 0x25, "SecurityCodeCharactedErased" }, | ||
| 124 | {0, 0x26, "SecurityCodeCleared" }, | ||
| 117 | { 7, 0, "Keyboard" }, | 125 | { 7, 0, "Keyboard" }, |
| 118 | { 8, 0, "LED" }, | 126 | { 8, 0, "LED" }, |
| 119 | {0, 0x01, "NumLock"}, | 127 | {0, 0x01, "NumLock"}, |
diff --git a/drivers/hid/hid-emsff.c b/drivers/hid/hid-emsff.c index 9bdde867a02f..2630d483d262 100644 --- a/drivers/hid/hid-emsff.c +++ b/drivers/hid/hid-emsff.c | |||
| @@ -140,7 +140,7 @@ err: | |||
| 140 | } | 140 | } |
| 141 | 141 | ||
| 142 | static const struct hid_device_id ems_devices[] = { | 142 | static const struct hid_device_id ems_devices[] = { |
| 143 | { HID_USB_DEVICE(USB_VENDOR_ID_EMS, 0x118) }, | 143 | { HID_USB_DEVICE(USB_VENDOR_ID_EMS, USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II) }, |
| 144 | { } | 144 | { } |
| 145 | }; | 145 | }; |
| 146 | MODULE_DEVICE_TABLE(hid, ems_devices); | 146 | MODULE_DEVICE_TABLE(hid, ems_devices); |
diff --git a/drivers/hid/hid-hyperv.c b/drivers/hid/hid-hyperv.c new file mode 100644 index 000000000000..0c33ae9cf0f0 --- /dev/null +++ b/drivers/hid/hid-hyperv.c | |||
| @@ -0,0 +1,586 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2009, Citrix Systems, Inc. | ||
| 3 | * Copyright (c) 2010, Microsoft Corporation. | ||
| 4 | * Copyright (c) 2011, Novell Inc. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify it | ||
| 7 | * under the terms and conditions of the GNU General Public License, | ||
| 8 | * version 2, as published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
| 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 13 | * more details. | ||
| 14 | */ | ||
| 15 | #include <linux/init.h> | ||
| 16 | #include <linux/module.h> | ||
| 17 | #include <linux/device.h> | ||
| 18 | #include <linux/completion.h> | ||
| 19 | #include <linux/input.h> | ||
| 20 | #include <linux/hid.h> | ||
| 21 | #include <linux/hiddev.h> | ||
| 22 | #include <linux/hyperv.h> | ||
| 23 | |||
| 24 | |||
| 25 | struct hv_input_dev_info { | ||
| 26 | unsigned int size; | ||
| 27 | unsigned short vendor; | ||
| 28 | unsigned short product; | ||
| 29 | unsigned short version; | ||
| 30 | unsigned short reserved[11]; | ||
| 31 | }; | ||
| 32 | |||
| 33 | /* The maximum size of a synthetic input message. */ | ||
| 34 | #define SYNTHHID_MAX_INPUT_REPORT_SIZE 16 | ||
| 35 | |||
| 36 | /* | ||
| 37 | * Current version | ||
| 38 | * | ||
| 39 | * History: | ||
| 40 | * Beta, RC < 2008/1/22 1,0 | ||
| 41 | * RC > 2008/1/22 2,0 | ||
| 42 | */ | ||
| 43 | #define SYNTHHID_INPUT_VERSION_MAJOR 2 | ||
| 44 | #define SYNTHHID_INPUT_VERSION_MINOR 0 | ||
| 45 | #define SYNTHHID_INPUT_VERSION (SYNTHHID_INPUT_VERSION_MINOR | \ | ||
| 46 | (SYNTHHID_INPUT_VERSION_MAJOR << 16)) | ||
| 47 | |||
| 48 | |||
| 49 | #pragma pack(push, 1) | ||
| 50 | /* | ||
| 51 | * Message types in the synthetic input protocol | ||
| 52 | */ | ||
| 53 | enum synthhid_msg_type { | ||
| 54 | SYNTH_HID_PROTOCOL_REQUEST, | ||
| 55 | SYNTH_HID_PROTOCOL_RESPONSE, | ||
| 56 | SYNTH_HID_INITIAL_DEVICE_INFO, | ||
| 57 | SYNTH_HID_INITIAL_DEVICE_INFO_ACK, | ||
| 58 | SYNTH_HID_INPUT_REPORT, | ||
| 59 | SYNTH_HID_MAX | ||
| 60 | }; | ||
| 61 | |||
| 62 | /* | ||
| 63 | * Basic message structures. | ||
| 64 | */ | ||
| 65 | struct synthhid_msg_hdr { | ||
| 66 | enum synthhid_msg_type type; | ||
| 67 | u32 size; | ||
| 68 | }; | ||
| 69 | |||
| 70 | struct synthhid_msg { | ||
| 71 | struct synthhid_msg_hdr header; | ||
| 72 | char data[1]; /* Enclosed message */ | ||
| 73 | }; | ||
| 74 | |||
| 75 | union synthhid_version { | ||
| 76 | struct { | ||
| 77 | u16 minor_version; | ||
| 78 | u16 major_version; | ||
| 79 | }; | ||
| 80 | u32 version; | ||
| 81 | }; | ||
| 82 | |||
| 83 | /* | ||
| 84 | * Protocol messages | ||
| 85 | */ | ||
| 86 | struct synthhid_protocol_request { | ||
| 87 | struct synthhid_msg_hdr header; | ||
| 88 | union synthhid_version version_requested; | ||
| 89 | }; | ||
| 90 | |||
| 91 | struct synthhid_protocol_response { | ||
| 92 | struct synthhid_msg_hdr header; | ||
| 93 | union synthhid_version version_requested; | ||
| 94 | unsigned char approved; | ||
| 95 | }; | ||
| 96 | |||
| 97 | struct synthhid_device_info { | ||
| 98 | struct synthhid_msg_hdr header; | ||
| 99 | struct hv_input_dev_info hid_dev_info; | ||
| 100 | struct hid_descriptor hid_descriptor; | ||
| 101 | }; | ||
| 102 | |||
| 103 | struct synthhid_device_info_ack { | ||
| 104 | struct synthhid_msg_hdr header; | ||
| 105 | unsigned char reserved; | ||
| 106 | }; | ||
| 107 | |||
| 108 | struct synthhid_input_report { | ||
| 109 | struct synthhid_msg_hdr header; | ||
| 110 | char buffer[1]; | ||
| 111 | }; | ||
| 112 | |||
| 113 | #pragma pack(pop) | ||
| 114 | |||
| 115 | #define INPUTVSC_SEND_RING_BUFFER_SIZE (10*PAGE_SIZE) | ||
| 116 | #define INPUTVSC_RECV_RING_BUFFER_SIZE (10*PAGE_SIZE) | ||
| 117 | |||
| 118 | |||
| 119 | enum pipe_prot_msg_type { | ||
| 120 | PIPE_MESSAGE_INVALID, | ||
| 121 | PIPE_MESSAGE_DATA, | ||
| 122 | PIPE_MESSAGE_MAXIMUM | ||
| 123 | }; | ||
| 124 | |||
| 125 | |||
| 126 | struct pipe_prt_msg { | ||
| 127 | enum pipe_prot_msg_type type; | ||
| 128 | u32 size; | ||
| 129 | char data[1]; | ||
| 130 | }; | ||
| 131 | |||
| 132 | struct mousevsc_prt_msg { | ||
| 133 | enum pipe_prot_msg_type type; | ||
| 134 | u32 size; | ||
| 135 | union { | ||
| 136 | struct synthhid_protocol_request request; | ||
| 137 | struct synthhid_protocol_response response; | ||
| 138 | struct synthhid_device_info_ack ack; | ||
| 139 | }; | ||
| 140 | }; | ||
| 141 | |||
| 142 | /* | ||
| 143 | * Represents an mousevsc device | ||
| 144 | */ | ||
| 145 | struct mousevsc_dev { | ||
| 146 | struct hv_device *device; | ||
| 147 | bool init_complete; | ||
| 148 | bool connected; | ||
| 149 | struct mousevsc_prt_msg protocol_req; | ||
| 150 | struct mousevsc_prt_msg protocol_resp; | ||
| 151 | /* Synchronize the request/response if needed */ | ||
| 152 | struct completion wait_event; | ||
| 153 | int dev_info_status; | ||
| 154 | |||
| 155 | struct hid_descriptor *hid_desc; | ||
| 156 | unsigned char *report_desc; | ||
| 157 | u32 report_desc_size; | ||
| 158 | struct hv_input_dev_info hid_dev_info; | ||
| 159 | struct hid_device *hid_device; | ||
| 160 | }; | ||
| 161 | |||
| 162 | |||
| 163 | static struct mousevsc_dev *mousevsc_alloc_device(struct hv_device *device) | ||
| 164 | { | ||
| 165 | struct mousevsc_dev *input_dev; | ||
| 166 | |||
| 167 | input_dev = kzalloc(sizeof(struct mousevsc_dev), GFP_KERNEL); | ||
| 168 | |||
| 169 | if (!input_dev) | ||
| 170 | return NULL; | ||
| 171 | |||
| 172 | input_dev->device = device; | ||
| 173 | hv_set_drvdata(device, input_dev); | ||
| 174 | init_completion(&input_dev->wait_event); | ||
| 175 | input_dev->init_complete = false; | ||
| 176 | |||
| 177 | return input_dev; | ||
| 178 | } | ||
| 179 | |||
| 180 | static void mousevsc_free_device(struct mousevsc_dev *device) | ||
| 181 | { | ||
| 182 | kfree(device->hid_desc); | ||
| 183 | kfree(device->report_desc); | ||
| 184 | hv_set_drvdata(device->device, NULL); | ||
| 185 | kfree(device); | ||
| 186 | } | ||
| 187 | |||
| 188 | static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device, | ||
| 189 | struct synthhid_device_info *device_info) | ||
| 190 | { | ||
| 191 | int ret = 0; | ||
| 192 | struct hid_descriptor *desc; | ||
| 193 | struct mousevsc_prt_msg ack; | ||
| 194 | |||
| 195 | input_device->dev_info_status = -ENOMEM; | ||
| 196 | |||
| 197 | input_device->hid_dev_info = device_info->hid_dev_info; | ||
| 198 | desc = &device_info->hid_descriptor; | ||
| 199 | if (desc->bLength == 0) | ||
| 200 | goto cleanup; | ||
| 201 | |||
| 202 | input_device->hid_desc = kzalloc(desc->bLength, GFP_ATOMIC); | ||
| 203 | |||
| 204 | if (!input_device->hid_desc) | ||
| 205 | goto cleanup; | ||
| 206 | |||
| 207 | memcpy(input_device->hid_desc, desc, desc->bLength); | ||
| 208 | |||
| 209 | input_device->report_desc_size = desc->desc[0].wDescriptorLength; | ||
| 210 | if (input_device->report_desc_size == 0) { | ||
| 211 | input_device->dev_info_status = -EINVAL; | ||
| 212 | goto cleanup; | ||
| 213 | } | ||
| 214 | |||
| 215 | input_device->report_desc = kzalloc(input_device->report_desc_size, | ||
| 216 | GFP_ATOMIC); | ||
| 217 | |||
| 218 | if (!input_device->report_desc) { | ||
| 219 | input_device->dev_info_status = -ENOMEM; | ||
| 220 | goto cleanup; | ||
| 221 | } | ||
| 222 | |||
| 223 | memcpy(input_device->report_desc, | ||
| 224 | ((unsigned char *)desc) + desc->bLength, | ||
| 225 | desc->desc[0].wDescriptorLength); | ||
| 226 | |||
| 227 | /* Send the ack */ | ||
| 228 | memset(&ack, 0, sizeof(struct mousevsc_prt_msg)); | ||
| 229 | |||
| 230 | ack.type = PIPE_MESSAGE_DATA; | ||
| 231 | ack.size = sizeof(struct synthhid_device_info_ack); | ||
| 232 | |||
| 233 | ack.ack.header.type = SYNTH_HID_INITIAL_DEVICE_INFO_ACK; | ||
| 234 | ack.ack.header.size = 1; | ||
| 235 | ack.ack.reserved = 0; | ||
| 236 | |||
| 237 | ret = vmbus_sendpacket(input_device->device->channel, | ||
| 238 | &ack, | ||
| 239 | sizeof(struct pipe_prt_msg) - sizeof(unsigned char) + | ||
| 240 | sizeof(struct synthhid_device_info_ack), | ||
| 241 | (unsigned long)&ack, | ||
| 242 | VM_PKT_DATA_INBAND, | ||
| 243 | VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); | ||
| 244 | |||
| 245 | if (!ret) | ||
| 246 | input_device->dev_info_status = 0; | ||
| 247 | |||
| 248 | cleanup: | ||
| 249 | complete(&input_device->wait_event); | ||
| 250 | |||
| 251 | return; | ||
| 252 | } | ||
| 253 | |||
| 254 | static void mousevsc_on_receive(struct hv_device *device, | ||
| 255 | struct vmpacket_descriptor *packet) | ||
| 256 | { | ||
| 257 | struct pipe_prt_msg *pipe_msg; | ||
| 258 | struct synthhid_msg *hid_msg; | ||
| 259 | struct mousevsc_dev *input_dev = hv_get_drvdata(device); | ||
| 260 | struct synthhid_input_report *input_report; | ||
| 261 | |||
| 262 | pipe_msg = (struct pipe_prt_msg *)((unsigned long)packet + | ||
| 263 | (packet->offset8 << 3)); | ||
| 264 | |||
| 265 | if (pipe_msg->type != PIPE_MESSAGE_DATA) | ||
| 266 | return; | ||
| 267 | |||
| 268 | hid_msg = (struct synthhid_msg *)pipe_msg->data; | ||
| 269 | |||
| 270 | switch (hid_msg->header.type) { | ||
| 271 | case SYNTH_HID_PROTOCOL_RESPONSE: | ||
| 272 | /* | ||
| 273 | * While it will be impossible for us to protect against | ||
| 274 | * malicious/buggy hypervisor/host, add a check here to | ||
| 275 | * ensure we don't corrupt memory. | ||
| 276 | */ | ||
| 277 | if ((pipe_msg->size + sizeof(struct pipe_prt_msg) | ||
| 278 | - sizeof(unsigned char)) | ||
| 279 | > sizeof(struct mousevsc_prt_msg)) { | ||
| 280 | WARN_ON(1); | ||
| 281 | break; | ||
| 282 | } | ||
| 283 | |||
| 284 | memcpy(&input_dev->protocol_resp, pipe_msg, | ||
| 285 | pipe_msg->size + sizeof(struct pipe_prt_msg) - | ||
| 286 | sizeof(unsigned char)); | ||
| 287 | complete(&input_dev->wait_event); | ||
| 288 | break; | ||
| 289 | |||
| 290 | case SYNTH_HID_INITIAL_DEVICE_INFO: | ||
| 291 | WARN_ON(pipe_msg->size < sizeof(struct hv_input_dev_info)); | ||
| 292 | |||
| 293 | /* | ||
| 294 | * Parse out the device info into device attr, | ||
| 295 | * hid desc and report desc | ||
| 296 | */ | ||
| 297 | mousevsc_on_receive_device_info(input_dev, | ||
| 298 | (struct synthhid_device_info *)pipe_msg->data); | ||
| 299 | break; | ||
| 300 | case SYNTH_HID_INPUT_REPORT: | ||
| 301 | input_report = | ||
| 302 | (struct synthhid_input_report *)pipe_msg->data; | ||
| 303 | if (!input_dev->init_complete) | ||
| 304 | break; | ||
| 305 | hid_input_report(input_dev->hid_device, | ||
| 306 | HID_INPUT_REPORT, input_report->buffer, | ||
| 307 | input_report->header.size, 1); | ||
| 308 | break; | ||
| 309 | default: | ||
| 310 | pr_err("unsupported hid msg type - type %d len %d", | ||
| 311 | hid_msg->header.type, hid_msg->header.size); | ||
| 312 | break; | ||
| 313 | } | ||
| 314 | |||
| 315 | } | ||
| 316 | |||
| 317 | static void mousevsc_on_channel_callback(void *context) | ||
| 318 | { | ||
| 319 | const int packet_size = 0x100; | ||
| 320 | int ret; | ||
| 321 | struct hv_device *device = context; | ||
| 322 | u32 bytes_recvd; | ||
| 323 | u64 req_id; | ||
| 324 | struct vmpacket_descriptor *desc; | ||
| 325 | unsigned char *buffer; | ||
| 326 | int bufferlen = packet_size; | ||
| 327 | |||
| 328 | buffer = kmalloc(bufferlen, GFP_ATOMIC); | ||
| 329 | if (!buffer) | ||
| 330 | return; | ||
| 331 | |||
| 332 | do { | ||
| 333 | ret = vmbus_recvpacket_raw(device->channel, buffer, | ||
| 334 | bufferlen, &bytes_recvd, &req_id); | ||
| 335 | |||
| 336 | switch (ret) { | ||
| 337 | case 0: | ||
| 338 | if (bytes_recvd <= 0) { | ||
| 339 | kfree(buffer); | ||
| 340 | return; | ||
| 341 | } | ||
| 342 | desc = (struct vmpacket_descriptor *)buffer; | ||
| 343 | |||
| 344 | switch (desc->type) { | ||
| 345 | case VM_PKT_COMP: | ||
| 346 | break; | ||
| 347 | |||
| 348 | case VM_PKT_DATA_INBAND: | ||
| 349 | mousevsc_on_receive(device, desc); | ||
| 350 | break; | ||
| 351 | |||
| 352 | default: | ||
| 353 | pr_err("unhandled packet type %d, tid %llx len %d\n", | ||
| 354 | desc->type, req_id, bytes_recvd); | ||
| 355 | break; | ||
| 356 | } | ||
| 357 | |||
| 358 | break; | ||
| 359 | |||
| 360 | case -ENOBUFS: | ||
| 361 | kfree(buffer); | ||
| 362 | /* Handle large packet */ | ||
| 363 | bufferlen = bytes_recvd; | ||
| 364 | buffer = kmalloc(bytes_recvd, GFP_ATOMIC); | ||
| 365 | |||
| 366 | if (!buffer) | ||
| 367 | return; | ||
| 368 | |||
| 369 | break; | ||
| 370 | } | ||
| 371 | } while (1); | ||
| 372 | |||
| 373 | } | ||
| 374 | |||
| 375 | static int mousevsc_connect_to_vsp(struct hv_device *device) | ||
| 376 | { | ||
| 377 | int ret = 0; | ||
| 378 | int t; | ||
| 379 | struct mousevsc_dev *input_dev = hv_get_drvdata(device); | ||
| 380 | struct mousevsc_prt_msg *request; | ||
| 381 | struct mousevsc_prt_msg *response; | ||
| 382 | |||
| 383 | request = &input_dev->protocol_req; | ||
| 384 | memset(request, 0, sizeof(struct mousevsc_prt_msg)); | ||
| 385 | |||
| 386 | request->type = PIPE_MESSAGE_DATA; | ||
| 387 | request->size = sizeof(struct synthhid_protocol_request); | ||
| 388 | request->request.header.type = SYNTH_HID_PROTOCOL_REQUEST; | ||
| 389 | request->request.header.size = sizeof(unsigned int); | ||
| 390 | request->request.version_requested.version = SYNTHHID_INPUT_VERSION; | ||
| 391 | |||
| 392 | ret = vmbus_sendpacket(device->channel, request, | ||
| 393 | sizeof(struct pipe_prt_msg) - | ||
| 394 | sizeof(unsigned char) + | ||
| 395 | sizeof(struct synthhid_protocol_request), | ||
| 396 | (unsigned long)request, | ||
| 397 | VM_PKT_DATA_INBAND, | ||
| 398 | VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); | ||
| 399 | if (ret) | ||
| 400 | goto cleanup; | ||
| 401 | |||
| 402 | t = wait_for_completion_timeout(&input_dev->wait_event, 5*HZ); | ||
| 403 | if (!t) { | ||
| 404 | ret = -ETIMEDOUT; | ||
| 405 | goto cleanup; | ||
| 406 | } | ||
| 407 | |||
| 408 | response = &input_dev->protocol_resp; | ||
| 409 | |||
| 410 | if (!response->response.approved) { | ||
| 411 | pr_err("synthhid protocol request failed (version %d)\n", | ||
| 412 | SYNTHHID_INPUT_VERSION); | ||
| 413 | ret = -ENODEV; | ||
| 414 | goto cleanup; | ||
| 415 | } | ||
| 416 | |||
| 417 | t = wait_for_completion_timeout(&input_dev->wait_event, 5*HZ); | ||
| 418 | if (!t) { | ||
| 419 | ret = -ETIMEDOUT; | ||
| 420 | goto cleanup; | ||
| 421 | } | ||
| 422 | |||
| 423 | /* | ||
| 424 | * We should have gotten the device attr, hid desc and report | ||
| 425 | * desc at this point | ||
| 426 | */ | ||
| 427 | ret = input_dev->dev_info_status; | ||
| 428 | |||
| 429 | cleanup: | ||
| 430 | return ret; | ||
| 431 | } | ||
| 432 | |||
| 433 | static int mousevsc_hid_open(struct hid_device *hid) | ||
| 434 | { | ||
| 435 | return 0; | ||
| 436 | } | ||
| 437 | |||
| 438 | static int mousevsc_hid_start(struct hid_device *hid) | ||
| 439 | { | ||
| 440 | return 0; | ||
| 441 | } | ||
| 442 | |||
| 443 | static void mousevsc_hid_close(struct hid_device *hid) | ||
| 444 | { | ||
| 445 | } | ||
| 446 | |||
| 447 | static void mousevsc_hid_stop(struct hid_device *hid) | ||
| 448 | { | ||
| 449 | } | ||
| 450 | |||
| 451 | static struct hid_ll_driver mousevsc_ll_driver = { | ||
| 452 | .open = mousevsc_hid_open, | ||
| 453 | .close = mousevsc_hid_close, | ||
| 454 | .start = mousevsc_hid_start, | ||
| 455 | .stop = mousevsc_hid_stop, | ||
| 456 | }; | ||
| 457 | |||
| 458 | static struct hid_driver mousevsc_hid_driver; | ||
| 459 | |||
| 460 | static int mousevsc_probe(struct hv_device *device, | ||
| 461 | const struct hv_vmbus_device_id *dev_id) | ||
| 462 | { | ||
| 463 | int ret; | ||
| 464 | struct mousevsc_dev *input_dev; | ||
| 465 | struct hid_device *hid_dev; | ||
| 466 | |||
| 467 | input_dev = mousevsc_alloc_device(device); | ||
| 468 | |||
| 469 | if (!input_dev) | ||
| 470 | return -ENOMEM; | ||
| 471 | |||
| 472 | ret = vmbus_open(device->channel, | ||
| 473 | INPUTVSC_SEND_RING_BUFFER_SIZE, | ||
| 474 | INPUTVSC_RECV_RING_BUFFER_SIZE, | ||
| 475 | NULL, | ||
| 476 | 0, | ||
| 477 | mousevsc_on_channel_callback, | ||
| 478 | device | ||
| 479 | ); | ||
| 480 | |||
| 481 | if (ret) | ||
| 482 | goto probe_err0; | ||
| 483 | |||
| 484 | ret = mousevsc_connect_to_vsp(device); | ||
| 485 | |||
| 486 | if (ret) | ||
| 487 | goto probe_err1; | ||
| 488 | |||
| 489 | /* workaround SA-167 */ | ||
| 490 | if (input_dev->report_desc[14] == 0x25) | ||
| 491 | input_dev->report_desc[14] = 0x29; | ||
| 492 | |||
| 493 | hid_dev = hid_allocate_device(); | ||
| 494 | if (IS_ERR(hid_dev)) { | ||
| 495 | ret = PTR_ERR(hid_dev); | ||
| 496 | goto probe_err1; | ||
| 497 | } | ||
| 498 | |||
| 499 | hid_dev->ll_driver = &mousevsc_ll_driver; | ||
| 500 | hid_dev->driver = &mousevsc_hid_driver; | ||
| 501 | hid_dev->bus = BUS_VIRTUAL; | ||
| 502 | hid_dev->vendor = input_dev->hid_dev_info.vendor; | ||
| 503 | hid_dev->product = input_dev->hid_dev_info.product; | ||
| 504 | hid_dev->version = input_dev->hid_dev_info.version; | ||
| 505 | input_dev->hid_device = hid_dev; | ||
| 506 | |||
| 507 | sprintf(hid_dev->name, "%s", "Microsoft Vmbus HID-compliant Mouse"); | ||
| 508 | |||
| 509 | ret = hid_add_device(hid_dev); | ||
| 510 | if (ret) | ||
| 511 | goto probe_err1; | ||
| 512 | |||
| 513 | ret = hid_parse_report(hid_dev, input_dev->report_desc, | ||
| 514 | input_dev->report_desc_size); | ||
| 515 | |||
| 516 | if (ret) { | ||
| 517 | hid_err(hid_dev, "parse failed\n"); | ||
| 518 | goto probe_err2; | ||
| 519 | } | ||
| 520 | |||
| 521 | ret = hid_hw_start(hid_dev, HID_CONNECT_HIDINPUT | HID_CONNECT_HIDDEV); | ||
| 522 | |||
| 523 | if (ret) { | ||
| 524 | hid_err(hid_dev, "hw start failed\n"); | ||
| 525 | goto probe_err2; | ||
| 526 | } | ||
| 527 | |||
| 528 | input_dev->connected = true; | ||
| 529 | input_dev->init_complete = true; | ||
| 530 | |||
| 531 | return ret; | ||
| 532 | |||
| 533 | probe_err2: | ||
| 534 | hid_destroy_device(hid_dev); | ||
| 535 | |||
| 536 | probe_err1: | ||
| 537 | vmbus_close(device->channel); | ||
| 538 | |||
| 539 | probe_err0: | ||
| 540 | mousevsc_free_device(input_dev); | ||
| 541 | |||
| 542 | return ret; | ||
| 543 | } | ||
| 544 | |||
| 545 | |||
| 546 | static int mousevsc_remove(struct hv_device *dev) | ||
| 547 | { | ||
| 548 | struct mousevsc_dev *input_dev = hv_get_drvdata(dev); | ||
| 549 | |||
| 550 | vmbus_close(dev->channel); | ||
| 551 | hid_destroy_device(input_dev->hid_device); | ||
| 552 | mousevsc_free_device(input_dev); | ||
| 553 | |||
| 554 | return 0; | ||
| 555 | } | ||
| 556 | |||
| 557 | static const struct hv_vmbus_device_id id_table[] = { | ||
| 558 | /* Mouse guid */ | ||
| 559 | { VMBUS_DEVICE(0x9E, 0xB6, 0xA8, 0xCF, 0x4A, 0x5B, 0xc0, 0x4c, | ||
| 560 | 0xB9, 0x8B, 0x8B, 0xA1, 0xA1, 0xF3, 0xF9, 0x5A) }, | ||
| 561 | { }, | ||
| 562 | }; | ||
| 563 | |||
| 564 | MODULE_DEVICE_TABLE(vmbus, id_table); | ||
| 565 | |||
| 566 | static struct hv_driver mousevsc_drv = { | ||
| 567 | .name = KBUILD_MODNAME, | ||
| 568 | .id_table = id_table, | ||
| 569 | .probe = mousevsc_probe, | ||
| 570 | .remove = mousevsc_remove, | ||
| 571 | }; | ||
| 572 | |||
| 573 | static int __init mousevsc_init(void) | ||
| 574 | { | ||
| 575 | return vmbus_driver_register(&mousevsc_drv); | ||
| 576 | } | ||
| 577 | |||
| 578 | static void __exit mousevsc_exit(void) | ||
| 579 | { | ||
| 580 | vmbus_driver_unregister(&mousevsc_drv); | ||
| 581 | } | ||
| 582 | |||
| 583 | MODULE_LICENSE("GPL"); | ||
| 584 | MODULE_VERSION(HV_DRV_VERSION); | ||
| 585 | module_init(mousevsc_init); | ||
| 586 | module_exit(mousevsc_exit); | ||
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 4a441a6f9967..b8574cddd953 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #define USB_VENDOR_ID_3M 0x0596 | 21 | #define USB_VENDOR_ID_3M 0x0596 |
| 22 | #define USB_DEVICE_ID_3M1968 0x0500 | 22 | #define USB_DEVICE_ID_3M1968 0x0500 |
| 23 | #define USB_DEVICE_ID_3M2256 0x0502 | 23 | #define USB_DEVICE_ID_3M2256 0x0502 |
| 24 | #define USB_DEVICE_ID_3M3266 0x0506 | ||
| 24 | 25 | ||
| 25 | #define USB_VENDOR_ID_A4TECH 0x09da | 26 | #define USB_VENDOR_ID_A4TECH 0x09da |
| 26 | #define USB_DEVICE_ID_A4TECH_WCP32PU 0x0006 | 27 | #define USB_DEVICE_ID_A4TECH_WCP32PU 0x0006 |
| @@ -124,6 +125,7 @@ | |||
| 124 | #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI 0x0239 | 125 | #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI 0x0239 |
| 125 | #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO 0x023a | 126 | #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO 0x023a |
| 126 | #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS 0x023b | 127 | #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS 0x023b |
| 128 | #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI 0x0255 | ||
| 127 | #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO 0x0256 | 129 | #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO 0x0256 |
| 128 | #define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a | 130 | #define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a |
| 129 | #define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b | 131 | #define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b |
| @@ -145,6 +147,9 @@ | |||
| 145 | #define USB_DEVICE_ID_ATEN_4PORTKVM 0x2205 | 147 | #define USB_DEVICE_ID_ATEN_4PORTKVM 0x2205 |
| 146 | #define USB_DEVICE_ID_ATEN_4PORTKVMC 0x2208 | 148 | #define USB_DEVICE_ID_ATEN_4PORTKVMC 0x2208 |
| 147 | 149 | ||
| 150 | #define USB_VENDOR_ID_ATMEL 0x03eb | ||
| 151 | #define USB_DEVICE_ID_ATMEL_MULTITOUCH 0x211c | ||
| 152 | |||
| 148 | #define USB_VENDOR_ID_AVERMEDIA 0x07ca | 153 | #define USB_VENDOR_ID_AVERMEDIA 0x07ca |
| 149 | #define USB_DEVICE_ID_AVER_FM_MR800 0xb800 | 154 | #define USB_DEVICE_ID_AVER_FM_MR800 0xb800 |
| 150 | 155 | ||
| @@ -230,11 +235,14 @@ | |||
| 230 | 235 | ||
| 231 | #define USB_VENDOR_ID_DWAV 0x0eef | 236 | #define USB_VENDOR_ID_DWAV 0x0eef |
| 232 | #define USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER 0x0001 | 237 | #define USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER 0x0001 |
| 233 | #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH 0x480d | 238 | #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480D 0x480d |
| 234 | #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1 0x720c | 239 | #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480E 0x480e |
| 235 | #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH2 0x72a1 | 240 | #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_720C 0x720c |
| 236 | #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH3 0x480e | 241 | #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_726B 0x726b |
| 237 | #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH4 0x726b | 242 | #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72A1 0x72a1 |
| 243 | #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72FA 0x72fa | ||
| 244 | #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7302 0x7302 | ||
| 245 | #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001 0xa001 | ||
| 238 | 246 | ||
| 239 | #define USB_VENDOR_ID_ELECOM 0x056e | 247 | #define USB_VENDOR_ID_ELECOM 0x056e |
| 240 | #define USB_DEVICE_ID_ELECOM_BM084 0x0061 | 248 | #define USB_DEVICE_ID_ELECOM_BM084 0x0061 |
| @@ -356,6 +364,9 @@ | |||
| 356 | #define USB_VENDOR_ID_HANVON 0x20b3 | 364 | #define USB_VENDOR_ID_HANVON 0x20b3 |
| 357 | #define USB_DEVICE_ID_HANVON_MULTITOUCH 0x0a18 | 365 | #define USB_DEVICE_ID_HANVON_MULTITOUCH 0x0a18 |
| 358 | 366 | ||
| 367 | #define USB_VENDOR_ID_HANVON_ALT 0x22ed | ||
| 368 | #define USB_DEVICE_ID_HANVON_ALT_MULTITOUCH 0x1010 | ||
| 369 | |||
| 359 | #define USB_VENDOR_ID_HAPP 0x078b | 370 | #define USB_VENDOR_ID_HAPP 0x078b |
| 360 | #define USB_DEVICE_ID_UGCI_DRIVING 0x0010 | 371 | #define USB_DEVICE_ID_UGCI_DRIVING 0x0010 |
| 361 | #define USB_DEVICE_ID_UGCI_FLYING 0x0020 | 372 | #define USB_DEVICE_ID_UGCI_FLYING 0x0020 |
| @@ -571,6 +582,11 @@ | |||
| 571 | #define USB_VENDOR_ID_PI_ENGINEERING 0x05f3 | 582 | #define USB_VENDOR_ID_PI_ENGINEERING 0x05f3 |
| 572 | #define USB_DEVICE_ID_PI_ENGINEERING_VEC_USB_FOOTPEDAL 0xff | 583 | #define USB_DEVICE_ID_PI_ENGINEERING_VEC_USB_FOOTPEDAL 0xff |
| 573 | 584 | ||
| 585 | #define USB_VENDOR_ID_PIXART 0x093a | ||
| 586 | #define USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN 0x8001 | ||
| 587 | #define USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1 0x8002 | ||
| 588 | #define USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2 0x8003 | ||
| 589 | |||
| 574 | #define USB_VENDOR_ID_PLAYDOTCOM 0x0b43 | 590 | #define USB_VENDOR_ID_PLAYDOTCOM 0x0b43 |
| 575 | #define USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII 0x0003 | 591 | #define USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII 0x0003 |
| 576 | 592 | ||
| @@ -581,11 +597,14 @@ | |||
| 581 | #define USB_DEVICE_ID_PRODIGE_CORDLESS 0x3062 | 597 | #define USB_DEVICE_ID_PRODIGE_CORDLESS 0x3062 |
| 582 | 598 | ||
| 583 | #define USB_VENDOR_ID_QUANTA 0x0408 | 599 | #define USB_VENDOR_ID_QUANTA 0x0408 |
| 584 | #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH 0x3000 | 600 | #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH 0x3000 |
| 601 | #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001 0x3001 | ||
| 602 | #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008 0x3008 | ||
| 585 | #define USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN 0x3001 | 603 | #define USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN 0x3001 |
| 586 | 604 | ||
| 587 | #define USB_VENDOR_ID_ROCCAT 0x1e7d | 605 | #define USB_VENDOR_ID_ROCCAT 0x1e7d |
| 588 | #define USB_DEVICE_ID_ROCCAT_ARVO 0x30d4 | 606 | #define USB_DEVICE_ID_ROCCAT_ARVO 0x30d4 |
| 607 | #define USB_DEVICE_ID_ROCCAT_ISKU 0x319c | ||
| 589 | #define USB_DEVICE_ID_ROCCAT_KONE 0x2ced | 608 | #define USB_DEVICE_ID_ROCCAT_KONE 0x2ced |
| 590 | #define USB_DEVICE_ID_ROCCAT_KONEPLUS 0x2d51 | 609 | #define USB_DEVICE_ID_ROCCAT_KONEPLUS 0x2d51 |
| 591 | #define USB_DEVICE_ID_ROCCAT_KOVAPLUS 0x2d50 | 610 | #define USB_DEVICE_ID_ROCCAT_KOVAPLUS 0x2d50 |
| @@ -679,6 +698,7 @@ | |||
| 679 | 698 | ||
| 680 | #define USB_VENDOR_ID_WACOM 0x056a | 699 | #define USB_VENDOR_ID_WACOM 0x056a |
| 681 | #define USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH 0x81 | 700 | #define USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH 0x81 |
| 701 | #define USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH 0x00BD | ||
| 682 | 702 | ||
| 683 | #define USB_VENDOR_ID_WALTOP 0x172f | 703 | #define USB_VENDOR_ID_WALTOP 0x172f |
| 684 | #define USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH 0x0032 | 704 | #define USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH 0x0032 |
| @@ -707,6 +727,17 @@ | |||
| 707 | #define USB_VENDOR_ID_XAT 0x2505 | 727 | #define USB_VENDOR_ID_XAT 0x2505 |
| 708 | #define USB_DEVICE_ID_XAT_CSR 0x0220 | 728 | #define USB_DEVICE_ID_XAT_CSR 0x0220 |
| 709 | 729 | ||
| 730 | #define USB_VENDOR_ID_XIROKU 0x1477 | ||
| 731 | #define USB_DEVICE_ID_XIROKU_SPX 0x1006 | ||
| 732 | #define USB_DEVICE_ID_XIROKU_MPX 0x1007 | ||
| 733 | #define USB_DEVICE_ID_XIROKU_CSR 0x100e | ||
| 734 | #define USB_DEVICE_ID_XIROKU_SPX1 0x1021 | ||
| 735 | #define USB_DEVICE_ID_XIROKU_CSR1 0x1022 | ||
| 736 | #define USB_DEVICE_ID_XIROKU_MPX1 0x1023 | ||
| 737 | #define USB_DEVICE_ID_XIROKU_SPX2 0x1024 | ||
| 738 | #define USB_DEVICE_ID_XIROKU_CSR2 0x1025 | ||
| 739 | #define USB_DEVICE_ID_XIROKU_MPX2 0x1026 | ||
| 740 | |||
| 710 | #define USB_VENDOR_ID_YEALINK 0x6993 | 741 | #define USB_VENDOR_ID_YEALINK 0x6993 |
| 711 | #define USB_DEVICE_ID_YEALINK_P1K_P4K_B2K 0xb001 | 742 | #define USB_DEVICE_ID_YEALINK_P1K_P4K_B2K 0xb001 |
| 712 | 743 | ||
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index f333139d1a48..9333d692a786 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c | |||
| @@ -32,6 +32,8 @@ | |||
| 32 | #include <linux/hid.h> | 32 | #include <linux/hid.h> |
| 33 | #include <linux/hid-debug.h> | 33 | #include <linux/hid-debug.h> |
| 34 | 34 | ||
| 35 | #include "hid-ids.h" | ||
| 36 | |||
| 35 | #define unk KEY_UNKNOWN | 37 | #define unk KEY_UNKNOWN |
| 36 | 38 | ||
| 37 | static const unsigned char hid_keyboard[256] = { | 39 | static const unsigned char hid_keyboard[256] = { |
| @@ -271,6 +273,161 @@ static __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code) | |||
| 271 | return logical_extents / physical_extents; | 273 | return logical_extents / physical_extents; |
| 272 | } | 274 | } |
| 273 | 275 | ||
| 276 | #ifdef CONFIG_HID_BATTERY_STRENGTH | ||
| 277 | static enum power_supply_property hidinput_battery_props[] = { | ||
| 278 | POWER_SUPPLY_PROP_PRESENT, | ||
| 279 | POWER_SUPPLY_PROP_ONLINE, | ||
| 280 | POWER_SUPPLY_PROP_CAPACITY, | ||
| 281 | POWER_SUPPLY_PROP_MODEL_NAME, | ||
| 282 | POWER_SUPPLY_PROP_STATUS | ||
| 283 | }; | ||
| 284 | |||
| 285 | #define HID_BATTERY_QUIRK_PERCENT (1 << 0) /* always reports percent */ | ||
| 286 | #define HID_BATTERY_QUIRK_FEATURE (1 << 1) /* ask for feature report */ | ||
| 287 | |||
| 288 | static const struct hid_device_id hid_battery_quirks[] = { | ||
| 289 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, | ||
| 290 | USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI), | ||
| 291 | HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE }, | ||
| 292 | {} | ||
| 293 | }; | ||
| 294 | |||
| 295 | static unsigned find_battery_quirk(struct hid_device *hdev) | ||
| 296 | { | ||
| 297 | unsigned quirks = 0; | ||
| 298 | const struct hid_device_id *match; | ||
| 299 | |||
| 300 | match = hid_match_id(hdev, hid_battery_quirks); | ||
| 301 | if (match != NULL) | ||
| 302 | quirks = match->driver_data; | ||
| 303 | |||
| 304 | return quirks; | ||
| 305 | } | ||
| 306 | |||
| 307 | static int hidinput_get_battery_property(struct power_supply *psy, | ||
| 308 | enum power_supply_property prop, | ||
| 309 | union power_supply_propval *val) | ||
| 310 | { | ||
| 311 | struct hid_device *dev = container_of(psy, struct hid_device, battery); | ||
| 312 | int ret = 0; | ||
| 313 | __u8 buf[2] = {}; | ||
| 314 | |||
| 315 | switch (prop) { | ||
| 316 | case POWER_SUPPLY_PROP_PRESENT: | ||
| 317 | case POWER_SUPPLY_PROP_ONLINE: | ||
| 318 | val->intval = 1; | ||
| 319 | break; | ||
| 320 | |||
| 321 | case POWER_SUPPLY_PROP_CAPACITY: | ||
| 322 | ret = dev->hid_get_raw_report(dev, dev->battery_report_id, | ||
| 323 | buf, sizeof(buf), | ||
| 324 | dev->battery_report_type); | ||
| 325 | |||
| 326 | if (ret != 2) { | ||
| 327 | if (ret >= 0) | ||
| 328 | ret = -EINVAL; | ||
| 329 | break; | ||
| 330 | } | ||
| 331 | |||
| 332 | if (dev->battery_min < dev->battery_max && | ||
| 333 | buf[1] >= dev->battery_min && | ||
| 334 | buf[1] <= dev->battery_max) | ||
| 335 | val->intval = (100 * (buf[1] - dev->battery_min)) / | ||
| 336 | (dev->battery_max - dev->battery_min); | ||
| 337 | break; | ||
| 338 | |||
| 339 | case POWER_SUPPLY_PROP_MODEL_NAME: | ||
| 340 | val->strval = dev->name; | ||
| 341 | break; | ||
| 342 | |||
| 343 | case POWER_SUPPLY_PROP_STATUS: | ||
| 344 | val->intval = POWER_SUPPLY_STATUS_DISCHARGING; | ||
| 345 | break; | ||
| 346 | |||
| 347 | default: | ||
| 348 | ret = -EINVAL; | ||
| 349 | break; | ||
| 350 | } | ||
| 351 | |||
| 352 | return ret; | ||
| 353 | } | ||
| 354 | |||
| 355 | static bool hidinput_setup_battery(struct hid_device *dev, unsigned report_type, struct hid_field *field) | ||
| 356 | { | ||
| 357 | struct power_supply *battery = &dev->battery; | ||
| 358 | int ret; | ||
| 359 | unsigned quirks; | ||
| 360 | s32 min, max; | ||
| 361 | |||
| 362 | if (field->usage->hid != HID_DC_BATTERYSTRENGTH) | ||
| 363 | return false; /* no match */ | ||
| 364 | |||
| 365 | if (battery->name != NULL) | ||
| 366 | goto out; /* already initialized? */ | ||
| 367 | |||
| 368 | battery->name = kasprintf(GFP_KERNEL, "hid-%s-battery", dev->uniq); | ||
| 369 | if (battery->name == NULL) | ||
| 370 | goto out; | ||
| 371 | |||
| 372 | battery->type = POWER_SUPPLY_TYPE_BATTERY; | ||
| 373 | battery->properties = hidinput_battery_props; | ||
| 374 | battery->num_properties = ARRAY_SIZE(hidinput_battery_props); | ||
| 375 | battery->use_for_apm = 0; | ||
| 376 | battery->get_property = hidinput_get_battery_property; | ||
| 377 | |||
| 378 | quirks = find_battery_quirk(dev); | ||
| 379 | |||
| 380 | hid_dbg(dev, "device %x:%x:%x %d quirks %d\n", | ||
| 381 | dev->bus, dev->vendor, dev->product, dev->version, quirks); | ||
| 382 | |||
| 383 | min = field->logical_minimum; | ||
| 384 | max = field->logical_maximum; | ||
| 385 | |||
| 386 | if (quirks & HID_BATTERY_QUIRK_PERCENT) { | ||
| 387 | min = 0; | ||
| 388 | max = 100; | ||
| 389 | } | ||
| 390 | |||
| 391 | if (quirks & HID_BATTERY_QUIRK_FEATURE) | ||
| 392 | report_type = HID_FEATURE_REPORT; | ||
| 393 | |||
| 394 | dev->battery_min = min; | ||
| 395 | dev->battery_max = max; | ||
| 396 | dev->battery_report_type = report_type; | ||
| 397 | dev->battery_report_id = field->report->id; | ||
| 398 | |||
| 399 | ret = power_supply_register(&dev->dev, battery); | ||
| 400 | if (ret != 0) { | ||
| 401 | hid_warn(dev, "can't register power supply: %d\n", ret); | ||
| 402 | kfree(battery->name); | ||
| 403 | battery->name = NULL; | ||
| 404 | } | ||
| 405 | |||
| 406 | out: | ||
| 407 | return true; | ||
| 408 | } | ||
| 409 | |||
| 410 | static void hidinput_cleanup_battery(struct hid_device *dev) | ||
| 411 | { | ||
| 412 | if (!dev->battery.name) | ||
| 413 | return; | ||
| 414 | |||
| 415 | power_supply_unregister(&dev->battery); | ||
| 416 | kfree(dev->battery.name); | ||
| 417 | dev->battery.name = NULL; | ||
| 418 | } | ||
| 419 | #else /* !CONFIG_HID_BATTERY_STRENGTH */ | ||
| 420 | static bool hidinput_setup_battery(struct hid_device *dev, unsigned report_type, | ||
| 421 | struct hid_field *field) | ||
| 422 | { | ||
| 423 | return false; | ||
| 424 | } | ||
| 425 | |||
| 426 | static void hidinput_cleanup_battery(struct hid_device *dev) | ||
| 427 | { | ||
| 428 | } | ||
| 429 | #endif /* CONFIG_HID_BATTERY_STRENGTH */ | ||
| 430 | |||
| 274 | static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field, | 431 | static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field, |
| 275 | struct hid_usage *usage) | 432 | struct hid_usage *usage) |
| 276 | { | 433 | { |
| @@ -629,6 +786,13 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
| 629 | } | 786 | } |
| 630 | break; | 787 | break; |
| 631 | 788 | ||
| 789 | case HID_UP_GENDEVCTRLS: | ||
| 790 | if (hidinput_setup_battery(device, HID_INPUT_REPORT, field)) | ||
| 791 | goto ignore; | ||
| 792 | else | ||
| 793 | goto unknown; | ||
| 794 | break; | ||
| 795 | |||
| 632 | case HID_UP_HPVENDOR: /* Reported on a Dutch layout HP5308 */ | 796 | case HID_UP_HPVENDOR: /* Reported on a Dutch layout HP5308 */ |
| 633 | set_bit(EV_REP, input->evbit); | 797 | set_bit(EV_REP, input->evbit); |
| 634 | switch (usage->hid & HID_USAGE) { | 798 | switch (usage->hid & HID_USAGE) { |
| @@ -822,6 +986,12 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct | |||
| 822 | return; | 986 | return; |
| 823 | } | 987 | } |
| 824 | 988 | ||
| 989 | /* Ignore out-of-range values as per HID specification, section 5.10 */ | ||
| 990 | if (value < field->logical_minimum || value > field->logical_maximum) { | ||
| 991 | dbg_hid("Ignoring out-of-range value %x\n", value); | ||
| 992 | return; | ||
| 993 | } | ||
| 994 | |||
| 825 | /* report the usage code as scancode if the key status has changed */ | 995 | /* report the usage code as scancode if the key status has changed */ |
| 826 | if (usage->type == EV_KEY && !!test_bit(usage->code, input->key) != value) | 996 | if (usage->type == EV_KEY && !!test_bit(usage->code, input->key) != value) |
| 827 | input_event(input, EV_MSC, MSC_SCAN, usage->hid); | 997 | input_event(input, EV_MSC, MSC_SCAN, usage->hid); |
| @@ -861,6 +1031,48 @@ int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int | |||
| 861 | } | 1031 | } |
| 862 | EXPORT_SYMBOL_GPL(hidinput_find_field); | 1032 | EXPORT_SYMBOL_GPL(hidinput_find_field); |
| 863 | 1033 | ||
| 1034 | struct hid_field *hidinput_get_led_field(struct hid_device *hid) | ||
| 1035 | { | ||
| 1036 | struct hid_report *report; | ||
| 1037 | struct hid_field *field; | ||
| 1038 | int i, j; | ||
| 1039 | |||
| 1040 | list_for_each_entry(report, | ||
| 1041 | &hid->report_enum[HID_OUTPUT_REPORT].report_list, | ||
| 1042 | list) { | ||
| 1043 | for (i = 0; i < report->maxfield; i++) { | ||
| 1044 | field = report->field[i]; | ||
| 1045 | for (j = 0; j < field->maxusage; j++) | ||
| 1046 | if (field->usage[j].type == EV_LED) | ||
| 1047 | return field; | ||
| 1048 | } | ||
| 1049 | } | ||
| 1050 | return NULL; | ||
| 1051 | } | ||
| 1052 | EXPORT_SYMBOL_GPL(hidinput_get_led_field); | ||
| 1053 | |||
| 1054 | unsigned int hidinput_count_leds(struct hid_device *hid) | ||
| 1055 | { | ||
| 1056 | struct hid_report *report; | ||
| 1057 | struct hid_field *field; | ||
| 1058 | int i, j; | ||
| 1059 | unsigned int count = 0; | ||
| 1060 | |||
| 1061 | list_for_each_entry(report, | ||
| 1062 | &hid->report_enum[HID_OUTPUT_REPORT].report_list, | ||
| 1063 | list) { | ||
| 1064 | for (i = 0; i < report->maxfield; i++) { | ||
| 1065 | field = report->field[i]; | ||
| 1066 | for (j = 0; j < field->maxusage; j++) | ||
| 1067 | if (field->usage[j].type == EV_LED && | ||
| 1068 | field->value[j]) | ||
| 1069 | count += 1; | ||
| 1070 | } | ||
| 1071 | } | ||
| 1072 | return count; | ||
| 1073 | } | ||
| 1074 | EXPORT_SYMBOL_GPL(hidinput_count_leds); | ||
| 1075 | |||
| 864 | static int hidinput_open(struct input_dev *dev) | 1076 | static int hidinput_open(struct input_dev *dev) |
| 865 | { | 1077 | { |
| 866 | struct hid_device *hid = input_get_drvdata(dev); | 1078 | struct hid_device *hid = input_get_drvdata(dev); |
| @@ -882,15 +1094,17 @@ static void report_features(struct hid_device *hid) | |||
| 882 | struct hid_report *rep; | 1094 | struct hid_report *rep; |
| 883 | int i, j; | 1095 | int i, j; |
| 884 | 1096 | ||
| 885 | if (!drv->feature_mapping) | ||
| 886 | return; | ||
| 887 | |||
| 888 | rep_enum = &hid->report_enum[HID_FEATURE_REPORT]; | 1097 | rep_enum = &hid->report_enum[HID_FEATURE_REPORT]; |
| 889 | list_for_each_entry(rep, &rep_enum->report_list, list) | 1098 | list_for_each_entry(rep, &rep_enum->report_list, list) |
| 890 | for (i = 0; i < rep->maxfield; i++) | 1099 | for (i = 0; i < rep->maxfield; i++) |
| 891 | for (j = 0; j < rep->field[i]->maxusage; j++) | 1100 | for (j = 0; j < rep->field[i]->maxusage; j++) { |
| 892 | drv->feature_mapping(hid, rep->field[i], | 1101 | /* Verify if Battery Strength feature is available */ |
| 893 | rep->field[i]->usage + j); | 1102 | hidinput_setup_battery(hid, HID_FEATURE_REPORT, rep->field[i]); |
| 1103 | |||
| 1104 | if (drv->feature_mapping) | ||
| 1105 | drv->feature_mapping(hid, rep->field[i], | ||
| 1106 | rep->field[i]->usage + j); | ||
| 1107 | } | ||
| 894 | } | 1108 | } |
| 895 | 1109 | ||
| 896 | /* | 1110 | /* |
| @@ -1010,6 +1224,8 @@ void hidinput_disconnect(struct hid_device *hid) | |||
| 1010 | { | 1224 | { |
| 1011 | struct hid_input *hidinput, *next; | 1225 | struct hid_input *hidinput, *next; |
| 1012 | 1226 | ||
| 1227 | hidinput_cleanup_battery(hid); | ||
| 1228 | |||
| 1013 | list_for_each_entry_safe(hidinput, next, &hid->inputs, list) { | 1229 | list_for_each_entry_safe(hidinput, next, &hid->inputs, list) { |
| 1014 | list_del(&hidinput->list); | 1230 | list_del(&hidinput->list); |
| 1015 | input_unregister_device(hidinput->input); | 1231 | input_unregister_device(hidinput->input); |
diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c index 103f30d93f76..6ecc9e220440 100644 --- a/drivers/hid/hid-lg4ff.c +++ b/drivers/hid/hid-lg4ff.c | |||
| @@ -430,7 +430,7 @@ int lg4ff_init(struct hid_device *hid) | |||
| 430 | } | 430 | } |
| 431 | 431 | ||
| 432 | /* Add the device to device_list */ | 432 | /* Add the device to device_list */ |
| 433 | entry = (struct lg4ff_device_entry *)kzalloc(sizeof(struct lg4ff_device_entry), GFP_KERNEL); | 433 | entry = kzalloc(sizeof(struct lg4ff_device_entry), GFP_KERNEL); |
| 434 | if (!entry) { | 434 | if (!entry) { |
| 435 | hid_err(hid, "Cannot add device, insufficient memory.\n"); | 435 | hid_err(hid, "Cannot add device, insufficient memory.\n"); |
| 436 | return -ENOMEM; | 436 | return -ENOMEM; |
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index f1c909f1b239..24fc4423b937 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c | |||
| @@ -50,7 +50,6 @@ MODULE_LICENSE("GPL"); | |||
| 50 | #define MT_QUIRK_ALWAYS_VALID (1 << 4) | 50 | #define MT_QUIRK_ALWAYS_VALID (1 << 4) |
| 51 | #define MT_QUIRK_VALID_IS_INRANGE (1 << 5) | 51 | #define MT_QUIRK_VALID_IS_INRANGE (1 << 5) |
| 52 | #define MT_QUIRK_VALID_IS_CONFIDENCE (1 << 6) | 52 | #define MT_QUIRK_VALID_IS_CONFIDENCE (1 << 6) |
| 53 | #define MT_QUIRK_EGALAX_XYZ_FIXUP (1 << 7) | ||
| 54 | #define MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE (1 << 8) | 53 | #define MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE (1 << 8) |
| 55 | 54 | ||
| 56 | struct mt_slot { | 55 | struct mt_slot { |
| @@ -60,9 +59,19 @@ struct mt_slot { | |||
| 60 | bool seen_in_this_frame;/* has this slot been updated */ | 59 | bool seen_in_this_frame;/* has this slot been updated */ |
| 61 | }; | 60 | }; |
| 62 | 61 | ||
| 62 | struct mt_class { | ||
| 63 | __s32 name; /* MT_CLS */ | ||
| 64 | __s32 quirks; | ||
| 65 | __s32 sn_move; /* Signal/noise ratio for move events */ | ||
| 66 | __s32 sn_width; /* Signal/noise ratio for width events */ | ||
| 67 | __s32 sn_height; /* Signal/noise ratio for height events */ | ||
| 68 | __s32 sn_pressure; /* Signal/noise ratio for pressure events */ | ||
| 69 | __u8 maxcontacts; | ||
| 70 | }; | ||
| 71 | |||
| 63 | struct mt_device { | 72 | struct mt_device { |
| 64 | struct mt_slot curdata; /* placeholder of incoming data */ | 73 | struct mt_slot curdata; /* placeholder of incoming data */ |
| 65 | struct mt_class *mtclass; /* our mt device class */ | 74 | struct mt_class mtclass; /* our mt device class */ |
| 66 | unsigned last_field_index; /* last field index of the report */ | 75 | unsigned last_field_index; /* last field index of the report */ |
| 67 | unsigned last_slot_field; /* the last field of a slot */ | 76 | unsigned last_slot_field; /* the last field of a slot */ |
| 68 | int last_mt_collection; /* last known mt-related collection */ | 77 | int last_mt_collection; /* last known mt-related collection */ |
| @@ -74,30 +83,23 @@ struct mt_device { | |||
| 74 | struct mt_slot *slots; | 83 | struct mt_slot *slots; |
| 75 | }; | 84 | }; |
| 76 | 85 | ||
| 77 | struct mt_class { | ||
| 78 | __s32 name; /* MT_CLS */ | ||
| 79 | __s32 quirks; | ||
| 80 | __s32 sn_move; /* Signal/noise ratio for move events */ | ||
| 81 | __s32 sn_width; /* Signal/noise ratio for width events */ | ||
| 82 | __s32 sn_height; /* Signal/noise ratio for height events */ | ||
| 83 | __s32 sn_pressure; /* Signal/noise ratio for pressure events */ | ||
| 84 | __u8 maxcontacts; | ||
| 85 | }; | ||
| 86 | |||
| 87 | /* classes of device behavior */ | 86 | /* classes of device behavior */ |
| 88 | #define MT_CLS_DEFAULT 0x0001 | 87 | #define MT_CLS_DEFAULT 0x0001 |
| 89 | 88 | ||
| 90 | #define MT_CLS_SERIAL 0x0002 | 89 | #define MT_CLS_SERIAL 0x0002 |
| 91 | #define MT_CLS_CONFIDENCE 0x0003 | 90 | #define MT_CLS_CONFIDENCE 0x0003 |
| 92 | #define MT_CLS_CONFIDENCE_MINUS_ONE 0x0004 | 91 | #define MT_CLS_CONFIDENCE_CONTACT_ID 0x0004 |
| 93 | #define MT_CLS_DUAL_INRANGE_CONTACTID 0x0005 | 92 | #define MT_CLS_CONFIDENCE_MINUS_ONE 0x0005 |
| 94 | #define MT_CLS_DUAL_INRANGE_CONTACTNUMBER 0x0006 | 93 | #define MT_CLS_DUAL_INRANGE_CONTACTID 0x0006 |
| 95 | #define MT_CLS_DUAL_NSMU_CONTACTID 0x0007 | 94 | #define MT_CLS_DUAL_INRANGE_CONTACTNUMBER 0x0007 |
| 95 | #define MT_CLS_DUAL_NSMU_CONTACTID 0x0008 | ||
| 96 | #define MT_CLS_INRANGE_CONTACTNUMBER 0x0009 | ||
| 96 | 97 | ||
| 97 | /* vendor specific classes */ | 98 | /* vendor specific classes */ |
| 98 | #define MT_CLS_3M 0x0101 | 99 | #define MT_CLS_3M 0x0101 |
| 99 | #define MT_CLS_CYPRESS 0x0102 | 100 | #define MT_CLS_CYPRESS 0x0102 |
| 100 | #define MT_CLS_EGALAX 0x0103 | 101 | #define MT_CLS_EGALAX 0x0103 |
| 102 | #define MT_CLS_EGALAX_SERIAL 0x0104 | ||
| 101 | 103 | ||
| 102 | #define MT_DEFAULT_MAXCONTACT 10 | 104 | #define MT_DEFAULT_MAXCONTACT 10 |
| 103 | 105 | ||
| @@ -133,13 +135,16 @@ static int find_slot_from_contactid(struct mt_device *td) | |||
| 133 | return -1; | 135 | return -1; |
| 134 | } | 136 | } |
| 135 | 137 | ||
| 136 | struct mt_class mt_classes[] = { | 138 | static struct mt_class mt_classes[] = { |
| 137 | { .name = MT_CLS_DEFAULT, | 139 | { .name = MT_CLS_DEFAULT, |
| 138 | .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP }, | 140 | .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP }, |
| 139 | { .name = MT_CLS_SERIAL, | 141 | { .name = MT_CLS_SERIAL, |
| 140 | .quirks = MT_QUIRK_ALWAYS_VALID}, | 142 | .quirks = MT_QUIRK_ALWAYS_VALID}, |
| 141 | { .name = MT_CLS_CONFIDENCE, | 143 | { .name = MT_CLS_CONFIDENCE, |
| 142 | .quirks = MT_QUIRK_VALID_IS_CONFIDENCE }, | 144 | .quirks = MT_QUIRK_VALID_IS_CONFIDENCE }, |
| 145 | { .name = MT_CLS_CONFIDENCE_CONTACT_ID, | ||
| 146 | .quirks = MT_QUIRK_VALID_IS_CONFIDENCE | | ||
| 147 | MT_QUIRK_SLOT_IS_CONTACTID }, | ||
| 143 | { .name = MT_CLS_CONFIDENCE_MINUS_ONE, | 148 | { .name = MT_CLS_CONFIDENCE_MINUS_ONE, |
| 144 | .quirks = MT_QUIRK_VALID_IS_CONFIDENCE | | 149 | .quirks = MT_QUIRK_VALID_IS_CONFIDENCE | |
| 145 | MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE }, | 150 | MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE }, |
| @@ -155,6 +160,9 @@ struct mt_class mt_classes[] = { | |||
| 155 | .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP | | 160 | .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP | |
| 156 | MT_QUIRK_SLOT_IS_CONTACTID, | 161 | MT_QUIRK_SLOT_IS_CONTACTID, |
| 157 | .maxcontacts = 2 }, | 162 | .maxcontacts = 2 }, |
| 163 | { .name = MT_CLS_INRANGE_CONTACTNUMBER, | ||
| 164 | .quirks = MT_QUIRK_VALID_IS_INRANGE | | ||
| 165 | MT_QUIRK_SLOT_IS_CONTACTNUMBER }, | ||
| 158 | 166 | ||
| 159 | /* | 167 | /* |
| 160 | * vendor specific classes | 168 | * vendor specific classes |
| @@ -171,9 +179,13 @@ struct mt_class mt_classes[] = { | |||
| 171 | .maxcontacts = 10 }, | 179 | .maxcontacts = 10 }, |
| 172 | { .name = MT_CLS_EGALAX, | 180 | { .name = MT_CLS_EGALAX, |
| 173 | .quirks = MT_QUIRK_SLOT_IS_CONTACTID | | 181 | .quirks = MT_QUIRK_SLOT_IS_CONTACTID | |
| 174 | MT_QUIRK_VALID_IS_INRANGE | | 182 | MT_QUIRK_VALID_IS_INRANGE, |
| 175 | MT_QUIRK_EGALAX_XYZ_FIXUP, | 183 | .sn_move = 4096, |
| 176 | .maxcontacts = 2, | 184 | .sn_pressure = 32, |
| 185 | }, | ||
| 186 | { .name = MT_CLS_EGALAX_SERIAL, | ||
| 187 | .quirks = MT_QUIRK_SLOT_IS_CONTACTID | | ||
| 188 | MT_QUIRK_ALWAYS_VALID, | ||
| 177 | .sn_move = 4096, | 189 | .sn_move = 4096, |
| 178 | .sn_pressure = 32, | 190 | .sn_pressure = 32, |
| 179 | }, | 191 | }, |
| @@ -181,6 +193,44 @@ struct mt_class mt_classes[] = { | |||
| 181 | { } | 193 | { } |
| 182 | }; | 194 | }; |
| 183 | 195 | ||
| 196 | static ssize_t mt_show_quirks(struct device *dev, | ||
| 197 | struct device_attribute *attr, | ||
| 198 | char *buf) | ||
| 199 | { | ||
| 200 | struct hid_device *hdev = container_of(dev, struct hid_device, dev); | ||
| 201 | struct mt_device *td = hid_get_drvdata(hdev); | ||
| 202 | |||
| 203 | return sprintf(buf, "%u\n", td->mtclass.quirks); | ||
| 204 | } | ||
| 205 | |||
| 206 | static ssize_t mt_set_quirks(struct device *dev, | ||
| 207 | struct device_attribute *attr, | ||
| 208 | const char *buf, size_t count) | ||
| 209 | { | ||
| 210 | struct hid_device *hdev = container_of(dev, struct hid_device, dev); | ||
| 211 | struct mt_device *td = hid_get_drvdata(hdev); | ||
| 212 | |||
| 213 | unsigned long val; | ||
| 214 | |||
| 215 | if (kstrtoul(buf, 0, &val)) | ||
| 216 | return -EINVAL; | ||
| 217 | |||
| 218 | td->mtclass.quirks = val; | ||
| 219 | |||
| 220 | return count; | ||
| 221 | } | ||
| 222 | |||
| 223 | static DEVICE_ATTR(quirks, S_IWUSR | S_IRUGO, mt_show_quirks, mt_set_quirks); | ||
| 224 | |||
| 225 | static struct attribute *sysfs_attrs[] = { | ||
| 226 | &dev_attr_quirks.attr, | ||
| 227 | NULL | ||
| 228 | }; | ||
| 229 | |||
| 230 | static struct attribute_group mt_attribute_group = { | ||
| 231 | .attrs = sysfs_attrs | ||
| 232 | }; | ||
| 233 | |||
| 184 | static void mt_feature_mapping(struct hid_device *hdev, | 234 | static void mt_feature_mapping(struct hid_device *hdev, |
| 185 | struct hid_field *field, struct hid_usage *usage) | 235 | struct hid_field *field, struct hid_usage *usage) |
| 186 | { | 236 | { |
| @@ -192,9 +242,9 @@ static void mt_feature_mapping(struct hid_device *hdev, | |||
| 192 | break; | 242 | break; |
| 193 | case HID_DG_CONTACTMAX: | 243 | case HID_DG_CONTACTMAX: |
| 194 | td->maxcontacts = field->value[0]; | 244 | td->maxcontacts = field->value[0]; |
| 195 | if (td->mtclass->maxcontacts) | 245 | if (td->mtclass.maxcontacts) |
| 196 | /* check if the maxcontacts is given by the class */ | 246 | /* check if the maxcontacts is given by the class */ |
| 197 | td->maxcontacts = td->mtclass->maxcontacts; | 247 | td->maxcontacts = td->mtclass.maxcontacts; |
| 198 | 248 | ||
| 199 | break; | 249 | break; |
| 200 | } | 250 | } |
| @@ -214,8 +264,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
| 214 | unsigned long **bit, int *max) | 264 | unsigned long **bit, int *max) |
| 215 | { | 265 | { |
| 216 | struct mt_device *td = hid_get_drvdata(hdev); | 266 | struct mt_device *td = hid_get_drvdata(hdev); |
| 217 | struct mt_class *cls = td->mtclass; | 267 | struct mt_class *cls = &td->mtclass; |
| 218 | __s32 quirks = cls->quirks; | ||
| 219 | 268 | ||
| 220 | /* Only map fields from TouchScreen or TouchPad collections. | 269 | /* Only map fields from TouchScreen or TouchPad collections. |
| 221 | * We need to ignore fields that belong to other collections | 270 | * We need to ignore fields that belong to other collections |
| @@ -227,13 +276,17 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
| 227 | else | 276 | else |
| 228 | return 0; | 277 | return 0; |
| 229 | 278 | ||
| 279 | /* eGalax devices provide a Digitizer.Stylus input which overrides | ||
| 280 | * the correct Digitizers.Finger X/Y ranges. | ||
| 281 | * Let's just ignore this input. */ | ||
| 282 | if (field->physical == HID_DG_STYLUS) | ||
| 283 | return -1; | ||
| 284 | |||
| 230 | switch (usage->hid & HID_USAGE_PAGE) { | 285 | switch (usage->hid & HID_USAGE_PAGE) { |
| 231 | 286 | ||
| 232 | case HID_UP_GENDESK: | 287 | case HID_UP_GENDESK: |
| 233 | switch (usage->hid) { | 288 | switch (usage->hid) { |
| 234 | case HID_GD_X: | 289 | case HID_GD_X: |
| 235 | if (quirks & MT_QUIRK_EGALAX_XYZ_FIXUP) | ||
| 236 | field->logical_maximum = 32760; | ||
| 237 | hid_map_usage(hi, usage, bit, max, | 290 | hid_map_usage(hi, usage, bit, max, |
| 238 | EV_ABS, ABS_MT_POSITION_X); | 291 | EV_ABS, ABS_MT_POSITION_X); |
| 239 | set_abs(hi->input, ABS_MT_POSITION_X, field, | 292 | set_abs(hi->input, ABS_MT_POSITION_X, field, |
| @@ -246,8 +299,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
| 246 | } | 299 | } |
| 247 | return 1; | 300 | return 1; |
| 248 | case HID_GD_Y: | 301 | case HID_GD_Y: |
| 249 | if (quirks & MT_QUIRK_EGALAX_XYZ_FIXUP) | ||
| 250 | field->logical_maximum = 32760; | ||
| 251 | hid_map_usage(hi, usage, bit, max, | 302 | hid_map_usage(hi, usage, bit, max, |
| 252 | EV_ABS, ABS_MT_POSITION_Y); | 303 | EV_ABS, ABS_MT_POSITION_Y); |
| 253 | set_abs(hi->input, ABS_MT_POSITION_Y, field, | 304 | set_abs(hi->input, ABS_MT_POSITION_Y, field, |
| @@ -315,8 +366,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
| 315 | } | 366 | } |
| 316 | return 1; | 367 | return 1; |
| 317 | case HID_DG_TIPPRESSURE: | 368 | case HID_DG_TIPPRESSURE: |
| 318 | if (quirks & MT_QUIRK_EGALAX_XYZ_FIXUP) | ||
| 319 | field->logical_minimum = 0; | ||
| 320 | hid_map_usage(hi, usage, bit, max, | 369 | hid_map_usage(hi, usage, bit, max, |
| 321 | EV_ABS, ABS_MT_PRESSURE); | 370 | EV_ABS, ABS_MT_PRESSURE); |
| 322 | set_abs(hi->input, ABS_MT_PRESSURE, field, | 371 | set_abs(hi->input, ABS_MT_PRESSURE, field, |
| @@ -363,7 +412,7 @@ static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi, | |||
| 363 | 412 | ||
| 364 | static int mt_compute_slot(struct mt_device *td) | 413 | static int mt_compute_slot(struct mt_device *td) |
| 365 | { | 414 | { |
| 366 | __s32 quirks = td->mtclass->quirks; | 415 | __s32 quirks = td->mtclass.quirks; |
| 367 | 416 | ||
| 368 | if (quirks & MT_QUIRK_SLOT_IS_CONTACTID) | 417 | if (quirks & MT_QUIRK_SLOT_IS_CONTACTID) |
| 369 | return td->curdata.contactid; | 418 | return td->curdata.contactid; |
| @@ -407,7 +456,7 @@ static void mt_emit_event(struct mt_device *td, struct input_dev *input) | |||
| 407 | 456 | ||
| 408 | for (i = 0; i < td->maxcontacts; ++i) { | 457 | for (i = 0; i < td->maxcontacts; ++i) { |
| 409 | struct mt_slot *s = &(td->slots[i]); | 458 | struct mt_slot *s = &(td->slots[i]); |
| 410 | if ((td->mtclass->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP) && | 459 | if ((td->mtclass.quirks & MT_QUIRK_NOT_SEEN_MEANS_UP) && |
| 411 | !s->seen_in_this_frame) { | 460 | !s->seen_in_this_frame) { |
| 412 | s->touch_state = false; | 461 | s->touch_state = false; |
| 413 | } | 462 | } |
| @@ -444,7 +493,7 @@ static int mt_event(struct hid_device *hid, struct hid_field *field, | |||
| 444 | struct hid_usage *usage, __s32 value) | 493 | struct hid_usage *usage, __s32 value) |
| 445 | { | 494 | { |
| 446 | struct mt_device *td = hid_get_drvdata(hid); | 495 | struct mt_device *td = hid_get_drvdata(hid); |
| 447 | __s32 quirks = td->mtclass->quirks; | 496 | __s32 quirks = td->mtclass.quirks; |
| 448 | 497 | ||
| 449 | if (hid->claimed & HID_CLAIMED_INPUT && td->slots) { | 498 | if (hid->claimed & HID_CLAIMED_INPUT && td->slots) { |
| 450 | switch (usage->hid) { | 499 | switch (usage->hid) { |
| @@ -552,7 +601,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
| 552 | dev_err(&hdev->dev, "cannot allocate multitouch data\n"); | 601 | dev_err(&hdev->dev, "cannot allocate multitouch data\n"); |
| 553 | return -ENOMEM; | 602 | return -ENOMEM; |
| 554 | } | 603 | } |
| 555 | td->mtclass = mtclass; | 604 | td->mtclass = *mtclass; |
| 556 | td->inputmode = -1; | 605 | td->inputmode = -1; |
| 557 | td->last_mt_collection = -1; | 606 | td->last_mt_collection = -1; |
| 558 | hid_set_drvdata(hdev, td); | 607 | hid_set_drvdata(hdev, td); |
| @@ -574,6 +623,8 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
| 574 | goto fail; | 623 | goto fail; |
| 575 | } | 624 | } |
| 576 | 625 | ||
| 626 | ret = sysfs_create_group(&hdev->dev.kobj, &mt_attribute_group); | ||
| 627 | |||
| 577 | mt_set_input_mode(hdev); | 628 | mt_set_input_mode(hdev); |
| 578 | 629 | ||
| 579 | return 0; | 630 | return 0; |
| @@ -594,6 +645,7 @@ static int mt_reset_resume(struct hid_device *hdev) | |||
| 594 | static void mt_remove(struct hid_device *hdev) | 645 | static void mt_remove(struct hid_device *hdev) |
| 595 | { | 646 | { |
| 596 | struct mt_device *td = hid_get_drvdata(hdev); | 647 | struct mt_device *td = hid_get_drvdata(hdev); |
| 648 | sysfs_remove_group(&hdev->dev.kobj, &mt_attribute_group); | ||
| 597 | hid_hw_stop(hdev); | 649 | hid_hw_stop(hdev); |
| 598 | kfree(td->slots); | 650 | kfree(td->slots); |
| 599 | kfree(td); | 651 | kfree(td); |
| @@ -609,12 +661,20 @@ static const struct hid_device_id mt_devices[] = { | |||
| 609 | { .driver_data = MT_CLS_3M, | 661 | { .driver_data = MT_CLS_3M, |
| 610 | HID_USB_DEVICE(USB_VENDOR_ID_3M, | 662 | HID_USB_DEVICE(USB_VENDOR_ID_3M, |
| 611 | USB_DEVICE_ID_3M2256) }, | 663 | USB_DEVICE_ID_3M2256) }, |
| 664 | { .driver_data = MT_CLS_3M, | ||
| 665 | HID_USB_DEVICE(USB_VENDOR_ID_3M, | ||
| 666 | USB_DEVICE_ID_3M3266) }, | ||
| 612 | 667 | ||
| 613 | /* ActionStar panels */ | 668 | /* ActionStar panels */ |
| 614 | { .driver_data = MT_CLS_DEFAULT, | 669 | { .driver_data = MT_CLS_DEFAULT, |
| 615 | HID_USB_DEVICE(USB_VENDOR_ID_ACTIONSTAR, | 670 | HID_USB_DEVICE(USB_VENDOR_ID_ACTIONSTAR, |
| 616 | USB_DEVICE_ID_ACTIONSTAR_1011) }, | 671 | USB_DEVICE_ID_ACTIONSTAR_1011) }, |
| 617 | 672 | ||
| 673 | /* Atmel panels */ | ||
| 674 | { .driver_data = MT_CLS_SERIAL, | ||
| 675 | HID_USB_DEVICE(USB_VENDOR_ID_ATMEL, | ||
| 676 | USB_DEVICE_ID_ATMEL_MULTITOUCH) }, | ||
| 677 | |||
| 618 | /* Cando panels */ | 678 | /* Cando panels */ |
| 619 | { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER, | 679 | { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER, |
| 620 | HID_USB_DEVICE(USB_VENDOR_ID_CANDO, | 680 | HID_USB_DEVICE(USB_VENDOR_ID_CANDO, |
| @@ -645,23 +705,32 @@ static const struct hid_device_id mt_devices[] = { | |||
| 645 | USB_DEVICE_ID_CYPRESS_TRUETOUCH) }, | 705 | USB_DEVICE_ID_CYPRESS_TRUETOUCH) }, |
| 646 | 706 | ||
| 647 | /* eGalax devices (resistive) */ | 707 | /* eGalax devices (resistive) */ |
| 648 | { .driver_data = MT_CLS_EGALAX, | 708 | { .driver_data = MT_CLS_EGALAX, |
| 649 | HID_USB_DEVICE(USB_VENDOR_ID_DWAV, | 709 | HID_USB_DEVICE(USB_VENDOR_ID_DWAV, |
| 650 | USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH) }, | 710 | USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480D) }, |
| 651 | { .driver_data = MT_CLS_EGALAX, | 711 | { .driver_data = MT_CLS_EGALAX, |
| 652 | HID_USB_DEVICE(USB_VENDOR_ID_DWAV, | 712 | HID_USB_DEVICE(USB_VENDOR_ID_DWAV, |
| 653 | USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH3) }, | 713 | USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480E) }, |
| 654 | 714 | ||
| 655 | /* eGalax devices (capacitive) */ | 715 | /* eGalax devices (capacitive) */ |
| 656 | { .driver_data = MT_CLS_EGALAX, | 716 | { .driver_data = MT_CLS_EGALAX, |
| 657 | HID_USB_DEVICE(USB_VENDOR_ID_DWAV, | 717 | HID_USB_DEVICE(USB_VENDOR_ID_DWAV, |
| 658 | USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1) }, | 718 | USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_720C) }, |
| 659 | { .driver_data = MT_CLS_EGALAX, | 719 | { .driver_data = MT_CLS_EGALAX, |
| 660 | HID_USB_DEVICE(USB_VENDOR_ID_DWAV, | 720 | HID_USB_DEVICE(USB_VENDOR_ID_DWAV, |
| 661 | USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH2) }, | 721 | USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_726B) }, |
| 662 | { .driver_data = MT_CLS_EGALAX, | 722 | { .driver_data = MT_CLS_EGALAX, |
| 663 | HID_USB_DEVICE(USB_VENDOR_ID_DWAV, | 723 | HID_USB_DEVICE(USB_VENDOR_ID_DWAV, |
| 664 | USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH4) }, | 724 | USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72A1) }, |
| 725 | { .driver_data = MT_CLS_EGALAX, | ||
| 726 | HID_USB_DEVICE(USB_VENDOR_ID_DWAV, | ||
| 727 | USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72FA) }, | ||
| 728 | { .driver_data = MT_CLS_EGALAX, | ||
| 729 | HID_USB_DEVICE(USB_VENDOR_ID_DWAV, | ||
| 730 | USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7302) }, | ||
| 731 | { .driver_data = MT_CLS_EGALAX_SERIAL, | ||
| 732 | HID_USB_DEVICE(USB_VENDOR_ID_DWAV, | ||
| 733 | USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001) }, | ||
| 665 | 734 | ||
| 666 | /* Elo TouchSystems IntelliTouch Plus panel */ | 735 | /* Elo TouchSystems IntelliTouch Plus panel */ |
| 667 | { .driver_data = MT_CLS_DUAL_NSMU_CONTACTID, | 736 | { .driver_data = MT_CLS_DUAL_NSMU_CONTACTID, |
| @@ -678,6 +747,11 @@ static const struct hid_device_id mt_devices[] = { | |||
| 678 | HID_USB_DEVICE(USB_VENDOR_ID_GOODTOUCH, | 747 | HID_USB_DEVICE(USB_VENDOR_ID_GOODTOUCH, |
| 679 | USB_DEVICE_ID_GOODTOUCH_000f) }, | 748 | USB_DEVICE_ID_GOODTOUCH_000f) }, |
| 680 | 749 | ||
| 750 | /* Hanvon panels */ | ||
| 751 | { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID, | ||
| 752 | HID_USB_DEVICE(USB_VENDOR_ID_HANVON_ALT, | ||
| 753 | USB_DEVICE_ID_HANVON_ALT_MULTITOUCH) }, | ||
| 754 | |||
| 681 | /* Ideacom panel */ | 755 | /* Ideacom panel */ |
| 682 | { .driver_data = MT_CLS_SERIAL, | 756 | { .driver_data = MT_CLS_SERIAL, |
| 683 | HID_USB_DEVICE(USB_VENDOR_ID_IDEACOM, | 757 | HID_USB_DEVICE(USB_VENDOR_ID_IDEACOM, |
| @@ -722,6 +796,17 @@ static const struct hid_device_id mt_devices[] = { | |||
| 722 | HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, | 796 | HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, |
| 723 | USB_DEVICE_ID_PENMOUNT_PCI) }, | 797 | USB_DEVICE_ID_PENMOUNT_PCI) }, |
| 724 | 798 | ||
| 799 | /* PixArt optical touch screen */ | ||
| 800 | { .driver_data = MT_CLS_INRANGE_CONTACTNUMBER, | ||
| 801 | HID_USB_DEVICE(USB_VENDOR_ID_PIXART, | ||
| 802 | USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN) }, | ||
| 803 | { .driver_data = MT_CLS_INRANGE_CONTACTNUMBER, | ||
| 804 | HID_USB_DEVICE(USB_VENDOR_ID_PIXART, | ||
| 805 | USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1) }, | ||
| 806 | { .driver_data = MT_CLS_INRANGE_CONTACTNUMBER, | ||
| 807 | HID_USB_DEVICE(USB_VENDOR_ID_PIXART, | ||
| 808 | USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2) }, | ||
| 809 | |||
| 725 | /* PixCir-based panels */ | 810 | /* PixCir-based panels */ |
| 726 | { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID, | 811 | { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID, |
| 727 | HID_USB_DEVICE(USB_VENDOR_ID_HANVON, | 812 | HID_USB_DEVICE(USB_VENDOR_ID_HANVON, |
| @@ -730,6 +815,17 @@ static const struct hid_device_id mt_devices[] = { | |||
| 730 | HID_USB_DEVICE(USB_VENDOR_ID_CANDO, | 815 | HID_USB_DEVICE(USB_VENDOR_ID_CANDO, |
| 731 | USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) }, | 816 | USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) }, |
| 732 | 817 | ||
| 818 | /* Quanta-based panels */ | ||
| 819 | { .driver_data = MT_CLS_CONFIDENCE_CONTACT_ID, | ||
| 820 | HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, | ||
| 821 | USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) }, | ||
| 822 | { .driver_data = MT_CLS_CONFIDENCE_CONTACT_ID, | ||
| 823 | HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, | ||
| 824 | USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001) }, | ||
| 825 | { .driver_data = MT_CLS_CONFIDENCE_CONTACT_ID, | ||
| 826 | HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, | ||
| 827 | USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008) }, | ||
| 828 | |||
| 733 | /* Stantum panels */ | 829 | /* Stantum panels */ |
| 734 | { .driver_data = MT_CLS_CONFIDENCE, | 830 | { .driver_data = MT_CLS_CONFIDENCE, |
| 735 | HID_USB_DEVICE(USB_VENDOR_ID_STANTUM, | 831 | HID_USB_DEVICE(USB_VENDOR_ID_STANTUM, |
| @@ -758,6 +854,35 @@ static const struct hid_device_id mt_devices[] = { | |||
| 758 | HID_USB_DEVICE(USB_VENDOR_ID_XAT, | 854 | HID_USB_DEVICE(USB_VENDOR_ID_XAT, |
| 759 | USB_DEVICE_ID_XAT_CSR) }, | 855 | USB_DEVICE_ID_XAT_CSR) }, |
| 760 | 856 | ||
| 857 | /* Xiroku */ | ||
| 858 | { .driver_data = MT_CLS_DEFAULT, | ||
| 859 | HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, | ||
| 860 | USB_DEVICE_ID_XIROKU_SPX) }, | ||
| 861 | { .driver_data = MT_CLS_DEFAULT, | ||
| 862 | HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, | ||
| 863 | USB_DEVICE_ID_XIROKU_MPX) }, | ||
| 864 | { .driver_data = MT_CLS_DEFAULT, | ||
| 865 | HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, | ||
| 866 | USB_DEVICE_ID_XIROKU_CSR) }, | ||
| 867 | { .driver_data = MT_CLS_DEFAULT, | ||
| 868 | HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, | ||
| 869 | USB_DEVICE_ID_XIROKU_SPX1) }, | ||
| 870 | { .driver_data = MT_CLS_DEFAULT, | ||
| 871 | HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, | ||
| 872 | USB_DEVICE_ID_XIROKU_MPX1) }, | ||
| 873 | { .driver_data = MT_CLS_DEFAULT, | ||
| 874 | HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, | ||
| 875 | USB_DEVICE_ID_XIROKU_CSR1) }, | ||
| 876 | { .driver_data = MT_CLS_DEFAULT, | ||
| 877 | HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, | ||
| 878 | USB_DEVICE_ID_XIROKU_SPX2) }, | ||
| 879 | { .driver_data = MT_CLS_DEFAULT, | ||
| 880 | HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, | ||
| 881 | USB_DEVICE_ID_XIROKU_MPX2) }, | ||
| 882 | { .driver_data = MT_CLS_DEFAULT, | ||
| 883 | HID_USB_DEVICE(USB_VENDOR_ID_XIROKU, | ||
| 884 | USB_DEVICE_ID_XIROKU_CSR2) }, | ||
| 885 | |||
| 761 | { } | 886 | { } |
| 762 | }; | 887 | }; |
| 763 | MODULE_DEVICE_TABLE(hid, mt_devices); | 888 | MODULE_DEVICE_TABLE(hid, mt_devices); |
diff --git a/drivers/hid/hid-picolcd.c b/drivers/hid/hid-picolcd.c index 01e7d2cd7c26..12f9777c385d 100644 --- a/drivers/hid/hid-picolcd.c +++ b/drivers/hid/hid-picolcd.c | |||
| @@ -633,7 +633,7 @@ struct picolcd_fb_cleanup_item { | |||
| 633 | struct picolcd_fb_cleanup_item *next; | 633 | struct picolcd_fb_cleanup_item *next; |
| 634 | }; | 634 | }; |
| 635 | static struct picolcd_fb_cleanup_item *fb_pending; | 635 | static struct picolcd_fb_cleanup_item *fb_pending; |
| 636 | DEFINE_SPINLOCK(fb_pending_lock); | 636 | static DEFINE_SPINLOCK(fb_pending_lock); |
| 637 | 637 | ||
| 638 | static void picolcd_fb_do_cleanup(struct work_struct *data) | 638 | static void picolcd_fb_do_cleanup(struct work_struct *data) |
| 639 | { | 639 | { |
| @@ -658,7 +658,7 @@ static void picolcd_fb_do_cleanup(struct work_struct *data) | |||
| 658 | } while (item); | 658 | } while (item); |
| 659 | } | 659 | } |
| 660 | 660 | ||
| 661 | DECLARE_WORK(picolcd_fb_cleanup, picolcd_fb_do_cleanup); | 661 | static DECLARE_WORK(picolcd_fb_cleanup, picolcd_fb_do_cleanup); |
| 662 | 662 | ||
| 663 | static int picolcd_fb_open(struct fb_info *info, int u) | 663 | static int picolcd_fb_open(struct fb_info *info, int u) |
| 664 | { | 664 | { |
diff --git a/drivers/hid/hid-quanta.c b/drivers/hid/hid-quanta.c deleted file mode 100644 index 87a54df4d4ac..000000000000 --- a/drivers/hid/hid-quanta.c +++ /dev/null | |||
| @@ -1,261 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * HID driver for Quanta Optical Touch dual-touch panels | ||
| 3 | * | ||
| 4 | * Copyright (c) 2009-2010 Stephane Chatty <chatty@enac.fr> | ||
| 5 | * | ||
| 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 <linux/device.h> | ||
| 16 | #include <linux/hid.h> | ||
| 17 | #include <linux/module.h> | ||
| 18 | #include <linux/slab.h> | ||
| 19 | |||
| 20 | MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>"); | ||
| 21 | MODULE_DESCRIPTION("Quanta dual-touch panel"); | ||
| 22 | MODULE_LICENSE("GPL"); | ||
| 23 | |||
| 24 | #include "hid-ids.h" | ||
| 25 | |||
| 26 | struct quanta_data { | ||
| 27 | __u16 x, y; | ||
| 28 | __u8 id; | ||
| 29 | bool valid; /* valid finger data, or just placeholder? */ | ||
| 30 | bool first; /* is this the first finger in this frame? */ | ||
| 31 | bool activity_now; /* at least one active finger in this frame? */ | ||
| 32 | bool activity; /* at least one active finger previously? */ | ||
| 33 | }; | ||
| 34 | |||
| 35 | static int quanta_input_mapping(struct hid_device *hdev, struct hid_input *hi, | ||
| 36 | struct hid_field *field, struct hid_usage *usage, | ||
| 37 | unsigned long **bit, int *max) | ||
| 38 | { | ||
| 39 | switch (usage->hid & HID_USAGE_PAGE) { | ||
| 40 | |||
| 41 | case HID_UP_GENDESK: | ||
| 42 | switch (usage->hid) { | ||
| 43 | case HID_GD_X: | ||
| 44 | hid_map_usage(hi, usage, bit, max, | ||
| 45 | EV_ABS, ABS_MT_POSITION_X); | ||
| 46 | /* touchscreen emulation */ | ||
| 47 | input_set_abs_params(hi->input, ABS_X, | ||
| 48 | field->logical_minimum, | ||
| 49 | field->logical_maximum, 0, 0); | ||
| 50 | return 1; | ||
| 51 | case HID_GD_Y: | ||
| 52 | hid_map_usage(hi, usage, bit, max, | ||
| 53 | EV_ABS, ABS_MT_POSITION_Y); | ||
| 54 | /* touchscreen emulation */ | ||
| 55 | input_set_abs_params(hi->input, ABS_Y, | ||
| 56 | field->logical_minimum, | ||
| 57 | field->logical_maximum, 0, 0); | ||
| 58 | return 1; | ||
| 59 | } | ||
| 60 | return 0; | ||
| 61 | |||
| 62 | case HID_UP_DIGITIZER: | ||
| 63 | switch (usage->hid) { | ||
| 64 | case HID_DG_CONFIDENCE: | ||
| 65 | case HID_DG_TIPSWITCH: | ||
| 66 | case HID_DG_INPUTMODE: | ||
| 67 | case HID_DG_DEVICEINDEX: | ||
| 68 | case HID_DG_CONTACTCOUNT: | ||
| 69 | case HID_DG_CONTACTMAX: | ||
| 70 | case HID_DG_TIPPRESSURE: | ||
| 71 | case HID_DG_WIDTH: | ||
| 72 | case HID_DG_HEIGHT: | ||
| 73 | return -1; | ||
| 74 | case HID_DG_INRANGE: | ||
| 75 | /* touchscreen emulation */ | ||
| 76 | hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); | ||
| 77 | return 1; | ||
| 78 | case HID_DG_CONTACTID: | ||
| 79 | hid_map_usage(hi, usage, bit, max, | ||
| 80 | EV_ABS, ABS_MT_TRACKING_ID); | ||
| 81 | return 1; | ||
| 82 | } | ||
| 83 | return 0; | ||
| 84 | |||
| 85 | case 0xff000000: | ||
| 86 | /* ignore vendor-specific features */ | ||
| 87 | return -1; | ||
| 88 | } | ||
| 89 | |||
| 90 | return 0; | ||
| 91 | } | ||
| 92 | |||
| 93 | static int quanta_input_mapped(struct hid_device *hdev, struct hid_input *hi, | ||
| 94 | struct hid_field *field, struct hid_usage *usage, | ||
| 95 | unsigned long **bit, int *max) | ||
| 96 | { | ||
| 97 | if (usage->type == EV_KEY || usage->type == EV_ABS) | ||
| 98 | clear_bit(usage->code, *bit); | ||
| 99 | |||
| 100 | return 0; | ||
| 101 | } | ||
| 102 | |||
| 103 | /* | ||
| 104 | * this function is called when a whole finger has been parsed, | ||
| 105 | * so that it can decide what to send to the input layer. | ||
| 106 | */ | ||
| 107 | static void quanta_filter_event(struct quanta_data *td, struct input_dev *input) | ||
| 108 | { | ||
| 109 | |||
| 110 | td->first = !td->first; /* touchscreen emulation */ | ||
| 111 | |||
| 112 | if (!td->valid) { | ||
| 113 | /* | ||
| 114 | * touchscreen emulation: if no finger in this frame is valid | ||
| 115 | * and there previously was finger activity, this is a release | ||
| 116 | */ | ||
| 117 | if (!td->first && !td->activity_now && td->activity) { | ||
| 118 | input_event(input, EV_KEY, BTN_TOUCH, 0); | ||
| 119 | td->activity = false; | ||
| 120 | } | ||
| 121 | return; | ||
| 122 | } | ||
| 123 | |||
| 124 | input_event(input, EV_ABS, ABS_MT_TRACKING_ID, td->id); | ||
| 125 | input_event(input, EV_ABS, ABS_MT_POSITION_X, td->x); | ||
| 126 | input_event(input, EV_ABS, ABS_MT_POSITION_Y, td->y); | ||
| 127 | |||
| 128 | input_mt_sync(input); | ||
| 129 | td->valid = false; | ||
| 130 | |||
| 131 | /* touchscreen emulation: if first active finger in this frame... */ | ||
| 132 | if (!td->activity_now) { | ||
| 133 | /* if there was no previous activity, emit touch event */ | ||
| 134 | if (!td->activity) { | ||
| 135 | input_event(input, EV_KEY, BTN_TOUCH, 1); | ||
| 136 | td->activity = true; | ||
| 137 | } | ||
| 138 | td->activity_now = true; | ||
| 139 | /* and in any case this is our preferred finger */ | ||
| 140 | input_event(input, EV_ABS, ABS_X, td->x); | ||
| 141 | input_event(input, EV_ABS, ABS_Y, td->y); | ||
| 142 | } | ||
| 143 | } | ||
| 144 | |||
| 145 | |||
| 146 | static int quanta_event(struct hid_device *hid, struct hid_field *field, | ||
| 147 | struct hid_usage *usage, __s32 value) | ||
| 148 | { | ||
| 149 | struct quanta_data *td = hid_get_drvdata(hid); | ||
| 150 | |||
| 151 | if (hid->claimed & HID_CLAIMED_INPUT) { | ||
| 152 | struct input_dev *input = field->hidinput->input; | ||
| 153 | |||
| 154 | switch (usage->hid) { | ||
| 155 | case HID_DG_INRANGE: | ||
| 156 | td->valid = !!value; | ||
| 157 | break; | ||
| 158 | case HID_GD_X: | ||
| 159 | td->x = value; | ||
| 160 | break; | ||
| 161 | case HID_GD_Y: | ||
| 162 | td->y = value; | ||
| 163 | quanta_filter_event(td, input); | ||
| 164 | break; | ||
| 165 | case HID_DG_CONTACTID: | ||
| 166 | td->id = value; | ||
| 167 | break; | ||
| 168 | case HID_DG_CONTACTCOUNT: | ||
| 169 | /* touch emulation: this is the last field in a frame */ | ||
| 170 | td->first = false; | ||
| 171 | td->activity_now = false; | ||
| 172 | break; | ||
| 173 | case HID_DG_CONFIDENCE: | ||
| 174 | case HID_DG_TIPSWITCH: | ||
| 175 | /* avoid interference from generic hidinput handling */ | ||
| 176 | break; | ||
| 177 | |||
| 178 | default: | ||
| 179 | /* fallback to the generic hidinput handling */ | ||
| 180 | return 0; | ||
| 181 | } | ||
| 182 | } | ||
| 183 | |||
| 184 | /* we have handled the hidinput part, now remains hiddev */ | ||
| 185 | if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event) | ||
| 186 | hid->hiddev_hid_event(hid, field, usage, value); | ||
| 187 | |||
| 188 | return 1; | ||
| 189 | } | ||
| 190 | |||
| 191 | static int quanta_probe(struct hid_device *hdev, const struct hid_device_id *id) | ||
| 192 | { | ||
| 193 | int ret; | ||
| 194 | struct quanta_data *td; | ||
| 195 | |||
| 196 | td = kmalloc(sizeof(struct quanta_data), GFP_KERNEL); | ||
| 197 | if (!td) { | ||
| 198 | hid_err(hdev, "cannot allocate Quanta Touch data\n"); | ||
| 199 | return -ENOMEM; | ||
| 200 | } | ||
| 201 | td->valid = false; | ||
| 202 | td->activity = false; | ||
| 203 | td->activity_now = false; | ||
| 204 | td->first = false; | ||
| 205 | hid_set_drvdata(hdev, td); | ||
| 206 | |||
| 207 | ret = hid_parse(hdev); | ||
| 208 | if (!ret) | ||
| 209 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); | ||
| 210 | |||
| 211 | if (ret) | ||
| 212 | kfree(td); | ||
| 213 | |||
| 214 | return ret; | ||
| 215 | } | ||
| 216 | |||
| 217 | static void quanta_remove(struct hid_device *hdev) | ||
| 218 | { | ||
| 219 | hid_hw_stop(hdev); | ||
| 220 | kfree(hid_get_drvdata(hdev)); | ||
| 221 | hid_set_drvdata(hdev, NULL); | ||
| 222 | } | ||
| 223 | |||
| 224 | static const struct hid_device_id quanta_devices[] = { | ||
| 225 | { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, | ||
| 226 | USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) }, | ||
| 227 | { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, | ||
| 228 | USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN) }, | ||
| 229 | { } | ||
| 230 | }; | ||
| 231 | MODULE_DEVICE_TABLE(hid, quanta_devices); | ||
| 232 | |||
| 233 | static const struct hid_usage_id quanta_grabbed_usages[] = { | ||
| 234 | { HID_ANY_ID, HID_ANY_ID, HID_ANY_ID }, | ||
| 235 | { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1} | ||
| 236 | }; | ||
| 237 | |||
| 238 | static struct hid_driver quanta_driver = { | ||
| 239 | .name = "quanta-touch", | ||
| 240 | .id_table = quanta_devices, | ||
| 241 | .probe = quanta_probe, | ||
| 242 | .remove = quanta_remove, | ||
| 243 | .input_mapping = quanta_input_mapping, | ||
| 244 | .input_mapped = quanta_input_mapped, | ||
| 245 | .usage_table = quanta_grabbed_usages, | ||
| 246 | .event = quanta_event, | ||
| 247 | }; | ||
| 248 | |||
| 249 | static int __init quanta_init(void) | ||
| 250 | { | ||
| 251 | return hid_register_driver(&quanta_driver); | ||
| 252 | } | ||
| 253 | |||
| 254 | static void __exit quanta_exit(void) | ||
| 255 | { | ||
| 256 | hid_unregister_driver(&quanta_driver); | ||
| 257 | } | ||
| 258 | |||
| 259 | module_init(quanta_init); | ||
| 260 | module_exit(quanta_exit); | ||
| 261 | |||
diff --git a/drivers/hid/hid-roccat-common.c b/drivers/hid/hid-roccat-common.c index b07e7f96a358..a6d93992c75a 100644 --- a/drivers/hid/hid-roccat-common.c +++ b/drivers/hid/hid-roccat-common.c | |||
| @@ -49,12 +49,10 @@ int roccat_common_send(struct usb_device *usb_dev, uint report_id, | |||
| 49 | char *buf; | 49 | char *buf; |
| 50 | int len; | 50 | int len; |
| 51 | 51 | ||
| 52 | buf = kmalloc(size, GFP_KERNEL); | 52 | buf = kmemdup(data, size, GFP_KERNEL); |
| 53 | if (buf == NULL) | 53 | if (buf == NULL) |
| 54 | return -ENOMEM; | 54 | return -ENOMEM; |
| 55 | 55 | ||
| 56 | memcpy(buf, data, size); | ||
| 57 | |||
| 58 | len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), | 56 | len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), |
| 59 | HID_REQ_SET_REPORT, | 57 | HID_REQ_SET_REPORT, |
| 60 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, | 58 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, |
diff --git a/drivers/hid/hid-roccat-isku.c b/drivers/hid/hid-roccat-isku.c new file mode 100644 index 000000000000..0e4a0ab47142 --- /dev/null +++ b/drivers/hid/hid-roccat-isku.c | |||
| @@ -0,0 +1,487 @@ | |||
| 1 | /* | ||
| 2 | * Roccat Isku driver for Linux | ||
| 3 | * | ||
| 4 | * Copyright (c) 2011 Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 5 | */ | ||
| 6 | |||
| 7 | /* | ||
| 8 | * This program is free software; you can redistribute it and/or modify it | ||
| 9 | * under the terms of the GNU General Public License as published by the Free | ||
| 10 | * Software Foundation; either version 2 of the License, or (at your option) | ||
| 11 | * any later version. | ||
| 12 | */ | ||
| 13 | |||
| 14 | /* | ||
| 15 | * Roccat Isku is a gamer keyboard with macro keys that can be configured in | ||
| 16 | * 5 profiles. | ||
| 17 | */ | ||
| 18 | |||
| 19 | #include <linux/device.h> | ||
| 20 | #include <linux/input.h> | ||
| 21 | #include <linux/hid.h> | ||
| 22 | #include <linux/module.h> | ||
| 23 | #include <linux/slab.h> | ||
| 24 | #include <linux/hid-roccat.h> | ||
| 25 | #include "hid-ids.h" | ||
| 26 | #include "hid-roccat-common.h" | ||
| 27 | #include "hid-roccat-isku.h" | ||
| 28 | |||
| 29 | static struct class *isku_class; | ||
| 30 | |||
| 31 | static void isku_profile_activated(struct isku_device *isku, uint new_profile) | ||
| 32 | { | ||
| 33 | isku->actual_profile = new_profile; | ||
| 34 | } | ||
| 35 | |||
| 36 | static int isku_receive(struct usb_device *usb_dev, uint command, | ||
| 37 | void *buf, uint size) | ||
| 38 | { | ||
| 39 | return roccat_common_receive(usb_dev, command, buf, size); | ||
| 40 | } | ||
| 41 | |||
| 42 | static int isku_receive_control_status(struct usb_device *usb_dev) | ||
| 43 | { | ||
| 44 | int retval; | ||
| 45 | struct isku_control control; | ||
| 46 | |||
| 47 | do { | ||
| 48 | msleep(50); | ||
| 49 | retval = isku_receive(usb_dev, ISKU_COMMAND_CONTROL, | ||
| 50 | &control, sizeof(struct isku_control)); | ||
| 51 | |||
| 52 | if (retval) | ||
| 53 | return retval; | ||
| 54 | |||
| 55 | switch (control.value) { | ||
| 56 | case ISKU_CONTROL_VALUE_STATUS_OK: | ||
| 57 | return 0; | ||
| 58 | case ISKU_CONTROL_VALUE_STATUS_WAIT: | ||
| 59 | continue; | ||
| 60 | case ISKU_CONTROL_VALUE_STATUS_INVALID: | ||
| 61 | /* seems to be critical - replug necessary */ | ||
| 62 | case ISKU_CONTROL_VALUE_STATUS_OVERLOAD: | ||
| 63 | return -EINVAL; | ||
| 64 | default: | ||
| 65 | hid_err(usb_dev, "isku_receive_control_status: " | ||
| 66 | "unknown response value 0x%x\n", | ||
| 67 | control.value); | ||
| 68 | return -EINVAL; | ||
| 69 | } | ||
| 70 | |||
| 71 | } while (1); | ||
| 72 | } | ||
| 73 | |||
| 74 | static int isku_send(struct usb_device *usb_dev, uint command, | ||
| 75 | void const *buf, uint size) | ||
| 76 | { | ||
| 77 | int retval; | ||
| 78 | |||
| 79 | retval = roccat_common_send(usb_dev, command, buf, size); | ||
| 80 | if (retval) | ||
| 81 | return retval; | ||
| 82 | |||
| 83 | return isku_receive_control_status(usb_dev); | ||
| 84 | } | ||
| 85 | |||
| 86 | static int isku_get_actual_profile(struct usb_device *usb_dev) | ||
| 87 | { | ||
| 88 | struct isku_actual_profile buf; | ||
| 89 | int retval; | ||
| 90 | |||
| 91 | retval = isku_receive(usb_dev, ISKU_COMMAND_ACTUAL_PROFILE, | ||
| 92 | &buf, sizeof(struct isku_actual_profile)); | ||
| 93 | return retval ? retval : buf.actual_profile; | ||
| 94 | } | ||
| 95 | |||
| 96 | static int isku_set_actual_profile(struct usb_device *usb_dev, int new_profile) | ||
| 97 | { | ||
| 98 | struct isku_actual_profile buf; | ||
| 99 | |||
| 100 | buf.command = ISKU_COMMAND_ACTUAL_PROFILE; | ||
| 101 | buf.size = sizeof(struct isku_actual_profile); | ||
| 102 | buf.actual_profile = new_profile; | ||
| 103 | return isku_send(usb_dev, ISKU_COMMAND_ACTUAL_PROFILE, &buf, | ||
| 104 | sizeof(struct isku_actual_profile)); | ||
| 105 | } | ||
| 106 | |||
| 107 | static ssize_t isku_sysfs_show_actual_profile(struct device *dev, | ||
| 108 | struct device_attribute *attr, char *buf) | ||
| 109 | { | ||
| 110 | struct isku_device *isku = | ||
| 111 | hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); | ||
| 112 | return snprintf(buf, PAGE_SIZE, "%d\n", isku->actual_profile); | ||
| 113 | } | ||
| 114 | |||
| 115 | static ssize_t isku_sysfs_set_actual_profile(struct device *dev, | ||
| 116 | struct device_attribute *attr, char const *buf, size_t size) | ||
| 117 | { | ||
| 118 | struct isku_device *isku; | ||
| 119 | struct usb_device *usb_dev; | ||
| 120 | unsigned long profile; | ||
| 121 | int retval; | ||
| 122 | struct isku_roccat_report roccat_report; | ||
| 123 | |||
| 124 | dev = dev->parent->parent; | ||
| 125 | isku = hid_get_drvdata(dev_get_drvdata(dev)); | ||
| 126 | usb_dev = interface_to_usbdev(to_usb_interface(dev)); | ||
| 127 | |||
| 128 | retval = strict_strtoul(buf, 10, &profile); | ||
| 129 | if (retval) | ||
| 130 | return retval; | ||
| 131 | |||
| 132 | if (profile > 4) | ||
| 133 | return -EINVAL; | ||
| 134 | |||
| 135 | mutex_lock(&isku->isku_lock); | ||
| 136 | |||
| 137 | retval = isku_set_actual_profile(usb_dev, profile); | ||
| 138 | if (retval) { | ||
| 139 | mutex_unlock(&isku->isku_lock); | ||
| 140 | return retval; | ||
| 141 | } | ||
| 142 | |||
| 143 | isku_profile_activated(isku, profile); | ||
| 144 | |||
| 145 | roccat_report.event = ISKU_REPORT_BUTTON_EVENT_PROFILE; | ||
| 146 | roccat_report.data1 = profile + 1; | ||
| 147 | roccat_report.data2 = 0; | ||
| 148 | roccat_report.profile = profile + 1; | ||
| 149 | roccat_report_event(isku->chrdev_minor, (uint8_t const *)&roccat_report); | ||
| 150 | |||
| 151 | mutex_unlock(&isku->isku_lock); | ||
| 152 | |||
| 153 | return size; | ||
| 154 | } | ||
| 155 | |||
| 156 | static struct device_attribute isku_attributes[] = { | ||
| 157 | __ATTR(actual_profile, 0660, | ||
| 158 | isku_sysfs_show_actual_profile, | ||
| 159 | isku_sysfs_set_actual_profile), | ||
| 160 | __ATTR_NULL | ||
| 161 | }; | ||
| 162 | |||
| 163 | static ssize_t isku_sysfs_read(struct file *fp, struct kobject *kobj, | ||
| 164 | char *buf, loff_t off, size_t count, | ||
| 165 | size_t real_size, uint command) | ||
| 166 | { | ||
| 167 | struct device *dev = | ||
| 168 | container_of(kobj, struct device, kobj)->parent->parent; | ||
| 169 | struct isku_device *isku = hid_get_drvdata(dev_get_drvdata(dev)); | ||
| 170 | struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); | ||
| 171 | int retval; | ||
| 172 | |||
| 173 | if (off >= real_size) | ||
| 174 | return 0; | ||
| 175 | |||
| 176 | if (off != 0 || count != real_size) | ||
| 177 | return -EINVAL; | ||
| 178 | |||
| 179 | mutex_lock(&isku->isku_lock); | ||
| 180 | retval = isku_receive(usb_dev, command, buf, real_size); | ||
| 181 | mutex_unlock(&isku->isku_lock); | ||
| 182 | |||
| 183 | return retval ? retval : real_size; | ||
| 184 | } | ||
| 185 | |||
| 186 | static ssize_t isku_sysfs_write(struct file *fp, struct kobject *kobj, | ||
| 187 | void const *buf, loff_t off, size_t count, | ||
| 188 | size_t real_size, uint command) | ||
| 189 | { | ||
| 190 | struct device *dev = | ||
| 191 | container_of(kobj, struct device, kobj)->parent->parent; | ||
| 192 | struct isku_device *isku = hid_get_drvdata(dev_get_drvdata(dev)); | ||
| 193 | struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); | ||
| 194 | int retval; | ||
| 195 | |||
| 196 | if (off != 0 || count != real_size) | ||
| 197 | return -EINVAL; | ||
| 198 | |||
| 199 | mutex_lock(&isku->isku_lock); | ||
| 200 | retval = isku_send(usb_dev, command, (void *)buf, real_size); | ||
| 201 | mutex_unlock(&isku->isku_lock); | ||
| 202 | |||
| 203 | return retval ? retval : real_size; | ||
| 204 | } | ||
| 205 | |||
| 206 | #define ISKU_SYSFS_W(thingy, THINGY) \ | ||
| 207 | static ssize_t isku_sysfs_write_ ## thingy(struct file *fp, struct kobject *kobj, \ | ||
| 208 | struct bin_attribute *attr, char *buf, \ | ||
| 209 | loff_t off, size_t count) \ | ||
| 210 | { \ | ||
| 211 | return isku_sysfs_write(fp, kobj, buf, off, count, \ | ||
| 212 | sizeof(struct isku_ ## thingy), ISKU_COMMAND_ ## THINGY); \ | ||
| 213 | } | ||
| 214 | |||
| 215 | #define ISKU_SYSFS_R(thingy, THINGY) \ | ||
| 216 | static ssize_t isku_sysfs_read_ ## thingy(struct file *fp, struct kobject *kobj, \ | ||
| 217 | struct bin_attribute *attr, char *buf, \ | ||
| 218 | loff_t off, size_t count) \ | ||
| 219 | { \ | ||
| 220 | return isku_sysfs_read(fp, kobj, buf, off, count, \ | ||
| 221 | sizeof(struct isku_ ## thingy), ISKU_COMMAND_ ## THINGY); \ | ||
| 222 | } | ||
| 223 | |||
| 224 | #define ISKU_SYSFS_RW(thingy, THINGY) \ | ||
| 225 | ISKU_SYSFS_R(thingy, THINGY) \ | ||
| 226 | ISKU_SYSFS_W(thingy, THINGY) | ||
| 227 | |||
| 228 | #define ISKU_BIN_ATTR_RW(thingy) \ | ||
| 229 | { \ | ||
| 230 | .attr = { .name = #thingy, .mode = 0660 }, \ | ||
| 231 | .size = sizeof(struct isku_ ## thingy), \ | ||
| 232 | .read = isku_sysfs_read_ ## thingy, \ | ||
| 233 | .write = isku_sysfs_write_ ## thingy \ | ||
| 234 | } | ||
| 235 | |||
| 236 | #define ISKU_BIN_ATTR_R(thingy) \ | ||
| 237 | { \ | ||
| 238 | .attr = { .name = #thingy, .mode = 0440 }, \ | ||
| 239 | .size = sizeof(struct isku_ ## thingy), \ | ||
| 240 | .read = isku_sysfs_read_ ## thingy, \ | ||
| 241 | } | ||
| 242 | |||
| 243 | #define ISKU_BIN_ATTR_W(thingy) \ | ||
| 244 | { \ | ||
| 245 | .attr = { .name = #thingy, .mode = 0220 }, \ | ||
| 246 | .size = sizeof(struct isku_ ## thingy), \ | ||
| 247 | .write = isku_sysfs_write_ ## thingy \ | ||
| 248 | } | ||
| 249 | |||
| 250 | ISKU_SYSFS_RW(macro, MACRO) | ||
| 251 | ISKU_SYSFS_RW(keys_function, KEYS_FUNCTION) | ||
| 252 | ISKU_SYSFS_RW(keys_easyzone, KEYS_EASYZONE) | ||
| 253 | ISKU_SYSFS_RW(keys_media, KEYS_MEDIA) | ||
| 254 | ISKU_SYSFS_RW(keys_thumbster, KEYS_THUMBSTER) | ||
| 255 | ISKU_SYSFS_RW(keys_macro, KEYS_MACRO) | ||
| 256 | ISKU_SYSFS_RW(keys_capslock, KEYS_CAPSLOCK) | ||
| 257 | ISKU_SYSFS_RW(light, LIGHT) | ||
| 258 | ISKU_SYSFS_RW(key_mask, KEY_MASK) | ||
| 259 | ISKU_SYSFS_RW(last_set, LAST_SET) | ||
| 260 | ISKU_SYSFS_W(talk, TALK) | ||
| 261 | ISKU_SYSFS_R(info, INFO) | ||
| 262 | ISKU_SYSFS_W(control, CONTROL) | ||
| 263 | |||
| 264 | static struct bin_attribute isku_bin_attributes[] = { | ||
| 265 | ISKU_BIN_ATTR_RW(macro), | ||
| 266 | ISKU_BIN_ATTR_RW(keys_function), | ||
| 267 | ISKU_BIN_ATTR_RW(keys_easyzone), | ||
| 268 | ISKU_BIN_ATTR_RW(keys_media), | ||
| 269 | ISKU_BIN_ATTR_RW(keys_thumbster), | ||
| 270 | ISKU_BIN_ATTR_RW(keys_macro), | ||
| 271 | ISKU_BIN_ATTR_RW(keys_capslock), | ||
| 272 | ISKU_BIN_ATTR_RW(light), | ||
| 273 | ISKU_BIN_ATTR_RW(key_mask), | ||
| 274 | ISKU_BIN_ATTR_RW(last_set), | ||
| 275 | ISKU_BIN_ATTR_W(talk), | ||
| 276 | ISKU_BIN_ATTR_R(info), | ||
| 277 | ISKU_BIN_ATTR_W(control), | ||
| 278 | __ATTR_NULL | ||
| 279 | }; | ||
| 280 | |||
| 281 | static int isku_init_isku_device_struct(struct usb_device *usb_dev, | ||
| 282 | struct isku_device *isku) | ||
| 283 | { | ||
| 284 | int retval; | ||
| 285 | |||
| 286 | mutex_init(&isku->isku_lock); | ||
| 287 | |||
| 288 | retval = isku_get_actual_profile(usb_dev); | ||
| 289 | if (retval < 0) | ||
| 290 | return retval; | ||
| 291 | isku_profile_activated(isku, retval); | ||
| 292 | |||
| 293 | return 0; | ||
| 294 | } | ||
| 295 | |||
| 296 | static int isku_init_specials(struct hid_device *hdev) | ||
| 297 | { | ||
| 298 | struct usb_interface *intf = to_usb_interface(hdev->dev.parent); | ||
| 299 | struct usb_device *usb_dev = interface_to_usbdev(intf); | ||
| 300 | struct isku_device *isku; | ||
| 301 | int retval; | ||
| 302 | |||
| 303 | if (intf->cur_altsetting->desc.bInterfaceProtocol | ||
| 304 | != ISKU_USB_INTERFACE_PROTOCOL) { | ||
| 305 | hid_set_drvdata(hdev, NULL); | ||
| 306 | return 0; | ||
| 307 | } | ||
| 308 | |||
| 309 | isku = kzalloc(sizeof(*isku), GFP_KERNEL); | ||
| 310 | if (!isku) { | ||
| 311 | hid_err(hdev, "can't alloc device descriptor\n"); | ||
| 312 | return -ENOMEM; | ||
| 313 | } | ||
| 314 | hid_set_drvdata(hdev, isku); | ||
| 315 | |||
| 316 | retval = isku_init_isku_device_struct(usb_dev, isku); | ||
| 317 | if (retval) { | ||
| 318 | hid_err(hdev, "couldn't init struct isku_device\n"); | ||
| 319 | goto exit_free; | ||
| 320 | } | ||
| 321 | |||
| 322 | retval = roccat_connect(isku_class, hdev, | ||
| 323 | sizeof(struct isku_roccat_report)); | ||
| 324 | if (retval < 0) { | ||
| 325 | hid_err(hdev, "couldn't init char dev\n"); | ||
| 326 | } else { | ||
| 327 | isku->chrdev_minor = retval; | ||
| 328 | isku->roccat_claimed = 1; | ||
| 329 | } | ||
| 330 | |||
| 331 | return 0; | ||
| 332 | exit_free: | ||
| 333 | kfree(isku); | ||
| 334 | return retval; | ||
| 335 | } | ||
| 336 | |||
| 337 | static void isku_remove_specials(struct hid_device *hdev) | ||
| 338 | { | ||
| 339 | struct usb_interface *intf = to_usb_interface(hdev->dev.parent); | ||
| 340 | struct isku_device *isku; | ||
| 341 | |||
| 342 | if (intf->cur_altsetting->desc.bInterfaceProtocol | ||
| 343 | != ISKU_USB_INTERFACE_PROTOCOL) | ||
| 344 | return; | ||
| 345 | |||
| 346 | isku = hid_get_drvdata(hdev); | ||
| 347 | if (isku->roccat_claimed) | ||
| 348 | roccat_disconnect(isku->chrdev_minor); | ||
| 349 | kfree(isku); | ||
| 350 | } | ||
| 351 | |||
| 352 | static int isku_probe(struct hid_device *hdev, | ||
| 353 | const struct hid_device_id *id) | ||
| 354 | { | ||
| 355 | int retval; | ||
| 356 | |||
| 357 | retval = hid_parse(hdev); | ||
| 358 | if (retval) { | ||
| 359 | hid_err(hdev, "parse failed\n"); | ||
| 360 | goto exit; | ||
| 361 | } | ||
| 362 | |||
| 363 | retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT); | ||
| 364 | if (retval) { | ||
| 365 | hid_err(hdev, "hw start failed\n"); | ||
| 366 | goto exit; | ||
| 367 | } | ||
| 368 | |||
| 369 | retval = isku_init_specials(hdev); | ||
| 370 | if (retval) { | ||
| 371 | hid_err(hdev, "couldn't install keyboard\n"); | ||
| 372 | goto exit_stop; | ||
| 373 | } | ||
| 374 | |||
| 375 | return 0; | ||
| 376 | |||
| 377 | exit_stop: | ||
| 378 | hid_hw_stop(hdev); | ||
| 379 | exit: | ||
| 380 | return retval; | ||
| 381 | } | ||
| 382 | |||
| 383 | static void isku_remove(struct hid_device *hdev) | ||
| 384 | { | ||
| 385 | isku_remove_specials(hdev); | ||
| 386 | hid_hw_stop(hdev); | ||
| 387 | } | ||
| 388 | |||
| 389 | static void isku_keep_values_up_to_date(struct isku_device *isku, | ||
| 390 | u8 const *data) | ||
| 391 | { | ||
| 392 | struct isku_report_button const *button_report; | ||
| 393 | |||
| 394 | switch (data[0]) { | ||
| 395 | case ISKU_REPORT_NUMBER_BUTTON: | ||
| 396 | button_report = (struct isku_report_button const *)data; | ||
| 397 | switch (button_report->event) { | ||
| 398 | case ISKU_REPORT_BUTTON_EVENT_PROFILE: | ||
| 399 | isku_profile_activated(isku, button_report->data1 - 1); | ||
| 400 | break; | ||
| 401 | } | ||
| 402 | break; | ||
| 403 | } | ||
| 404 | } | ||
| 405 | |||
| 406 | static void isku_report_to_chrdev(struct isku_device const *isku, | ||
| 407 | u8 const *data) | ||
| 408 | { | ||
| 409 | struct isku_roccat_report roccat_report; | ||
| 410 | struct isku_report_button const *button_report; | ||
| 411 | |||
| 412 | if (data[0] != ISKU_REPORT_NUMBER_BUTTON) | ||
| 413 | return; | ||
| 414 | |||
| 415 | button_report = (struct isku_report_button const *)data; | ||
| 416 | |||
| 417 | roccat_report.event = button_report->event; | ||
| 418 | roccat_report.data1 = button_report->data1; | ||
| 419 | roccat_report.data2 = button_report->data2; | ||
| 420 | roccat_report.profile = isku->actual_profile + 1; | ||
| 421 | roccat_report_event(isku->chrdev_minor, | ||
| 422 | (uint8_t const *)&roccat_report); | ||
| 423 | } | ||
| 424 | |||
| 425 | static int isku_raw_event(struct hid_device *hdev, | ||
| 426 | struct hid_report *report, u8 *data, int size) | ||
| 427 | { | ||
| 428 | struct usb_interface *intf = to_usb_interface(hdev->dev.parent); | ||
| 429 | struct isku_device *isku = hid_get_drvdata(hdev); | ||
| 430 | |||
| 431 | if (intf->cur_altsetting->desc.bInterfaceProtocol | ||
| 432 | != ISKU_USB_INTERFACE_PROTOCOL) | ||
| 433 | return 0; | ||
| 434 | |||
| 435 | if (isku == NULL) | ||
| 436 | return 0; | ||
| 437 | |||
| 438 | isku_keep_values_up_to_date(isku, data); | ||
| 439 | |||
| 440 | if (isku->roccat_claimed) | ||
| 441 | isku_report_to_chrdev(isku, data); | ||
| 442 | |||
| 443 | return 0; | ||
| 444 | } | ||
| 445 | |||
| 446 | static const struct hid_device_id isku_devices[] = { | ||
| 447 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKU) }, | ||
| 448 | { } | ||
| 449 | }; | ||
| 450 | |||
| 451 | MODULE_DEVICE_TABLE(hid, isku_devices); | ||
| 452 | |||
| 453 | static struct hid_driver isku_driver = { | ||
| 454 | .name = "isku", | ||
| 455 | .id_table = isku_devices, | ||
| 456 | .probe = isku_probe, | ||
| 457 | .remove = isku_remove, | ||
| 458 | .raw_event = isku_raw_event | ||
| 459 | }; | ||
| 460 | |||
| 461 | static int __init isku_init(void) | ||
| 462 | { | ||
| 463 | int retval; | ||
| 464 | isku_class = class_create(THIS_MODULE, "isku"); | ||
| 465 | if (IS_ERR(isku_class)) | ||
| 466 | return PTR_ERR(isku_class); | ||
| 467 | isku_class->dev_attrs = isku_attributes; | ||
| 468 | isku_class->dev_bin_attrs = isku_bin_attributes; | ||
| 469 | |||
| 470 | retval = hid_register_driver(&isku_driver); | ||
| 471 | if (retval) | ||
| 472 | class_destroy(isku_class); | ||
| 473 | return retval; | ||
| 474 | } | ||
| 475 | |||
| 476 | static void __exit isku_exit(void) | ||
| 477 | { | ||
| 478 | hid_unregister_driver(&isku_driver); | ||
| 479 | class_destroy(isku_class); | ||
| 480 | } | ||
| 481 | |||
| 482 | module_init(isku_init); | ||
| 483 | module_exit(isku_exit); | ||
| 484 | |||
| 485 | MODULE_AUTHOR("Stefan Achatz"); | ||
| 486 | MODULE_DESCRIPTION("USB Roccat Isku driver"); | ||
| 487 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/hid/hid-roccat-isku.h b/drivers/hid/hid-roccat-isku.h new file mode 100644 index 000000000000..075f6efaec58 --- /dev/null +++ b/drivers/hid/hid-roccat-isku.h | |||
| @@ -0,0 +1,147 @@ | |||
| 1 | #ifndef __HID_ROCCAT_ISKU_H | ||
| 2 | #define __HID_ROCCAT_ISKU_H | ||
| 3 | |||
| 4 | /* | ||
| 5 | * Copyright (c) 2011 Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 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 <linux/types.h> | ||
| 16 | |||
| 17 | enum { | ||
| 18 | ISKU_PROFILE_NUM = 5, | ||
| 19 | ISKU_USB_INTERFACE_PROTOCOL = 0, | ||
| 20 | }; | ||
| 21 | |||
| 22 | struct isku_control { | ||
| 23 | uint8_t command; /* ISKU_COMMAND_CONTROL */ | ||
| 24 | uint8_t value; | ||
| 25 | uint8_t request; | ||
| 26 | } __packed; | ||
| 27 | |||
| 28 | enum isku_control_values { | ||
| 29 | ISKU_CONTROL_VALUE_STATUS_OVERLOAD = 0, | ||
| 30 | ISKU_CONTROL_VALUE_STATUS_OK = 1, | ||
| 31 | ISKU_CONTROL_VALUE_STATUS_INVALID = 2, | ||
| 32 | ISKU_CONTROL_VALUE_STATUS_WAIT = 3, | ||
| 33 | }; | ||
| 34 | |||
| 35 | struct isku_actual_profile { | ||
| 36 | uint8_t command; /* ISKU_COMMAND_ACTUAL_PROFILE */ | ||
| 37 | uint8_t size; /* always 3 */ | ||
| 38 | uint8_t actual_profile; | ||
| 39 | } __packed; | ||
| 40 | |||
| 41 | struct isku_key_mask { | ||
| 42 | uint8_t command; /* ISKU_COMMAND_KEY_MASK */ | ||
| 43 | uint8_t size; /* 6 */ | ||
| 44 | uint8_t profile_number; /* 0-4 */ | ||
| 45 | uint8_t mask; | ||
| 46 | uint16_t checksum; | ||
| 47 | } __packed; | ||
| 48 | |||
| 49 | struct isku_keys_function { | ||
| 50 | uint8_t data[0x29]; | ||
| 51 | } __packed; | ||
| 52 | |||
| 53 | struct isku_keys_easyzone { | ||
| 54 | uint8_t data[0x41]; | ||
| 55 | } __packed; | ||
| 56 | |||
| 57 | struct isku_keys_media { | ||
| 58 | uint8_t data[0x1d]; | ||
| 59 | } __packed; | ||
| 60 | |||
| 61 | struct isku_keys_thumbster { | ||
| 62 | uint8_t data[0x17]; | ||
| 63 | } __packed; | ||
| 64 | |||
| 65 | struct isku_keys_macro { | ||
| 66 | uint8_t data[0x23]; | ||
| 67 | } __packed; | ||
| 68 | |||
| 69 | struct isku_keys_capslock { | ||
| 70 | uint8_t data[0x6]; | ||
| 71 | } __packed; | ||
| 72 | |||
| 73 | struct isku_macro { | ||
| 74 | uint8_t data[0x823]; | ||
| 75 | } __packed; | ||
| 76 | |||
| 77 | struct isku_light { | ||
| 78 | uint8_t data[0xa]; | ||
| 79 | } __packed; | ||
| 80 | |||
| 81 | struct isku_info { | ||
| 82 | uint8_t data[2]; | ||
| 83 | uint8_t firmware_version; | ||
| 84 | uint8_t unknown[3]; | ||
| 85 | } __packed; | ||
| 86 | |||
| 87 | struct isku_talk { | ||
| 88 | uint8_t data[0x10]; | ||
| 89 | } __packed; | ||
| 90 | |||
| 91 | struct isku_last_set { | ||
| 92 | uint8_t data[0x14]; | ||
| 93 | } __packed; | ||
| 94 | |||
| 95 | enum isku_commands { | ||
| 96 | ISKU_COMMAND_CONTROL = 0x4, | ||
| 97 | ISKU_COMMAND_ACTUAL_PROFILE = 0x5, | ||
| 98 | ISKU_COMMAND_KEY_MASK = 0x7, | ||
| 99 | ISKU_COMMAND_KEYS_FUNCTION = 0x8, | ||
| 100 | ISKU_COMMAND_KEYS_EASYZONE = 0x9, | ||
| 101 | ISKU_COMMAND_KEYS_MEDIA = 0xa, | ||
| 102 | ISKU_COMMAND_KEYS_THUMBSTER = 0xb, | ||
| 103 | ISKU_COMMAND_KEYS_MACRO = 0xd, | ||
| 104 | ISKU_COMMAND_MACRO = 0xe, | ||
| 105 | ISKU_COMMAND_INFO = 0xf, | ||
| 106 | ISKU_COMMAND_LIGHT = 0x10, | ||
| 107 | ISKU_COMMAND_KEYS_CAPSLOCK = 0x13, | ||
| 108 | ISKU_COMMAND_LAST_SET = 0x14, | ||
| 109 | ISKU_COMMAND_15 = 0x15, | ||
| 110 | ISKU_COMMAND_TALK = 0x16, | ||
| 111 | ISKU_COMMAND_FIRMWARE_WRITE = 0x1b, | ||
| 112 | ISKU_COMMAND_FIRMWARE_WRITE_CONTROL = 0x1c, | ||
| 113 | }; | ||
| 114 | |||
| 115 | struct isku_report_button { | ||
| 116 | uint8_t number; /* ISKU_REPORT_NUMBER_BUTTON */ | ||
| 117 | uint8_t zero; | ||
| 118 | uint8_t event; | ||
| 119 | uint8_t data1; | ||
| 120 | uint8_t data2; | ||
| 121 | }; | ||
| 122 | |||
| 123 | enum isku_report_numbers { | ||
| 124 | ISKU_REPORT_NUMBER_BUTTON = 3, | ||
| 125 | }; | ||
| 126 | |||
| 127 | enum isku_report_button_events { | ||
| 128 | ISKU_REPORT_BUTTON_EVENT_PROFILE = 0x2, | ||
| 129 | }; | ||
| 130 | |||
| 131 | struct isku_roccat_report { | ||
| 132 | uint8_t event; | ||
| 133 | uint8_t data1; | ||
| 134 | uint8_t data2; | ||
| 135 | uint8_t profile; | ||
| 136 | } __packed; | ||
| 137 | |||
| 138 | struct isku_device { | ||
| 139 | int roccat_claimed; | ||
| 140 | int chrdev_minor; | ||
| 141 | |||
| 142 | struct mutex isku_lock; | ||
| 143 | |||
| 144 | int actual_profile; | ||
| 145 | }; | ||
| 146 | |||
| 147 | #endif | ||
diff --git a/drivers/hid/hid-roccat-kone.c b/drivers/hid/hid-roccat-kone.c index e2072afb34bb..40090d602158 100644 --- a/drivers/hid/hid-roccat-kone.c +++ b/drivers/hid/hid-roccat-kone.c | |||
| @@ -78,12 +78,10 @@ static int kone_send(struct usb_device *usb_dev, uint usb_command, | |||
| 78 | char *buf; | 78 | char *buf; |
| 79 | int len; | 79 | int len; |
| 80 | 80 | ||
| 81 | buf = kmalloc(size, GFP_KERNEL); | 81 | buf = kmemdup(data, size, GFP_KERNEL); |
| 82 | if (buf == NULL) | 82 | if (buf == NULL) |
| 83 | return -ENOMEM; | 83 | return -ENOMEM; |
| 84 | 84 | ||
| 85 | memcpy(buf, data, size); | ||
| 86 | |||
| 87 | len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), | 85 | len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), |
| 88 | HID_REQ_SET_REPORT, | 86 | HID_REQ_SET_REPORT, |
| 89 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, | 87 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, |
diff --git a/drivers/hid/hid-wacom.c b/drivers/hid/hid-wacom.c index 17bb88f782b6..f2183486a9b6 100644 --- a/drivers/hid/hid-wacom.c +++ b/drivers/hid/hid-wacom.c | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | * Copyright (c) 2008 Jiri Slaby <jirislaby@gmail.com> | 9 | * Copyright (c) 2008 Jiri Slaby <jirislaby@gmail.com> |
| 10 | * Copyright (c) 2006 Andrew Zabolotny <zap@homelink.ru> | 10 | * Copyright (c) 2006 Andrew Zabolotny <zap@homelink.ru> |
| 11 | * Copyright (c) 2009 Bastien Nocera <hadess@hadess.net> | 11 | * Copyright (c) 2009 Bastien Nocera <hadess@hadess.net> |
| 12 | * Copyright (c) 2011 Przemysław Firszt <przemo@firszt.eu> | ||
| 12 | */ | 13 | */ |
| 13 | 14 | ||
| 14 | /* | 15 | /* |
| @@ -33,6 +34,7 @@ | |||
| 33 | struct wacom_data { | 34 | struct wacom_data { |
| 34 | __u16 tool; | 35 | __u16 tool; |
| 35 | unsigned char butstate; | 36 | unsigned char butstate; |
| 37 | __u8 features; | ||
| 36 | unsigned char high_speed; | 38 | unsigned char high_speed; |
| 37 | #ifdef CONFIG_HID_WACOM_POWER_SUPPLY | 39 | #ifdef CONFIG_HID_WACOM_POWER_SUPPLY |
| 38 | int battery_capacity; | 40 | int battery_capacity; |
| @@ -107,6 +109,19 @@ static int wacom_ac_get_property(struct power_supply *psy, | |||
| 107 | } | 109 | } |
| 108 | #endif | 110 | #endif |
| 109 | 111 | ||
| 112 | static void wacom_set_features(struct hid_device *hdev) | ||
| 113 | { | ||
| 114 | int ret; | ||
| 115 | __u8 rep_data[2]; | ||
| 116 | |||
| 117 | /*set high speed, tablet mode*/ | ||
| 118 | rep_data[0] = 0x03; | ||
| 119 | rep_data[1] = 0x20; | ||
| 120 | ret = hdev->hid_output_raw_report(hdev, rep_data, 2, | ||
| 121 | HID_FEATURE_REPORT); | ||
| 122 | return; | ||
| 123 | } | ||
| 124 | |||
| 110 | static void wacom_poke(struct hid_device *hdev, u8 speed) | 125 | static void wacom_poke(struct hid_device *hdev, u8 speed) |
| 111 | { | 126 | { |
| 112 | struct wacom_data *wdata = hid_get_drvdata(hdev); | 127 | struct wacom_data *wdata = hid_get_drvdata(hdev); |
| @@ -177,26 +192,13 @@ static ssize_t wacom_store_speed(struct device *dev, | |||
| 177 | static DEVICE_ATTR(speed, S_IRUGO | S_IWUSR | S_IWGRP, | 192 | static DEVICE_ATTR(speed, S_IRUGO | S_IWUSR | S_IWGRP, |
| 178 | wacom_show_speed, wacom_store_speed); | 193 | wacom_show_speed, wacom_store_speed); |
| 179 | 194 | ||
| 180 | static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report, | 195 | static int wacom_gr_parse_report(struct hid_device *hdev, |
| 181 | u8 *raw_data, int size) | 196 | struct wacom_data *wdata, |
| 197 | struct input_dev *input, unsigned char *data) | ||
| 182 | { | 198 | { |
| 183 | struct wacom_data *wdata = hid_get_drvdata(hdev); | ||
| 184 | struct hid_input *hidinput; | ||
| 185 | struct input_dev *input; | ||
| 186 | unsigned char *data = (unsigned char *) raw_data; | ||
| 187 | int tool, x, y, rw; | 199 | int tool, x, y, rw; |
| 188 | 200 | ||
| 189 | if (!(hdev->claimed & HID_CLAIMED_INPUT)) | ||
| 190 | return 0; | ||
| 191 | |||
| 192 | tool = 0; | 201 | tool = 0; |
| 193 | hidinput = list_entry(hdev->inputs.next, struct hid_input, list); | ||
| 194 | input = hidinput->input; | ||
| 195 | |||
| 196 | /* Check if this is a tablet report */ | ||
| 197 | if (data[0] != 0x03) | ||
| 198 | return 0; | ||
| 199 | |||
| 200 | /* Get X & Y positions */ | 202 | /* Get X & Y positions */ |
| 201 | x = le16_to_cpu(*(__le16 *) &data[2]); | 203 | x = le16_to_cpu(*(__le16 *) &data[2]); |
| 202 | y = le16_to_cpu(*(__le16 *) &data[4]); | 204 | y = le16_to_cpu(*(__le16 *) &data[4]); |
| @@ -304,6 +306,121 @@ static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report, | |||
| 304 | return 1; | 306 | return 1; |
| 305 | } | 307 | } |
| 306 | 308 | ||
| 309 | static void wacom_i4_parse_pen_report(struct wacom_data *wdata, | ||
| 310 | struct input_dev *input, unsigned char *data) | ||
| 311 | { | ||
| 312 | __u16 x, y, pressure; | ||
| 313 | __u32 id; | ||
| 314 | |||
| 315 | switch (data[1]) { | ||
| 316 | case 0x80: /* Out of proximity report */ | ||
| 317 | wdata->tool = 0; | ||
| 318 | input_report_key(input, BTN_TOUCH, 0); | ||
| 319 | input_report_abs(input, ABS_PRESSURE, 0); | ||
| 320 | input_report_key(input, wdata->tool, 0); | ||
| 321 | input_sync(input); | ||
| 322 | break; | ||
| 323 | case 0xC2: /* Tool report */ | ||
| 324 | id = ((data[2] << 4) | (data[3] >> 4) | | ||
| 325 | ((data[7] & 0x0f) << 20) | | ||
| 326 | ((data[8] & 0xf0) << 12)) & 0xfffff; | ||
| 327 | |||
| 328 | switch (id) { | ||
| 329 | case 0x802: | ||
| 330 | wdata->tool = BTN_TOOL_PEN; | ||
| 331 | break; | ||
| 332 | case 0x80A: | ||
| 333 | wdata->tool = BTN_TOOL_RUBBER; | ||
| 334 | break; | ||
| 335 | } | ||
| 336 | break; | ||
| 337 | default: /* Position/pressure report */ | ||
| 338 | x = data[2] << 9 | data[3] << 1 | ((data[9] & 0x02) >> 1); | ||
| 339 | y = data[4] << 9 | data[5] << 1 | (data[9] & 0x01); | ||
| 340 | pressure = (data[6] << 3) | ((data[7] & 0xC0) >> 5) | ||
| 341 | | (data[1] & 0x01); | ||
| 342 | |||
| 343 | input_report_key(input, BTN_TOUCH, pressure > 1); | ||
| 344 | |||
| 345 | input_report_key(input, BTN_STYLUS, data[1] & 0x02); | ||
| 346 | input_report_key(input, BTN_STYLUS2, data[1] & 0x04); | ||
| 347 | input_report_key(input, wdata->tool, 1); | ||
| 348 | input_report_abs(input, ABS_X, x); | ||
| 349 | input_report_abs(input, ABS_Y, y); | ||
| 350 | input_report_abs(input, ABS_PRESSURE, pressure); | ||
| 351 | input_sync(input); | ||
| 352 | break; | ||
| 353 | } | ||
| 354 | |||
| 355 | return; | ||
| 356 | } | ||
| 357 | |||
| 358 | static void wacom_i4_parse_report(struct hid_device *hdev, | ||
| 359 | struct wacom_data *wdata, | ||
| 360 | struct input_dev *input, unsigned char *data) | ||
| 361 | { | ||
| 362 | switch (data[0]) { | ||
| 363 | case 0x00: /* Empty report */ | ||
| 364 | break; | ||
| 365 | case 0x02: /* Pen report */ | ||
| 366 | wacom_i4_parse_pen_report(wdata, input, data); | ||
| 367 | break; | ||
| 368 | case 0x03: /* Features Report */ | ||
| 369 | wdata->features = data[2]; | ||
| 370 | break; | ||
| 371 | case 0x0C: /* Button report */ | ||
| 372 | break; | ||
| 373 | default: | ||
| 374 | hid_err(hdev, "Unknown report: %d,%d\n", data[0], data[1]); | ||
| 375 | break; | ||
| 376 | } | ||
| 377 | } | ||
| 378 | |||
| 379 | static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report, | ||
| 380 | u8 *raw_data, int size) | ||
| 381 | { | ||
| 382 | struct wacom_data *wdata = hid_get_drvdata(hdev); | ||
| 383 | struct hid_input *hidinput; | ||
| 384 | struct input_dev *input; | ||
| 385 | unsigned char *data = (unsigned char *) raw_data; | ||
| 386 | int i; | ||
| 387 | |||
| 388 | if (!(hdev->claimed & HID_CLAIMED_INPUT)) | ||
| 389 | return 0; | ||
| 390 | |||
| 391 | hidinput = list_entry(hdev->inputs.next, struct hid_input, list); | ||
| 392 | input = hidinput->input; | ||
| 393 | |||
| 394 | /* Check if this is a tablet report */ | ||
| 395 | if (data[0] != 0x03) | ||
| 396 | return 0; | ||
| 397 | |||
| 398 | switch (hdev->product) { | ||
| 399 | case USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH: | ||
| 400 | return wacom_gr_parse_report(hdev, wdata, input, data); | ||
| 401 | break; | ||
| 402 | case USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH: | ||
| 403 | i = 1; | ||
| 404 | |||
| 405 | switch (data[0]) { | ||
| 406 | case 0x04: | ||
| 407 | wacom_i4_parse_report(hdev, wdata, input, data + i); | ||
| 408 | i += 10; | ||
| 409 | /* fall through */ | ||
| 410 | case 0x03: | ||
| 411 | wacom_i4_parse_report(hdev, wdata, input, data + i); | ||
| 412 | i += 10; | ||
| 413 | wacom_i4_parse_report(hdev, wdata, input, data + i); | ||
| 414 | break; | ||
| 415 | default: | ||
| 416 | hid_err(hdev, "Unknown report: %d,%d size:%d\n", | ||
| 417 | data[0], data[1], size); | ||
| 418 | return 0; | ||
| 419 | } | ||
| 420 | } | ||
| 421 | return 1; | ||
| 422 | } | ||
| 423 | |||
| 307 | static int wacom_input_mapped(struct hid_device *hdev, struct hid_input *hi, | 424 | static int wacom_input_mapped(struct hid_device *hdev, struct hid_input *hi, |
| 308 | struct hid_field *field, struct hid_usage *usage, unsigned long **bit, | 425 | struct hid_field *field, struct hid_usage *usage, unsigned long **bit, |
| 309 | int *max) | 426 | int *max) |
| @@ -338,10 +455,19 @@ static int wacom_input_mapped(struct hid_device *hdev, struct hid_input *hi, | |||
| 338 | __set_bit(BTN_TOOL_RUBBER, input->keybit); | 455 | __set_bit(BTN_TOOL_RUBBER, input->keybit); |
| 339 | __set_bit(BTN_TOOL_MOUSE, input->keybit); | 456 | __set_bit(BTN_TOOL_MOUSE, input->keybit); |
| 340 | 457 | ||
| 341 | input_set_abs_params(input, ABS_X, 0, 16704, 4, 0); | 458 | switch (hdev->product) { |
| 342 | input_set_abs_params(input, ABS_Y, 0, 12064, 4, 0); | 459 | case USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH: |
| 343 | input_set_abs_params(input, ABS_PRESSURE, 0, 511, 0, 0); | 460 | input_set_abs_params(input, ABS_X, 0, 16704, 4, 0); |
| 344 | input_set_abs_params(input, ABS_DISTANCE, 0, 32, 0, 0); | 461 | input_set_abs_params(input, ABS_Y, 0, 12064, 4, 0); |
| 462 | input_set_abs_params(input, ABS_PRESSURE, 0, 511, 0, 0); | ||
| 463 | input_set_abs_params(input, ABS_DISTANCE, 0, 32, 0, 0); | ||
| 464 | break; | ||
| 465 | case USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH: | ||
| 466 | input_set_abs_params(input, ABS_X, 0, 40640, 4, 0); | ||
| 467 | input_set_abs_params(input, ABS_Y, 0, 25400, 4, 0); | ||
| 468 | input_set_abs_params(input, ABS_PRESSURE, 0, 2047, 0, 0); | ||
| 469 | break; | ||
| 470 | } | ||
| 345 | 471 | ||
| 346 | return 0; | 472 | return 0; |
| 347 | } | 473 | } |
| @@ -378,8 +504,16 @@ static int wacom_probe(struct hid_device *hdev, | |||
| 378 | hid_warn(hdev, | 504 | hid_warn(hdev, |
| 379 | "can't create sysfs speed attribute err: %d\n", ret); | 505 | "can't create sysfs speed attribute err: %d\n", ret); |
| 380 | 506 | ||
| 381 | /* Set Wacom mode 2 with high reporting speed */ | 507 | switch (hdev->product) { |
| 382 | wacom_poke(hdev, 1); | 508 | case USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH: |
| 509 | /* Set Wacom mode 2 with high reporting speed */ | ||
| 510 | wacom_poke(hdev, 1); | ||
| 511 | break; | ||
| 512 | case USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH: | ||
| 513 | wdata->features = 0; | ||
| 514 | wacom_set_features(hdev); | ||
| 515 | break; | ||
| 516 | } | ||
| 383 | 517 | ||
| 384 | #ifdef CONFIG_HID_WACOM_POWER_SUPPLY | 518 | #ifdef CONFIG_HID_WACOM_POWER_SUPPLY |
| 385 | wdata->battery.properties = wacom_battery_props; | 519 | wdata->battery.properties = wacom_battery_props; |
| @@ -441,6 +575,7 @@ static void wacom_remove(struct hid_device *hdev) | |||
| 441 | 575 | ||
| 442 | static const struct hid_device_id wacom_devices[] = { | 576 | static const struct hid_device_id wacom_devices[] = { |
| 443 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) }, | 577 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) }, |
| 578 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH) }, | ||
| 444 | 579 | ||
| 445 | { } | 580 | { } |
| 446 | }; | 581 | }; |
diff --git a/drivers/hid/hid-wiimote.c b/drivers/hid/hid-wiimote-core.c index 76739c07fa3c..61881b35c670 100644 --- a/drivers/hid/hid-wiimote.c +++ b/drivers/hid/hid-wiimote-core.c | |||
| @@ -20,91 +20,7 @@ | |||
| 20 | #include <linux/power_supply.h> | 20 | #include <linux/power_supply.h> |
| 21 | #include <linux/spinlock.h> | 21 | #include <linux/spinlock.h> |
| 22 | #include "hid-ids.h" | 22 | #include "hid-ids.h" |
| 23 | 23 | #include "hid-wiimote.h" | |
| 24 | #define WIIMOTE_VERSION "0.2" | ||
| 25 | #define WIIMOTE_NAME "Nintendo Wii Remote" | ||
| 26 | #define WIIMOTE_BUFSIZE 32 | ||
| 27 | |||
| 28 | struct wiimote_buf { | ||
| 29 | __u8 data[HID_MAX_BUFFER_SIZE]; | ||
| 30 | size_t size; | ||
| 31 | }; | ||
| 32 | |||
| 33 | struct wiimote_state { | ||
| 34 | spinlock_t lock; | ||
| 35 | __u8 flags; | ||
| 36 | __u8 accel_split[2]; | ||
| 37 | |||
| 38 | /* synchronous cmd requests */ | ||
| 39 | struct mutex sync; | ||
| 40 | struct completion ready; | ||
| 41 | int cmd; | ||
| 42 | __u32 opt; | ||
| 43 | |||
| 44 | /* results of synchronous requests */ | ||
| 45 | __u8 cmd_battery; | ||
| 46 | __u8 cmd_err; | ||
| 47 | }; | ||
| 48 | |||
| 49 | struct wiimote_data { | ||
| 50 | struct hid_device *hdev; | ||
| 51 | struct input_dev *input; | ||
| 52 | struct led_classdev *leds[4]; | ||
| 53 | struct input_dev *accel; | ||
| 54 | struct input_dev *ir; | ||
| 55 | struct power_supply battery; | ||
| 56 | |||
| 57 | spinlock_t qlock; | ||
| 58 | __u8 head; | ||
| 59 | __u8 tail; | ||
| 60 | struct wiimote_buf outq[WIIMOTE_BUFSIZE]; | ||
| 61 | struct work_struct worker; | ||
| 62 | |||
| 63 | struct wiimote_state state; | ||
| 64 | }; | ||
| 65 | |||
| 66 | #define WIIPROTO_FLAG_LED1 0x01 | ||
| 67 | #define WIIPROTO_FLAG_LED2 0x02 | ||
| 68 | #define WIIPROTO_FLAG_LED3 0x04 | ||
| 69 | #define WIIPROTO_FLAG_LED4 0x08 | ||
| 70 | #define WIIPROTO_FLAG_RUMBLE 0x10 | ||
| 71 | #define WIIPROTO_FLAG_ACCEL 0x20 | ||
| 72 | #define WIIPROTO_FLAG_IR_BASIC 0x40 | ||
| 73 | #define WIIPROTO_FLAG_IR_EXT 0x80 | ||
| 74 | #define WIIPROTO_FLAG_IR_FULL 0xc0 /* IR_BASIC | IR_EXT */ | ||
| 75 | #define WIIPROTO_FLAGS_LEDS (WIIPROTO_FLAG_LED1 | WIIPROTO_FLAG_LED2 | \ | ||
| 76 | WIIPROTO_FLAG_LED3 | WIIPROTO_FLAG_LED4) | ||
| 77 | #define WIIPROTO_FLAGS_IR (WIIPROTO_FLAG_IR_BASIC | WIIPROTO_FLAG_IR_EXT | \ | ||
| 78 | WIIPROTO_FLAG_IR_FULL) | ||
| 79 | |||
| 80 | /* return flag for led \num */ | ||
| 81 | #define WIIPROTO_FLAG_LED(num) (WIIPROTO_FLAG_LED1 << (num - 1)) | ||
| 82 | |||
| 83 | enum wiiproto_reqs { | ||
| 84 | WIIPROTO_REQ_NULL = 0x0, | ||
| 85 | WIIPROTO_REQ_RUMBLE = 0x10, | ||
| 86 | WIIPROTO_REQ_LED = 0x11, | ||
| 87 | WIIPROTO_REQ_DRM = 0x12, | ||
| 88 | WIIPROTO_REQ_IR1 = 0x13, | ||
| 89 | WIIPROTO_REQ_SREQ = 0x15, | ||
| 90 | WIIPROTO_REQ_WMEM = 0x16, | ||
| 91 | WIIPROTO_REQ_RMEM = 0x17, | ||
| 92 | WIIPROTO_REQ_IR2 = 0x1a, | ||
| 93 | WIIPROTO_REQ_STATUS = 0x20, | ||
| 94 | WIIPROTO_REQ_DATA = 0x21, | ||
| 95 | WIIPROTO_REQ_RETURN = 0x22, | ||
| 96 | WIIPROTO_REQ_DRM_K = 0x30, | ||
| 97 | WIIPROTO_REQ_DRM_KA = 0x31, | ||
| 98 | WIIPROTO_REQ_DRM_KE = 0x32, | ||
| 99 | WIIPROTO_REQ_DRM_KAI = 0x33, | ||
| 100 | WIIPROTO_REQ_DRM_KEE = 0x34, | ||
| 101 | WIIPROTO_REQ_DRM_KAE = 0x35, | ||
| 102 | WIIPROTO_REQ_DRM_KIE = 0x36, | ||
| 103 | WIIPROTO_REQ_DRM_KAIE = 0x37, | ||
| 104 | WIIPROTO_REQ_DRM_E = 0x3d, | ||
| 105 | WIIPROTO_REQ_DRM_SKAI1 = 0x3e, | ||
| 106 | WIIPROTO_REQ_DRM_SKAI2 = 0x3f, | ||
| 107 | }; | ||
| 108 | 24 | ||
| 109 | enum wiiproto_keys { | 25 | enum wiiproto_keys { |
| 110 | WIIPROTO_KEY_LEFT, | 26 | WIIPROTO_KEY_LEFT, |
| @@ -139,52 +55,6 @@ static enum power_supply_property wiimote_battery_props[] = { | |||
| 139 | POWER_SUPPLY_PROP_CAPACITY | 55 | POWER_SUPPLY_PROP_CAPACITY |
| 140 | }; | 56 | }; |
| 141 | 57 | ||
| 142 | /* requires the state.lock spinlock to be held */ | ||
| 143 | static inline bool wiimote_cmd_pending(struct wiimote_data *wdata, int cmd, | ||
| 144 | __u32 opt) | ||
| 145 | { | ||
| 146 | return wdata->state.cmd == cmd && wdata->state.opt == opt; | ||
| 147 | } | ||
| 148 | |||
| 149 | /* requires the state.lock spinlock to be held */ | ||
| 150 | static inline void wiimote_cmd_complete(struct wiimote_data *wdata) | ||
| 151 | { | ||
| 152 | wdata->state.cmd = WIIPROTO_REQ_NULL; | ||
| 153 | complete(&wdata->state.ready); | ||
| 154 | } | ||
| 155 | |||
| 156 | static inline int wiimote_cmd_acquire(struct wiimote_data *wdata) | ||
| 157 | { | ||
| 158 | return mutex_lock_interruptible(&wdata->state.sync) ? -ERESTARTSYS : 0; | ||
| 159 | } | ||
| 160 | |||
| 161 | /* requires the state.lock spinlock to be held */ | ||
| 162 | static inline void wiimote_cmd_set(struct wiimote_data *wdata, int cmd, | ||
| 163 | __u32 opt) | ||
| 164 | { | ||
| 165 | INIT_COMPLETION(wdata->state.ready); | ||
| 166 | wdata->state.cmd = cmd; | ||
| 167 | wdata->state.opt = opt; | ||
| 168 | } | ||
| 169 | |||
| 170 | static inline void wiimote_cmd_release(struct wiimote_data *wdata) | ||
| 171 | { | ||
| 172 | mutex_unlock(&wdata->state.sync); | ||
| 173 | } | ||
| 174 | |||
| 175 | static inline int wiimote_cmd_wait(struct wiimote_data *wdata) | ||
| 176 | { | ||
| 177 | int ret; | ||
| 178 | |||
| 179 | ret = wait_for_completion_interruptible_timeout(&wdata->state.ready, HZ); | ||
| 180 | if (ret < 0) | ||
| 181 | return -ERESTARTSYS; | ||
| 182 | else if (ret == 0) | ||
| 183 | return -EIO; | ||
| 184 | else | ||
| 185 | return 0; | ||
| 186 | } | ||
| 187 | |||
| 188 | static ssize_t wiimote_hid_send(struct hid_device *hdev, __u8 *buffer, | 58 | static ssize_t wiimote_hid_send(struct hid_device *hdev, __u8 *buffer, |
| 189 | size_t count) | 59 | size_t count) |
| 190 | { | 60 | { |
| @@ -329,6 +199,7 @@ static void wiiproto_req_leds(struct wiimote_data *wdata, int leds) | |||
| 329 | static __u8 select_drm(struct wiimote_data *wdata) | 199 | static __u8 select_drm(struct wiimote_data *wdata) |
| 330 | { | 200 | { |
| 331 | __u8 ir = wdata->state.flags & WIIPROTO_FLAGS_IR; | 201 | __u8 ir = wdata->state.flags & WIIPROTO_FLAGS_IR; |
| 202 | bool ext = wiiext_active(wdata); | ||
| 332 | 203 | ||
| 333 | if (ir == WIIPROTO_FLAG_IR_BASIC) { | 204 | if (ir == WIIPROTO_FLAG_IR_BASIC) { |
| 334 | if (wdata->state.flags & WIIPROTO_FLAG_ACCEL) | 205 | if (wdata->state.flags & WIIPROTO_FLAG_ACCEL) |
| @@ -340,14 +211,21 @@ static __u8 select_drm(struct wiimote_data *wdata) | |||
| 340 | } else if (ir == WIIPROTO_FLAG_IR_FULL) { | 211 | } else if (ir == WIIPROTO_FLAG_IR_FULL) { |
| 341 | return WIIPROTO_REQ_DRM_SKAI1; | 212 | return WIIPROTO_REQ_DRM_SKAI1; |
| 342 | } else { | 213 | } else { |
| 343 | if (wdata->state.flags & WIIPROTO_FLAG_ACCEL) | 214 | if (wdata->state.flags & WIIPROTO_FLAG_ACCEL) { |
| 344 | return WIIPROTO_REQ_DRM_KA; | 215 | if (ext) |
| 345 | else | 216 | return WIIPROTO_REQ_DRM_KAE; |
| 346 | return WIIPROTO_REQ_DRM_K; | 217 | else |
| 218 | return WIIPROTO_REQ_DRM_KA; | ||
| 219 | } else { | ||
| 220 | if (ext) | ||
| 221 | return WIIPROTO_REQ_DRM_KE; | ||
| 222 | else | ||
| 223 | return WIIPROTO_REQ_DRM_K; | ||
| 224 | } | ||
| 347 | } | 225 | } |
| 348 | } | 226 | } |
| 349 | 227 | ||
| 350 | static void wiiproto_req_drm(struct wiimote_data *wdata, __u8 drm) | 228 | void wiiproto_req_drm(struct wiimote_data *wdata, __u8 drm) |
| 351 | { | 229 | { |
| 352 | __u8 cmd[3]; | 230 | __u8 cmd[3]; |
| 353 | 231 | ||
| @@ -358,6 +236,7 @@ static void wiiproto_req_drm(struct wiimote_data *wdata, __u8 drm) | |||
| 358 | cmd[1] = 0; | 236 | cmd[1] = 0; |
| 359 | cmd[2] = drm; | 237 | cmd[2] = drm; |
| 360 | 238 | ||
| 239 | wdata->state.drm = drm; | ||
| 361 | wiiproto_keep_rumble(wdata, &cmd[1]); | 240 | wiiproto_keep_rumble(wdata, &cmd[1]); |
| 362 | wiimote_queue(wdata, cmd, sizeof(cmd)); | 241 | wiimote_queue(wdata, cmd, sizeof(cmd)); |
| 363 | } | 242 | } |
| @@ -440,8 +319,33 @@ static void wiiproto_req_wmem(struct wiimote_data *wdata, bool eeprom, | |||
| 440 | wiimote_queue(wdata, cmd, sizeof(cmd)); | 319 | wiimote_queue(wdata, cmd, sizeof(cmd)); |
| 441 | } | 320 | } |
| 442 | 321 | ||
| 322 | void wiiproto_req_rmem(struct wiimote_data *wdata, bool eeprom, __u32 offset, | ||
| 323 | __u16 size) | ||
| 324 | { | ||
| 325 | __u8 cmd[7]; | ||
| 326 | |||
| 327 | if (size == 0) { | ||
| 328 | hid_warn(wdata->hdev, "Invalid length %d rmem request\n", size); | ||
| 329 | return; | ||
| 330 | } | ||
| 331 | |||
| 332 | cmd[0] = WIIPROTO_REQ_RMEM; | ||
| 333 | cmd[1] = 0; | ||
| 334 | cmd[2] = (offset >> 16) & 0xff; | ||
| 335 | cmd[3] = (offset >> 8) & 0xff; | ||
| 336 | cmd[4] = offset & 0xff; | ||
| 337 | cmd[5] = (size >> 8) & 0xff; | ||
| 338 | cmd[6] = size & 0xff; | ||
| 339 | |||
| 340 | if (!eeprom) | ||
| 341 | cmd[1] |= 0x04; | ||
| 342 | |||
| 343 | wiiproto_keep_rumble(wdata, &cmd[1]); | ||
| 344 | wiimote_queue(wdata, cmd, sizeof(cmd)); | ||
| 345 | } | ||
| 346 | |||
| 443 | /* requries the cmd-mutex to be held */ | 347 | /* requries the cmd-mutex to be held */ |
| 444 | static int wiimote_cmd_write(struct wiimote_data *wdata, __u32 offset, | 348 | int wiimote_cmd_write(struct wiimote_data *wdata, __u32 offset, |
| 445 | const __u8 *wmem, __u8 size) | 349 | const __u8 *wmem, __u8 size) |
| 446 | { | 350 | { |
| 447 | unsigned long flags; | 351 | unsigned long flags; |
| @@ -459,6 +363,36 @@ static int wiimote_cmd_write(struct wiimote_data *wdata, __u32 offset, | |||
| 459 | return ret; | 363 | return ret; |
| 460 | } | 364 | } |
| 461 | 365 | ||
| 366 | /* requries the cmd-mutex to be held */ | ||
| 367 | ssize_t wiimote_cmd_read(struct wiimote_data *wdata, __u32 offset, __u8 *rmem, | ||
| 368 | __u8 size) | ||
| 369 | { | ||
| 370 | unsigned long flags; | ||
| 371 | ssize_t ret; | ||
| 372 | |||
| 373 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
| 374 | wdata->state.cmd_read_size = size; | ||
| 375 | wdata->state.cmd_read_buf = rmem; | ||
| 376 | wiimote_cmd_set(wdata, WIIPROTO_REQ_RMEM, offset & 0xffff); | ||
| 377 | wiiproto_req_rreg(wdata, offset, size); | ||
| 378 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
| 379 | |||
| 380 | ret = wiimote_cmd_wait(wdata); | ||
| 381 | |||
| 382 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
| 383 | wdata->state.cmd_read_buf = NULL; | ||
| 384 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
| 385 | |||
| 386 | if (!ret) { | ||
| 387 | if (wdata->state.cmd_read_size == 0) | ||
| 388 | ret = -EIO; | ||
| 389 | else | ||
| 390 | ret = wdata->state.cmd_read_size; | ||
| 391 | } | ||
| 392 | |||
| 393 | return ret; | ||
| 394 | } | ||
| 395 | |||
| 462 | static int wiimote_battery_get_property(struct power_supply *psy, | 396 | static int wiimote_battery_get_property(struct power_supply *psy, |
| 463 | enum power_supply_property psp, | 397 | enum power_supply_property psp, |
| 464 | union power_supply_propval *val) | 398 | union power_supply_propval *val) |
| @@ -862,6 +796,8 @@ static void handler_status(struct wiimote_data *wdata, const __u8 *payload) | |||
| 862 | /* on status reports the drm is reset so we need to resend the drm */ | 796 | /* on status reports the drm is reset so we need to resend the drm */ |
| 863 | wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL); | 797 | wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL); |
| 864 | 798 | ||
| 799 | wiiext_event(wdata, payload[2] & 0x02); | ||
| 800 | |||
| 865 | if (wiimote_cmd_pending(wdata, WIIPROTO_REQ_SREQ, 0)) { | 801 | if (wiimote_cmd_pending(wdata, WIIPROTO_REQ_SREQ, 0)) { |
| 866 | wdata->state.cmd_battery = payload[5]; | 802 | wdata->state.cmd_battery = payload[5]; |
| 867 | wiimote_cmd_complete(wdata); | 803 | wiimote_cmd_complete(wdata); |
| @@ -870,7 +806,23 @@ static void handler_status(struct wiimote_data *wdata, const __u8 *payload) | |||
| 870 | 806 | ||
| 871 | static void handler_data(struct wiimote_data *wdata, const __u8 *payload) | 807 | static void handler_data(struct wiimote_data *wdata, const __u8 *payload) |
| 872 | { | 808 | { |
| 809 | __u16 offset = payload[3] << 8 | payload[4]; | ||
| 810 | __u8 size = (payload[2] >> 4) + 1; | ||
| 811 | __u8 err = payload[2] & 0x0f; | ||
| 812 | |||
| 873 | handler_keys(wdata, payload); | 813 | handler_keys(wdata, payload); |
| 814 | |||
| 815 | if (wiimote_cmd_pending(wdata, WIIPROTO_REQ_RMEM, offset)) { | ||
| 816 | if (err) | ||
| 817 | size = 0; | ||
| 818 | else if (size > wdata->state.cmd_read_size) | ||
| 819 | size = wdata->state.cmd_read_size; | ||
| 820 | |||
| 821 | wdata->state.cmd_read_size = size; | ||
| 822 | if (wdata->state.cmd_read_buf) | ||
| 823 | memcpy(wdata->state.cmd_read_buf, &payload[5], size); | ||
| 824 | wiimote_cmd_complete(wdata); | ||
| 825 | } | ||
| 874 | } | 826 | } |
| 875 | 827 | ||
| 876 | static void handler_return(struct wiimote_data *wdata, const __u8 *payload) | 828 | static void handler_return(struct wiimote_data *wdata, const __u8 *payload) |
| @@ -898,6 +850,7 @@ static void handler_drm_KA(struct wiimote_data *wdata, const __u8 *payload) | |||
| 898 | static void handler_drm_KE(struct wiimote_data *wdata, const __u8 *payload) | 850 | static void handler_drm_KE(struct wiimote_data *wdata, const __u8 *payload) |
| 899 | { | 851 | { |
| 900 | handler_keys(wdata, payload); | 852 | handler_keys(wdata, payload); |
| 853 | wiiext_handle(wdata, &payload[2]); | ||
| 901 | } | 854 | } |
| 902 | 855 | ||
| 903 | static void handler_drm_KAI(struct wiimote_data *wdata, const __u8 *payload) | 856 | static void handler_drm_KAI(struct wiimote_data *wdata, const __u8 *payload) |
| @@ -914,6 +867,7 @@ static void handler_drm_KAI(struct wiimote_data *wdata, const __u8 *payload) | |||
| 914 | static void handler_drm_KEE(struct wiimote_data *wdata, const __u8 *payload) | 867 | static void handler_drm_KEE(struct wiimote_data *wdata, const __u8 *payload) |
| 915 | { | 868 | { |
| 916 | handler_keys(wdata, payload); | 869 | handler_keys(wdata, payload); |
| 870 | wiiext_handle(wdata, &payload[2]); | ||
| 917 | } | 871 | } |
| 918 | 872 | ||
| 919 | static void handler_drm_KIE(struct wiimote_data *wdata, const __u8 *payload) | 873 | static void handler_drm_KIE(struct wiimote_data *wdata, const __u8 *payload) |
| @@ -924,12 +878,14 @@ static void handler_drm_KIE(struct wiimote_data *wdata, const __u8 *payload) | |||
| 924 | ir_to_input2(wdata, &payload[7], false); | 878 | ir_to_input2(wdata, &payload[7], false); |
| 925 | ir_to_input3(wdata, &payload[9], true); | 879 | ir_to_input3(wdata, &payload[9], true); |
| 926 | input_sync(wdata->ir); | 880 | input_sync(wdata->ir); |
| 881 | wiiext_handle(wdata, &payload[12]); | ||
| 927 | } | 882 | } |
| 928 | 883 | ||
| 929 | static void handler_drm_KAE(struct wiimote_data *wdata, const __u8 *payload) | 884 | static void handler_drm_KAE(struct wiimote_data *wdata, const __u8 *payload) |
| 930 | { | 885 | { |
| 931 | handler_keys(wdata, payload); | 886 | handler_keys(wdata, payload); |
| 932 | handler_accel(wdata, payload); | 887 | handler_accel(wdata, payload); |
| 888 | wiiext_handle(wdata, &payload[5]); | ||
| 933 | } | 889 | } |
| 934 | 890 | ||
| 935 | static void handler_drm_KAIE(struct wiimote_data *wdata, const __u8 *payload) | 891 | static void handler_drm_KAIE(struct wiimote_data *wdata, const __u8 *payload) |
| @@ -941,10 +897,12 @@ static void handler_drm_KAIE(struct wiimote_data *wdata, const __u8 *payload) | |||
| 941 | ir_to_input2(wdata, &payload[10], false); | 897 | ir_to_input2(wdata, &payload[10], false); |
| 942 | ir_to_input3(wdata, &payload[12], true); | 898 | ir_to_input3(wdata, &payload[12], true); |
| 943 | input_sync(wdata->ir); | 899 | input_sync(wdata->ir); |
| 900 | wiiext_handle(wdata, &payload[15]); | ||
| 944 | } | 901 | } |
| 945 | 902 | ||
| 946 | static void handler_drm_E(struct wiimote_data *wdata, const __u8 *payload) | 903 | static void handler_drm_E(struct wiimote_data *wdata, const __u8 *payload) |
| 947 | { | 904 | { |
| 905 | wiiext_handle(wdata, payload); | ||
| 948 | } | 906 | } |
| 949 | 907 | ||
| 950 | static void handler_drm_SKAI1(struct wiimote_data *wdata, const __u8 *payload) | 908 | static void handler_drm_SKAI1(struct wiimote_data *wdata, const __u8 *payload) |
| @@ -1182,6 +1140,7 @@ static struct wiimote_data *wiimote_create(struct hid_device *hdev) | |||
| 1182 | spin_lock_init(&wdata->state.lock); | 1140 | spin_lock_init(&wdata->state.lock); |
| 1183 | init_completion(&wdata->state.ready); | 1141 | init_completion(&wdata->state.ready); |
| 1184 | mutex_init(&wdata->state.sync); | 1142 | mutex_init(&wdata->state.sync); |
| 1143 | wdata->state.drm = WIIPROTO_REQ_DRM_K; | ||
| 1185 | 1144 | ||
| 1186 | return wdata; | 1145 | return wdata; |
| 1187 | 1146 | ||
| @@ -1196,6 +1155,8 @@ err: | |||
| 1196 | 1155 | ||
| 1197 | static void wiimote_destroy(struct wiimote_data *wdata) | 1156 | static void wiimote_destroy(struct wiimote_data *wdata) |
| 1198 | { | 1157 | { |
| 1158 | wiidebug_deinit(wdata); | ||
| 1159 | wiiext_deinit(wdata); | ||
| 1199 | wiimote_leds_destroy(wdata); | 1160 | wiimote_leds_destroy(wdata); |
| 1200 | 1161 | ||
| 1201 | power_supply_unregister(&wdata->battery); | 1162 | power_supply_unregister(&wdata->battery); |
| @@ -1214,6 +1175,8 @@ static int wiimote_hid_probe(struct hid_device *hdev, | |||
| 1214 | struct wiimote_data *wdata; | 1175 | struct wiimote_data *wdata; |
| 1215 | int ret; | 1176 | int ret; |
| 1216 | 1177 | ||
| 1178 | hdev->quirks |= HID_QUIRK_NO_INIT_REPORTS; | ||
| 1179 | |||
| 1217 | wdata = wiimote_create(hdev); | 1180 | wdata = wiimote_create(hdev); |
| 1218 | if (!wdata) { | 1181 | if (!wdata) { |
| 1219 | hid_err(hdev, "Can't alloc device\n"); | 1182 | hid_err(hdev, "Can't alloc device\n"); |
| @@ -1267,6 +1230,14 @@ static int wiimote_hid_probe(struct hid_device *hdev, | |||
| 1267 | if (ret) | 1230 | if (ret) |
| 1268 | goto err_free; | 1231 | goto err_free; |
| 1269 | 1232 | ||
| 1233 | ret = wiiext_init(wdata); | ||
| 1234 | if (ret) | ||
| 1235 | goto err_free; | ||
| 1236 | |||
| 1237 | ret = wiidebug_init(wdata); | ||
| 1238 | if (ret) | ||
| 1239 | goto err_free; | ||
| 1240 | |||
| 1270 | hid_info(hdev, "New device registered\n"); | 1241 | hid_info(hdev, "New device registered\n"); |
| 1271 | 1242 | ||
| 1272 | /* by default set led1 after device initialization */ | 1243 | /* by default set led1 after device initialization */ |
| @@ -1343,4 +1314,3 @@ module_exit(wiimote_exit); | |||
| 1343 | MODULE_LICENSE("GPL"); | 1314 | MODULE_LICENSE("GPL"); |
| 1344 | MODULE_AUTHOR("David Herrmann <dh.herrmann@gmail.com>"); | 1315 | MODULE_AUTHOR("David Herrmann <dh.herrmann@gmail.com>"); |
| 1345 | MODULE_DESCRIPTION(WIIMOTE_NAME " Device Driver"); | 1316 | MODULE_DESCRIPTION(WIIMOTE_NAME " Device Driver"); |
| 1346 | MODULE_VERSION(WIIMOTE_VERSION); | ||
diff --git a/drivers/hid/hid-wiimote-debug.c b/drivers/hid/hid-wiimote-debug.c new file mode 100644 index 000000000000..17dabc1f339e --- /dev/null +++ b/drivers/hid/hid-wiimote-debug.c | |||
| @@ -0,0 +1,227 @@ | |||
| 1 | /* | ||
| 2 | * Debug support for HID Nintendo Wiimote devices | ||
| 3 | * Copyright (c) 2011 David Herrmann | ||
| 4 | */ | ||
| 5 | |||
| 6 | /* | ||
| 7 | * This program is free software; you can redistribute it and/or modify it | ||
| 8 | * under the terms of the GNU General Public License as published by the Free | ||
| 9 | * Software Foundation; either version 2 of the License, or (at your option) | ||
| 10 | * any later version. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include <linux/debugfs.h> | ||
| 14 | #include <linux/module.h> | ||
| 15 | #include <linux/seq_file.h> | ||
| 16 | #include <linux/spinlock.h> | ||
| 17 | #include <linux/uaccess.h> | ||
| 18 | #include "hid-wiimote.h" | ||
| 19 | |||
| 20 | struct wiimote_debug { | ||
| 21 | struct wiimote_data *wdata; | ||
| 22 | struct dentry *eeprom; | ||
| 23 | struct dentry *drm; | ||
| 24 | }; | ||
| 25 | |||
| 26 | static int wiidebug_eeprom_open(struct inode *i, struct file *f) | ||
| 27 | { | ||
| 28 | f->private_data = i->i_private; | ||
| 29 | return 0; | ||
| 30 | } | ||
| 31 | |||
| 32 | static ssize_t wiidebug_eeprom_read(struct file *f, char __user *u, size_t s, | ||
| 33 | loff_t *off) | ||
| 34 | { | ||
| 35 | struct wiimote_debug *dbg = f->private_data; | ||
| 36 | struct wiimote_data *wdata = dbg->wdata; | ||
| 37 | unsigned long flags; | ||
| 38 | ssize_t ret; | ||
| 39 | char buf[16]; | ||
| 40 | __u16 size; | ||
| 41 | |||
| 42 | if (s == 0) | ||
| 43 | return -EINVAL; | ||
| 44 | if (*off > 0xffffff) | ||
| 45 | return 0; | ||
| 46 | if (s > 16) | ||
| 47 | s = 16; | ||
| 48 | |||
| 49 | ret = wiimote_cmd_acquire(wdata); | ||
| 50 | if (ret) | ||
| 51 | return ret; | ||
| 52 | |||
| 53 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
| 54 | wdata->state.cmd_read_size = s; | ||
| 55 | wdata->state.cmd_read_buf = buf; | ||
| 56 | wiimote_cmd_set(wdata, WIIPROTO_REQ_RMEM, *off & 0xffff); | ||
| 57 | wiiproto_req_reeprom(wdata, *off, s); | ||
| 58 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
| 59 | |||
| 60 | ret = wiimote_cmd_wait(wdata); | ||
| 61 | if (!ret) | ||
| 62 | size = wdata->state.cmd_read_size; | ||
| 63 | |||
| 64 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
| 65 | wdata->state.cmd_read_buf = NULL; | ||
| 66 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
| 67 | |||
| 68 | wiimote_cmd_release(wdata); | ||
| 69 | |||
| 70 | if (ret) | ||
| 71 | return ret; | ||
| 72 | else if (size == 0) | ||
| 73 | return -EIO; | ||
| 74 | |||
| 75 | if (copy_to_user(u, buf, size)) | ||
| 76 | return -EFAULT; | ||
| 77 | |||
| 78 | *off += size; | ||
| 79 | ret = size; | ||
| 80 | |||
| 81 | return ret; | ||
| 82 | } | ||
| 83 | |||
| 84 | static const struct file_operations wiidebug_eeprom_fops = { | ||
| 85 | .owner = THIS_MODULE, | ||
| 86 | .open = wiidebug_eeprom_open, | ||
| 87 | .read = wiidebug_eeprom_read, | ||
| 88 | .llseek = generic_file_llseek, | ||
| 89 | }; | ||
| 90 | |||
| 91 | static const char *wiidebug_drmmap[] = { | ||
| 92 | [WIIPROTO_REQ_NULL] = "NULL", | ||
| 93 | [WIIPROTO_REQ_DRM_K] = "K", | ||
| 94 | [WIIPROTO_REQ_DRM_KA] = "KA", | ||
| 95 | [WIIPROTO_REQ_DRM_KE] = "KE", | ||
| 96 | [WIIPROTO_REQ_DRM_KAI] = "KAI", | ||
| 97 | [WIIPROTO_REQ_DRM_KEE] = "KEE", | ||
| 98 | [WIIPROTO_REQ_DRM_KAE] = "KAE", | ||
| 99 | [WIIPROTO_REQ_DRM_KIE] = "KIE", | ||
| 100 | [WIIPROTO_REQ_DRM_KAIE] = "KAIE", | ||
| 101 | [WIIPROTO_REQ_DRM_E] = "E", | ||
| 102 | [WIIPROTO_REQ_DRM_SKAI1] = "SKAI1", | ||
| 103 | [WIIPROTO_REQ_DRM_SKAI2] = "SKAI2", | ||
| 104 | [WIIPROTO_REQ_MAX] = NULL | ||
| 105 | }; | ||
| 106 | |||
| 107 | static int wiidebug_drm_show(struct seq_file *f, void *p) | ||
| 108 | { | ||
| 109 | struct wiimote_debug *dbg = f->private; | ||
| 110 | const char *str = NULL; | ||
| 111 | unsigned long flags; | ||
| 112 | __u8 drm; | ||
| 113 | |||
| 114 | spin_lock_irqsave(&dbg->wdata->state.lock, flags); | ||
| 115 | drm = dbg->wdata->state.drm; | ||
| 116 | spin_unlock_irqrestore(&dbg->wdata->state.lock, flags); | ||
| 117 | |||
| 118 | if (drm < WIIPROTO_REQ_MAX) | ||
| 119 | str = wiidebug_drmmap[drm]; | ||
| 120 | if (!str) | ||
| 121 | str = "unknown"; | ||
| 122 | |||
| 123 | seq_printf(f, "%s\n", str); | ||
| 124 | |||
| 125 | return 0; | ||
| 126 | } | ||
| 127 | |||
| 128 | static int wiidebug_drm_open(struct inode *i, struct file *f) | ||
| 129 | { | ||
| 130 | return single_open(f, wiidebug_drm_show, i->i_private); | ||
| 131 | } | ||
| 132 | |||
| 133 | static ssize_t wiidebug_drm_write(struct file *f, const char __user *u, | ||
| 134 | size_t s, loff_t *off) | ||
| 135 | { | ||
| 136 | struct wiimote_debug *dbg = f->private_data; | ||
| 137 | unsigned long flags; | ||
| 138 | char buf[16]; | ||
| 139 | ssize_t len; | ||
| 140 | int i; | ||
| 141 | |||
| 142 | if (s == 0) | ||
| 143 | return -EINVAL; | ||
| 144 | |||
| 145 | len = min((size_t) 15, s); | ||
| 146 | if (copy_from_user(buf, u, len)) | ||
| 147 | return -EFAULT; | ||
| 148 | |||
| 149 | buf[15] = 0; | ||
| 150 | |||
| 151 | for (i = 0; i < WIIPROTO_REQ_MAX; ++i) { | ||
| 152 | if (!wiidebug_drmmap[i]) | ||
| 153 | continue; | ||
| 154 | if (!strcasecmp(buf, wiidebug_drmmap[i])) | ||
| 155 | break; | ||
| 156 | } | ||
| 157 | |||
| 158 | if (i == WIIPROTO_REQ_MAX) | ||
| 159 | i = simple_strtoul(buf, NULL, 10); | ||
| 160 | |||
| 161 | spin_lock_irqsave(&dbg->wdata->state.lock, flags); | ||
| 162 | wiiproto_req_drm(dbg->wdata, (__u8) i); | ||
| 163 | spin_unlock_irqrestore(&dbg->wdata->state.lock, flags); | ||
| 164 | |||
| 165 | return len; | ||
| 166 | } | ||
| 167 | |||
| 168 | static const struct file_operations wiidebug_drm_fops = { | ||
| 169 | .owner = THIS_MODULE, | ||
| 170 | .open = wiidebug_drm_open, | ||
| 171 | .read = seq_read, | ||
| 172 | .llseek = seq_lseek, | ||
| 173 | .write = wiidebug_drm_write, | ||
| 174 | .release = single_release, | ||
| 175 | }; | ||
| 176 | |||
| 177 | int wiidebug_init(struct wiimote_data *wdata) | ||
| 178 | { | ||
| 179 | struct wiimote_debug *dbg; | ||
| 180 | unsigned long flags; | ||
| 181 | int ret = -ENOMEM; | ||
| 182 | |||
| 183 | dbg = kzalloc(sizeof(*dbg), GFP_KERNEL); | ||
| 184 | if (!dbg) | ||
| 185 | return -ENOMEM; | ||
| 186 | |||
| 187 | dbg->wdata = wdata; | ||
| 188 | |||
| 189 | dbg->eeprom = debugfs_create_file("eeprom", S_IRUSR, | ||
| 190 | dbg->wdata->hdev->debug_dir, dbg, &wiidebug_eeprom_fops); | ||
| 191 | if (!dbg->eeprom) | ||
| 192 | goto err; | ||
| 193 | |||
| 194 | dbg->drm = debugfs_create_file("drm", S_IRUSR, | ||
| 195 | dbg->wdata->hdev->debug_dir, dbg, &wiidebug_drm_fops); | ||
| 196 | if (!dbg->drm) | ||
| 197 | goto err_drm; | ||
| 198 | |||
| 199 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
| 200 | wdata->debug = dbg; | ||
| 201 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
| 202 | |||
| 203 | return 0; | ||
| 204 | |||
| 205 | err_drm: | ||
| 206 | debugfs_remove(dbg->eeprom); | ||
| 207 | err: | ||
| 208 | kfree(dbg); | ||
| 209 | return ret; | ||
| 210 | } | ||
| 211 | |||
| 212 | void wiidebug_deinit(struct wiimote_data *wdata) | ||
| 213 | { | ||
| 214 | struct wiimote_debug *dbg = wdata->debug; | ||
| 215 | unsigned long flags; | ||
| 216 | |||
| 217 | if (!dbg) | ||
| 218 | return; | ||
| 219 | |||
| 220 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
| 221 | wdata->debug = NULL; | ||
| 222 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
| 223 | |||
| 224 | debugfs_remove(dbg->drm); | ||
| 225 | debugfs_remove(dbg->eeprom); | ||
| 226 | kfree(dbg); | ||
| 227 | } | ||
diff --git a/drivers/hid/hid-wiimote-ext.c b/drivers/hid/hid-wiimote-ext.c new file mode 100644 index 000000000000..aa958706c0e5 --- /dev/null +++ b/drivers/hid/hid-wiimote-ext.c | |||
| @@ -0,0 +1,752 @@ | |||
| 1 | /* | ||
| 2 | * HID driver for Nintendo Wiimote extension devices | ||
| 3 | * Copyright (c) 2011 David Herrmann | ||
| 4 | */ | ||
| 5 | |||
| 6 | /* | ||
| 7 | * This program is free software; you can redistribute it and/or modify it | ||
| 8 | * under the terms of the GNU General Public License as published by the Free | ||
| 9 | * Software Foundation; either version 2 of the License, or (at your option) | ||
| 10 | * any later version. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include <linux/atomic.h> | ||
| 14 | #include <linux/module.h> | ||
| 15 | #include <linux/spinlock.h> | ||
| 16 | #include <linux/workqueue.h> | ||
| 17 | #include "hid-wiimote.h" | ||
| 18 | |||
| 19 | struct wiimote_ext { | ||
| 20 | struct wiimote_data *wdata; | ||
| 21 | struct work_struct worker; | ||
| 22 | struct input_dev *input; | ||
| 23 | struct input_dev *mp_input; | ||
| 24 | |||
| 25 | atomic_t opened; | ||
| 26 | atomic_t mp_opened; | ||
| 27 | bool plugged; | ||
| 28 | bool mp_plugged; | ||
| 29 | bool motionp; | ||
| 30 | __u8 ext_type; | ||
| 31 | }; | ||
| 32 | |||
| 33 | enum wiiext_type { | ||
| 34 | WIIEXT_NONE, /* placeholder */ | ||
| 35 | WIIEXT_CLASSIC, /* Nintendo classic controller */ | ||
| 36 | WIIEXT_NUNCHUCK, /* Nintendo nunchuck controller */ | ||
| 37 | }; | ||
| 38 | |||
| 39 | enum wiiext_keys { | ||
| 40 | WIIEXT_KEY_C, | ||
| 41 | WIIEXT_KEY_Z, | ||
| 42 | WIIEXT_KEY_A, | ||
| 43 | WIIEXT_KEY_B, | ||
| 44 | WIIEXT_KEY_X, | ||
| 45 | WIIEXT_KEY_Y, | ||
| 46 | WIIEXT_KEY_ZL, | ||
| 47 | WIIEXT_KEY_ZR, | ||
| 48 | WIIEXT_KEY_PLUS, | ||
| 49 | WIIEXT_KEY_MINUS, | ||
| 50 | WIIEXT_KEY_HOME, | ||
| 51 | WIIEXT_KEY_LEFT, | ||
| 52 | WIIEXT_KEY_RIGHT, | ||
| 53 | WIIEXT_KEY_UP, | ||
| 54 | WIIEXT_KEY_DOWN, | ||
| 55 | WIIEXT_KEY_LT, | ||
| 56 | WIIEXT_KEY_RT, | ||
| 57 | WIIEXT_KEY_COUNT | ||
| 58 | }; | ||
| 59 | |||
| 60 | static __u16 wiiext_keymap[] = { | ||
| 61 | BTN_C, /* WIIEXT_KEY_C */ | ||
| 62 | BTN_Z, /* WIIEXT_KEY_Z */ | ||
| 63 | BTN_A, /* WIIEXT_KEY_A */ | ||
| 64 | BTN_B, /* WIIEXT_KEY_B */ | ||
| 65 | BTN_X, /* WIIEXT_KEY_X */ | ||
| 66 | BTN_Y, /* WIIEXT_KEY_Y */ | ||
| 67 | BTN_TL2, /* WIIEXT_KEY_ZL */ | ||
| 68 | BTN_TR2, /* WIIEXT_KEY_ZR */ | ||
| 69 | KEY_NEXT, /* WIIEXT_KEY_PLUS */ | ||
| 70 | KEY_PREVIOUS, /* WIIEXT_KEY_MINUS */ | ||
| 71 | BTN_MODE, /* WIIEXT_KEY_HOME */ | ||
| 72 | KEY_LEFT, /* WIIEXT_KEY_LEFT */ | ||
| 73 | KEY_RIGHT, /* WIIEXT_KEY_RIGHT */ | ||
| 74 | KEY_UP, /* WIIEXT_KEY_UP */ | ||
| 75 | KEY_DOWN, /* WIIEXT_KEY_DOWN */ | ||
| 76 | BTN_TL, /* WIIEXT_KEY_LT */ | ||
| 77 | BTN_TR, /* WIIEXT_KEY_RT */ | ||
| 78 | }; | ||
| 79 | |||
| 80 | /* diable all extensions */ | ||
| 81 | static void ext_disable(struct wiimote_ext *ext) | ||
| 82 | { | ||
| 83 | unsigned long flags; | ||
| 84 | __u8 wmem = 0x55; | ||
| 85 | |||
| 86 | if (!wiimote_cmd_acquire(ext->wdata)) { | ||
| 87 | wiimote_cmd_write(ext->wdata, 0xa400f0, &wmem, sizeof(wmem)); | ||
| 88 | wiimote_cmd_release(ext->wdata); | ||
| 89 | } | ||
| 90 | |||
| 91 | spin_lock_irqsave(&ext->wdata->state.lock, flags); | ||
| 92 | ext->motionp = false; | ||
| 93 | ext->ext_type = WIIEXT_NONE; | ||
| 94 | wiiproto_req_drm(ext->wdata, WIIPROTO_REQ_NULL); | ||
| 95 | spin_unlock_irqrestore(&ext->wdata->state.lock, flags); | ||
| 96 | } | ||
| 97 | |||
| 98 | static bool motionp_read(struct wiimote_ext *ext) | ||
| 99 | { | ||
| 100 | __u8 rmem[2], wmem; | ||
| 101 | ssize_t ret; | ||
| 102 | bool avail = false; | ||
| 103 | |||
| 104 | if (!atomic_read(&ext->mp_opened)) | ||
| 105 | return false; | ||
| 106 | |||
| 107 | if (wiimote_cmd_acquire(ext->wdata)) | ||
| 108 | return false; | ||
| 109 | |||
| 110 | /* initialize motion plus */ | ||
| 111 | wmem = 0x55; | ||
| 112 | ret = wiimote_cmd_write(ext->wdata, 0xa600f0, &wmem, sizeof(wmem)); | ||
| 113 | if (ret) | ||
| 114 | goto error; | ||
| 115 | |||
| 116 | /* read motion plus ID */ | ||
| 117 | ret = wiimote_cmd_read(ext->wdata, 0xa600fe, rmem, 2); | ||
| 118 | if (ret == 2 || rmem[1] == 0x5) | ||
| 119 | avail = true; | ||
| 120 | |||
| 121 | error: | ||
| 122 | wiimote_cmd_release(ext->wdata); | ||
| 123 | return avail; | ||
| 124 | } | ||
| 125 | |||
| 126 | static __u8 ext_read(struct wiimote_ext *ext) | ||
| 127 | { | ||
| 128 | ssize_t ret; | ||
| 129 | __u8 rmem[2], wmem; | ||
| 130 | __u8 type = WIIEXT_NONE; | ||
| 131 | |||
| 132 | if (!ext->plugged || !atomic_read(&ext->opened)) | ||
| 133 | return WIIEXT_NONE; | ||
| 134 | |||
| 135 | if (wiimote_cmd_acquire(ext->wdata)) | ||
| 136 | return WIIEXT_NONE; | ||
| 137 | |||
| 138 | /* initialize extension */ | ||
| 139 | wmem = 0x55; | ||
| 140 | ret = wiimote_cmd_write(ext->wdata, 0xa400f0, &wmem, sizeof(wmem)); | ||
| 141 | if (!ret) { | ||
| 142 | /* disable encryption */ | ||
| 143 | wmem = 0x0; | ||
| 144 | wiimote_cmd_write(ext->wdata, 0xa400fb, &wmem, sizeof(wmem)); | ||
| 145 | } | ||
| 146 | |||
| 147 | /* read extension ID */ | ||
| 148 | ret = wiimote_cmd_read(ext->wdata, 0xa400fe, rmem, 2); | ||
| 149 | if (ret == 2) { | ||
| 150 | if (rmem[0] == 0 && rmem[1] == 0) | ||
| 151 | type = WIIEXT_NUNCHUCK; | ||
| 152 | else if (rmem[0] == 0x01 && rmem[1] == 0x01) | ||
| 153 | type = WIIEXT_CLASSIC; | ||
| 154 | } | ||
| 155 | |||
| 156 | wiimote_cmd_release(ext->wdata); | ||
| 157 | |||
| 158 | return type; | ||
| 159 | } | ||
| 160 | |||
| 161 | static void ext_enable(struct wiimote_ext *ext, bool motionp, __u8 ext_type) | ||
| 162 | { | ||
| 163 | unsigned long flags; | ||
| 164 | __u8 wmem; | ||
| 165 | int ret; | ||
| 166 | |||
| 167 | if (motionp) { | ||
| 168 | if (wiimote_cmd_acquire(ext->wdata)) | ||
| 169 | return; | ||
| 170 | |||
| 171 | if (ext_type == WIIEXT_CLASSIC) | ||
| 172 | wmem = 0x07; | ||
| 173 | else if (ext_type == WIIEXT_NUNCHUCK) | ||
| 174 | wmem = 0x05; | ||
| 175 | else | ||
| 176 | wmem = 0x04; | ||
| 177 | |||
| 178 | ret = wiimote_cmd_write(ext->wdata, 0xa600fe, &wmem, sizeof(wmem)); | ||
| 179 | wiimote_cmd_release(ext->wdata); | ||
| 180 | if (ret) | ||
| 181 | return; | ||
| 182 | } | ||
| 183 | |||
| 184 | spin_lock_irqsave(&ext->wdata->state.lock, flags); | ||
| 185 | ext->motionp = motionp; | ||
| 186 | ext->ext_type = ext_type; | ||
| 187 | wiiproto_req_drm(ext->wdata, WIIPROTO_REQ_NULL); | ||
| 188 | spin_unlock_irqrestore(&ext->wdata->state.lock, flags); | ||
| 189 | } | ||
| 190 | |||
| 191 | static void wiiext_worker(struct work_struct *work) | ||
| 192 | { | ||
| 193 | struct wiimote_ext *ext = container_of(work, struct wiimote_ext, | ||
| 194 | worker); | ||
| 195 | bool motionp; | ||
| 196 | __u8 ext_type; | ||
| 197 | |||
| 198 | ext_disable(ext); | ||
| 199 | motionp = motionp_read(ext); | ||
| 200 | ext_type = ext_read(ext); | ||
| 201 | ext_enable(ext, motionp, ext_type); | ||
| 202 | } | ||
| 203 | |||
| 204 | /* schedule work only once, otherwise mark for reschedule */ | ||
| 205 | static void wiiext_schedule(struct wiimote_ext *ext) | ||
| 206 | { | ||
| 207 | queue_work(system_nrt_wq, &ext->worker); | ||
| 208 | } | ||
| 209 | |||
| 210 | /* | ||
| 211 | * Reacts on extension port events | ||
| 212 | * Whenever the driver gets an event from the wiimote that an extension has been | ||
| 213 | * plugged or unplugged, this funtion shall be called. It checks what extensions | ||
| 214 | * are connected and initializes and activates them. | ||
| 215 | * This can be called in atomic context. The initialization is done in a | ||
| 216 | * separate worker thread. The state.lock spinlock must be held by the caller. | ||
| 217 | */ | ||
| 218 | void wiiext_event(struct wiimote_data *wdata, bool plugged) | ||
| 219 | { | ||
| 220 | if (!wdata->ext) | ||
| 221 | return; | ||
| 222 | |||
| 223 | if (wdata->ext->plugged == plugged) | ||
| 224 | return; | ||
| 225 | |||
| 226 | wdata->ext->plugged = plugged; | ||
| 227 | |||
| 228 | if (!plugged) | ||
| 229 | wdata->ext->mp_plugged = false; | ||
| 230 | |||
| 231 | /* | ||
| 232 | * We need to call wiiext_schedule(wdata->ext) here, however, the | ||
| 233 | * extension initialization logic is not fully understood and so | ||
| 234 | * automatic initialization is not supported, yet. | ||
| 235 | */ | ||
| 236 | } | ||
| 237 | |||
| 238 | /* | ||
| 239 | * Returns true if the current DRM mode should contain extension data and false | ||
| 240 | * if there is no interest in extension data. | ||
| 241 | * All supported extensions send 6 byte extension data so any DRM that contains | ||
| 242 | * extension bytes is fine. | ||
| 243 | * The caller must hold the state.lock spinlock. | ||
| 244 | */ | ||
| 245 | bool wiiext_active(struct wiimote_data *wdata) | ||
| 246 | { | ||
| 247 | if (!wdata->ext) | ||
| 248 | return false; | ||
| 249 | |||
| 250 | return wdata->ext->motionp || wdata->ext->ext_type; | ||
| 251 | } | ||
| 252 | |||
| 253 | static void handler_motionp(struct wiimote_ext *ext, const __u8 *payload) | ||
| 254 | { | ||
| 255 | __s32 x, y, z; | ||
| 256 | bool plugged; | ||
| 257 | |||
| 258 | /* | 8 7 6 5 4 3 | 2 | 1 | | ||
| 259 | * -----+------------------------------+-----+-----+ | ||
| 260 | * 1 | Yaw Speed <7:0> | | ||
| 261 | * 2 | Roll Speed <7:0> | | ||
| 262 | * 3 | Pitch Speed <7:0> | | ||
| 263 | * -----+------------------------------+-----+-----+ | ||
| 264 | * 4 | Yaw Speed <13:8> | Yaw |Pitch| | ||
| 265 | * -----+------------------------------+-----+-----+ | ||
| 266 | * 5 | Roll Speed <13:8> |Roll | Ext | | ||
| 267 | * -----+------------------------------+-----+-----+ | ||
| 268 | * 6 | Pitch Speed <13:8> | 1 | 0 | | ||
| 269 | * -----+------------------------------+-----+-----+ | ||
| 270 | * The single bits Yaw, Roll, Pitch in the lower right corner specify | ||
| 271 | * whether the wiimote is rotating fast (0) or slow (1). Speed for slow | ||
| 272 | * roation is 440 deg/s and for fast rotation 2000 deg/s. To get a | ||
| 273 | * linear scale we multiply by 2000/440 = ~4.5454 which is 18 for fast | ||
| 274 | * and 9 for slow. | ||
| 275 | * If the wiimote is not rotating the sensor reports 2^13 = 8192. | ||
| 276 | * Ext specifies whether an extension is connected to the motionp. | ||
| 277 | */ | ||
| 278 | |||
| 279 | x = payload[0]; | ||
| 280 | y = payload[1]; | ||
| 281 | z = payload[2]; | ||
| 282 | |||
| 283 | x |= (((__u16)payload[3]) << 6) & 0xff00; | ||
| 284 | y |= (((__u16)payload[4]) << 6) & 0xff00; | ||
| 285 | z |= (((__u16)payload[5]) << 6) & 0xff00; | ||
| 286 | |||
| 287 | x -= 8192; | ||
| 288 | y -= 8192; | ||
| 289 | z -= 8192; | ||
| 290 | |||
| 291 | if (!(payload[3] & 0x02)) | ||
| 292 | x *= 18; | ||
| 293 | else | ||
| 294 | x *= 9; | ||
| 295 | if (!(payload[4] & 0x02)) | ||
| 296 | y *= 18; | ||
| 297 | else | ||
| 298 | y *= 9; | ||
| 299 | if (!(payload[3] & 0x01)) | ||
| 300 | z *= 18; | ||
| 301 | else | ||
| 302 | z *= 9; | ||
| 303 | |||
| 304 | input_report_abs(ext->mp_input, ABS_RX, x); | ||
| 305 | input_report_abs(ext->mp_input, ABS_RY, y); | ||
| 306 | input_report_abs(ext->mp_input, ABS_RZ, z); | ||
| 307 | input_sync(ext->mp_input); | ||
| 308 | |||
| 309 | plugged = payload[5] & 0x01; | ||
| 310 | if (plugged != ext->mp_plugged) | ||
| 311 | ext->mp_plugged = plugged; | ||
| 312 | } | ||
| 313 | |||
| 314 | static void handler_nunchuck(struct wiimote_ext *ext, const __u8 *payload) | ||
| 315 | { | ||
| 316 | __s16 x, y, z, bx, by; | ||
| 317 | |||
| 318 | /* Byte | 8 7 | 6 5 | 4 3 | 2 | 1 | | ||
| 319 | * -----+----------+---------+---------+----+-----+ | ||
| 320 | * 1 | Button X <7:0> | | ||
| 321 | * 2 | Button Y <7:0> | | ||
| 322 | * -----+----------+---------+---------+----+-----+ | ||
| 323 | * 3 | Speed X <9:2> | | ||
| 324 | * 4 | Speed Y <9:2> | | ||
| 325 | * 5 | Speed Z <9:2> | | ||
| 326 | * -----+----------+---------+---------+----+-----+ | ||
| 327 | * 6 | Z <1:0> | Y <1:0> | X <1:0> | BC | BZ | | ||
| 328 | * -----+----------+---------+---------+----+-----+ | ||
| 329 | * Button X/Y is the analog stick. Speed X, Y and Z are the | ||
| 330 | * accelerometer data in the same format as the wiimote's accelerometer. | ||
| 331 | * The 6th byte contains the LSBs of the accelerometer data. | ||
| 332 | * BC and BZ are the C and Z buttons: 0 means pressed | ||
| 333 | * | ||
| 334 | * If reported interleaved with motionp, then the layout changes. The | ||
| 335 | * 5th and 6th byte changes to: | ||
| 336 | * -----+-----------------------------------+-----+ | ||
| 337 | * 5 | Speed Z <9:3> | EXT | | ||
| 338 | * -----+--------+-----+-----+----+----+----+-----+ | ||
| 339 | * 6 |Z <2:1> |Y <1>|X <1>| BC | BZ | 0 | 0 | | ||
| 340 | * -----+--------+-----+-----+----+----+----+-----+ | ||
| 341 | * All three accelerometer values lose their LSB. The other data is | ||
| 342 | * still available but slightly moved. | ||
| 343 | * | ||
| 344 | * Center data for button values is 128. Center value for accelerometer | ||
| 345 | * values it 512 / 0x200 | ||
| 346 | */ | ||
| 347 | |||
| 348 | bx = payload[0]; | ||
| 349 | by = payload[1]; | ||
| 350 | bx -= 128; | ||
| 351 | by -= 128; | ||
| 352 | |||
| 353 | x = payload[2] << 2; | ||
| 354 | y = payload[3] << 2; | ||
| 355 | z = payload[4] << 2; | ||
| 356 | |||
| 357 | if (ext->motionp) { | ||
| 358 | x |= (payload[5] >> 3) & 0x02; | ||
| 359 | y |= (payload[5] >> 4) & 0x02; | ||
| 360 | z &= ~0x4; | ||
| 361 | z |= (payload[5] >> 5) & 0x06; | ||
| 362 | } else { | ||
| 363 | x |= (payload[5] >> 2) & 0x03; | ||
| 364 | y |= (payload[5] >> 4) & 0x03; | ||
| 365 | z |= (payload[5] >> 6) & 0x03; | ||
| 366 | } | ||
| 367 | |||
| 368 | x -= 0x200; | ||
| 369 | y -= 0x200; | ||
| 370 | z -= 0x200; | ||
| 371 | |||
| 372 | input_report_abs(ext->input, ABS_HAT0X, bx); | ||
| 373 | input_report_abs(ext->input, ABS_HAT0Y, by); | ||
| 374 | |||
| 375 | input_report_abs(ext->input, ABS_RX, x); | ||
| 376 | input_report_abs(ext->input, ABS_RY, y); | ||
| 377 | input_report_abs(ext->input, ABS_RZ, z); | ||
| 378 | |||
| 379 | if (ext->motionp) { | ||
| 380 | input_report_key(ext->input, | ||
| 381 | wiiext_keymap[WIIEXT_KEY_Z], !!(payload[5] & 0x04)); | ||
| 382 | input_report_key(ext->input, | ||
| 383 | wiiext_keymap[WIIEXT_KEY_C], !!(payload[5] & 0x08)); | ||
| 384 | } else { | ||
| 385 | input_report_key(ext->input, | ||
| 386 | wiiext_keymap[WIIEXT_KEY_Z], !!(payload[5] & 0x01)); | ||
| 387 | input_report_key(ext->input, | ||
| 388 | wiiext_keymap[WIIEXT_KEY_C], !!(payload[5] & 0x02)); | ||
| 389 | } | ||
| 390 | |||
| 391 | input_sync(ext->input); | ||
| 392 | } | ||
| 393 | |||
| 394 | static void handler_classic(struct wiimote_ext *ext, const __u8 *payload) | ||
| 395 | { | ||
| 396 | __s8 rx, ry, lx, ly, lt, rt; | ||
| 397 | |||
| 398 | /* Byte | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | | ||
| 399 | * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | ||
| 400 | * 1 | RX <5:4> | LX <5:0> | | ||
| 401 | * 2 | RX <3:2> | LY <5:0> | | ||
| 402 | * -----+-----+-----+-----+-----------------------------+ | ||
| 403 | * 3 |RX<1>| LT <5:4> | RY <5:1> | | ||
| 404 | * -----+-----+-----------+-----------------------------+ | ||
| 405 | * 4 | LT <3:1> | RT <5:1> | | ||
| 406 | * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | ||
| 407 | * 5 | BDR | BDD | BLT | B- | BH | B+ | BRT | 1 | | ||
| 408 | * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | ||
| 409 | * 6 | BZL | BB | BY | BA | BX | BZR | BDL | BDU | | ||
| 410 | * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | ||
| 411 | * All buttons are 0 if pressed | ||
| 412 | * RX and RY are right analog stick | ||
| 413 | * LX and LY are left analog stick | ||
| 414 | * LT is left trigger, RT is right trigger | ||
| 415 | * BLT is 0 if left trigger is fully pressed | ||
| 416 | * BRT is 0 if right trigger is fully pressed | ||
| 417 | * BDR, BDD, BDL, BDU form the D-Pad with right, down, left, up buttons | ||
| 418 | * BZL is left Z button and BZR is right Z button | ||
| 419 | * B-, BH, B+ are +, HOME and - buttons | ||
| 420 | * BB, BY, BA, BX are A, B, X, Y buttons | ||
| 421 | * LSB of RX, RY, LT, and RT are not transmitted and always 0. | ||
| 422 | * | ||
| 423 | * With motionp enabled it changes slightly to this: | ||
| 424 | * Byte | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | | ||
| 425 | * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | ||
| 426 | * 1 | RX <4:3> | LX <5:1> | BDU | | ||
| 427 | * 2 | RX <2:1> | LY <5:1> | BDL | | ||
| 428 | * -----+-----+-----+-----+-----------------------+-----+ | ||
| 429 | * 3 |RX<0>| LT <4:3> | RY <4:0> | | ||
| 430 | * -----+-----+-----------+-----------------------------+ | ||
| 431 | * 4 | LT <2:0> | RT <4:0> | | ||
| 432 | * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | ||
| 433 | * 5 | BDR | BDD | BLT | B- | BH | B+ | BRT | EXT | | ||
| 434 | * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | ||
| 435 | * 6 | BZL | BB | BY | BA | BX | BZR | 0 | 0 | | ||
| 436 | * -----+-----+-----+-----+-----+-----+-----+-----+-----+ | ||
| 437 | * Only the LSBs of LX and LY are lost. BDU and BDL are moved, the rest | ||
| 438 | * is the same as before. | ||
| 439 | */ | ||
| 440 | |||
| 441 | if (ext->motionp) { | ||
| 442 | lx = payload[0] & 0x3e; | ||
| 443 | ly = payload[0] & 0x3e; | ||
| 444 | } else { | ||
| 445 | lx = payload[0] & 0x3f; | ||
| 446 | ly = payload[0] & 0x3f; | ||
| 447 | } | ||
| 448 | |||
| 449 | rx = (payload[0] >> 3) & 0x14; | ||
| 450 | rx |= (payload[1] >> 5) & 0x06; | ||
| 451 | rx |= (payload[2] >> 7) & 0x01; | ||
| 452 | ry = payload[2] & 0x1f; | ||
| 453 | |||
| 454 | rt = payload[3] & 0x1f; | ||
| 455 | lt = (payload[2] >> 2) & 0x18; | ||
| 456 | lt |= (payload[3] >> 5) & 0x07; | ||
| 457 | |||
| 458 | rx <<= 1; | ||
| 459 | ry <<= 1; | ||
| 460 | rt <<= 1; | ||
| 461 | lt <<= 1; | ||
| 462 | |||
| 463 | input_report_abs(ext->input, ABS_HAT1X, lx - 0x20); | ||
| 464 | input_report_abs(ext->input, ABS_HAT1Y, ly - 0x20); | ||
| 465 | input_report_abs(ext->input, ABS_HAT2X, rx - 0x20); | ||
| 466 | input_report_abs(ext->input, ABS_HAT2Y, ry - 0x20); | ||
| 467 | input_report_abs(ext->input, ABS_HAT3X, rt - 0x20); | ||
| 468 | input_report_abs(ext->input, ABS_HAT3Y, lt - 0x20); | ||
| 469 | |||
| 470 | input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_RIGHT], | ||
| 471 | !!(payload[4] & 0x80)); | ||
| 472 | input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_DOWN], | ||
| 473 | !!(payload[4] & 0x40)); | ||
| 474 | input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_LT], | ||
| 475 | !!(payload[4] & 0x20)); | ||
| 476 | input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_MINUS], | ||
| 477 | !!(payload[4] & 0x10)); | ||
| 478 | input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_HOME], | ||
| 479 | !!(payload[4] & 0x08)); | ||
| 480 | input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_PLUS], | ||
| 481 | !!(payload[4] & 0x04)); | ||
| 482 | input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_RT], | ||
| 483 | !!(payload[4] & 0x02)); | ||
| 484 | input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_ZL], | ||
| 485 | !!(payload[5] & 0x80)); | ||
| 486 | input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_B], | ||
| 487 | !!(payload[5] & 0x40)); | ||
| 488 | input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_Y], | ||
| 489 | !!(payload[5] & 0x20)); | ||
| 490 | input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_A], | ||
| 491 | !!(payload[5] & 0x10)); | ||
| 492 | input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_X], | ||
| 493 | !!(payload[5] & 0x08)); | ||
| 494 | input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_ZR], | ||
| 495 | !!(payload[5] & 0x04)); | ||
| 496 | |||
| 497 | if (ext->motionp) { | ||
| 498 | input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_UP], | ||
| 499 | !!(payload[0] & 0x01)); | ||
| 500 | input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_LEFT], | ||
| 501 | !!(payload[1] & 0x01)); | ||
| 502 | } else { | ||
| 503 | input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_UP], | ||
| 504 | !!(payload[5] & 0x01)); | ||
| 505 | input_report_key(ext->input, wiiext_keymap[WIIEXT_KEY_LEFT], | ||
| 506 | !!(payload[5] & 0x02)); | ||
| 507 | } | ||
| 508 | |||
| 509 | input_sync(ext->input); | ||
| 510 | } | ||
| 511 | |||
| 512 | /* call this with state.lock spinlock held */ | ||
| 513 | void wiiext_handle(struct wiimote_data *wdata, const __u8 *payload) | ||
| 514 | { | ||
| 515 | struct wiimote_ext *ext = wdata->ext; | ||
| 516 | |||
| 517 | if (!ext) | ||
| 518 | return; | ||
| 519 | |||
| 520 | if (ext->motionp && (payload[5] & 0x02)) { | ||
| 521 | handler_motionp(ext, payload); | ||
| 522 | } else if (ext->ext_type == WIIEXT_NUNCHUCK) { | ||
| 523 | handler_nunchuck(ext, payload); | ||
| 524 | } else if (ext->ext_type == WIIEXT_CLASSIC) { | ||
| 525 | handler_classic(ext, payload); | ||
| 526 | } | ||
| 527 | } | ||
| 528 | |||
| 529 | static ssize_t wiiext_show(struct device *dev, struct device_attribute *attr, | ||
| 530 | char *buf) | ||
| 531 | { | ||
| 532 | struct wiimote_data *wdata = dev_to_wii(dev); | ||
| 533 | __u8 type = WIIEXT_NONE; | ||
| 534 | bool motionp = false; | ||
| 535 | unsigned long flags; | ||
| 536 | |||
| 537 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
| 538 | if (wdata->ext) { | ||
| 539 | motionp = wdata->ext->motionp; | ||
| 540 | type = wdata->ext->ext_type; | ||
| 541 | } | ||
| 542 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
| 543 | |||
| 544 | if (type == WIIEXT_NUNCHUCK) { | ||
| 545 | if (motionp) | ||
| 546 | return sprintf(buf, "motionp+nunchuck\n"); | ||
| 547 | else | ||
| 548 | return sprintf(buf, "nunchuck\n"); | ||
| 549 | } else if (type == WIIEXT_CLASSIC) { | ||
| 550 | if (motionp) | ||
| 551 | return sprintf(buf, "motionp+classic\n"); | ||
| 552 | else | ||
| 553 | return sprintf(buf, "classic\n"); | ||
| 554 | } else { | ||
| 555 | if (motionp) | ||
| 556 | return sprintf(buf, "motionp\n"); | ||
| 557 | else | ||
| 558 | return sprintf(buf, "none\n"); | ||
| 559 | } | ||
| 560 | } | ||
| 561 | |||
| 562 | static DEVICE_ATTR(extension, S_IRUGO, wiiext_show, NULL); | ||
| 563 | |||
| 564 | static int wiiext_input_open(struct input_dev *dev) | ||
| 565 | { | ||
| 566 | struct wiimote_ext *ext = input_get_drvdata(dev); | ||
| 567 | int ret; | ||
| 568 | |||
| 569 | ret = hid_hw_open(ext->wdata->hdev); | ||
| 570 | if (ret) | ||
| 571 | return ret; | ||
| 572 | |||
| 573 | atomic_inc(&ext->opened); | ||
| 574 | wiiext_schedule(ext); | ||
| 575 | |||
| 576 | return 0; | ||
| 577 | } | ||
| 578 | |||
| 579 | static void wiiext_input_close(struct input_dev *dev) | ||
| 580 | { | ||
| 581 | struct wiimote_ext *ext = input_get_drvdata(dev); | ||
| 582 | |||
| 583 | atomic_dec(&ext->opened); | ||
| 584 | wiiext_schedule(ext); | ||
| 585 | hid_hw_close(ext->wdata->hdev); | ||
| 586 | } | ||
| 587 | |||
| 588 | static int wiiext_mp_open(struct input_dev *dev) | ||
| 589 | { | ||
| 590 | struct wiimote_ext *ext = input_get_drvdata(dev); | ||
| 591 | int ret; | ||
| 592 | |||
| 593 | ret = hid_hw_open(ext->wdata->hdev); | ||
| 594 | if (ret) | ||
| 595 | return ret; | ||
| 596 | |||
| 597 | atomic_inc(&ext->mp_opened); | ||
| 598 | wiiext_schedule(ext); | ||
| 599 | |||
| 600 | return 0; | ||
| 601 | } | ||
| 602 | |||
| 603 | static void wiiext_mp_close(struct input_dev *dev) | ||
| 604 | { | ||
| 605 | struct wiimote_ext *ext = input_get_drvdata(dev); | ||
| 606 | |||
| 607 | atomic_dec(&ext->mp_opened); | ||
| 608 | wiiext_schedule(ext); | ||
| 609 | hid_hw_close(ext->wdata->hdev); | ||
| 610 | } | ||
| 611 | |||
| 612 | /* Initializes the extension driver of a wiimote */ | ||
| 613 | int wiiext_init(struct wiimote_data *wdata) | ||
| 614 | { | ||
| 615 | struct wiimote_ext *ext; | ||
| 616 | unsigned long flags; | ||
| 617 | int ret, i; | ||
| 618 | |||
| 619 | ext = kzalloc(sizeof(*ext), GFP_KERNEL); | ||
| 620 | if (!ext) | ||
| 621 | return -ENOMEM; | ||
| 622 | |||
| 623 | ext->wdata = wdata; | ||
| 624 | INIT_WORK(&ext->worker, wiiext_worker); | ||
| 625 | |||
| 626 | ext->input = input_allocate_device(); | ||
| 627 | if (!ext->input) { | ||
| 628 | ret = -ENOMEM; | ||
| 629 | goto err_input; | ||
| 630 | } | ||
| 631 | |||
| 632 | input_set_drvdata(ext->input, ext); | ||
| 633 | ext->input->open = wiiext_input_open; | ||
| 634 | ext->input->close = wiiext_input_close; | ||
| 635 | ext->input->dev.parent = &wdata->hdev->dev; | ||
| 636 | ext->input->id.bustype = wdata->hdev->bus; | ||
| 637 | ext->input->id.vendor = wdata->hdev->vendor; | ||
| 638 | ext->input->id.product = wdata->hdev->product; | ||
| 639 | ext->input->id.version = wdata->hdev->version; | ||
| 640 | ext->input->name = WIIMOTE_NAME " Extension"; | ||
| 641 | |||
| 642 | set_bit(EV_KEY, ext->input->evbit); | ||
| 643 | for (i = 0; i < WIIEXT_KEY_COUNT; ++i) | ||
| 644 | set_bit(wiiext_keymap[i], ext->input->keybit); | ||
| 645 | |||
| 646 | set_bit(EV_ABS, ext->input->evbit); | ||
| 647 | set_bit(ABS_HAT0X, ext->input->absbit); | ||
| 648 | set_bit(ABS_HAT0Y, ext->input->absbit); | ||
| 649 | set_bit(ABS_HAT1X, ext->input->absbit); | ||
| 650 | set_bit(ABS_HAT1Y, ext->input->absbit); | ||
| 651 | set_bit(ABS_HAT2X, ext->input->absbit); | ||
| 652 | set_bit(ABS_HAT2Y, ext->input->absbit); | ||
| 653 | set_bit(ABS_HAT3X, ext->input->absbit); | ||
| 654 | set_bit(ABS_HAT3Y, ext->input->absbit); | ||
| 655 | input_set_abs_params(ext->input, ABS_HAT0X, -120, 120, 2, 4); | ||
| 656 | input_set_abs_params(ext->input, ABS_HAT0Y, -120, 120, 2, 4); | ||
| 657 | input_set_abs_params(ext->input, ABS_HAT1X, -30, 30, 1, 1); | ||
| 658 | input_set_abs_params(ext->input, ABS_HAT1Y, -30, 30, 1, 1); | ||
| 659 | input_set_abs_params(ext->input, ABS_HAT2X, -30, 30, 1, 1); | ||
| 660 | input_set_abs_params(ext->input, ABS_HAT2Y, -30, 30, 1, 1); | ||
| 661 | input_set_abs_params(ext->input, ABS_HAT3X, -30, 30, 1, 1); | ||
| 662 | input_set_abs_params(ext->input, ABS_HAT3Y, -30, 30, 1, 1); | ||
| 663 | set_bit(ABS_RX, ext->input->absbit); | ||
| 664 | set_bit(ABS_RY, ext->input->absbit); | ||
| 665 | set_bit(ABS_RZ, ext->input->absbit); | ||
| 666 | input_set_abs_params(ext->input, ABS_RX, -500, 500, 2, 4); | ||
| 667 | input_set_abs_params(ext->input, ABS_RY, -500, 500, 2, 4); | ||
| 668 | input_set_abs_params(ext->input, ABS_RZ, -500, 500, 2, 4); | ||
| 669 | |||
| 670 | ret = input_register_device(ext->input); | ||
| 671 | if (ret) { | ||
| 672 | input_free_device(ext->input); | ||
| 673 | goto err_input; | ||
| 674 | } | ||
| 675 | |||
| 676 | ext->mp_input = input_allocate_device(); | ||
| 677 | if (!ext->mp_input) { | ||
| 678 | ret = -ENOMEM; | ||
| 679 | goto err_mp; | ||
| 680 | } | ||
| 681 | |||
| 682 | input_set_drvdata(ext->mp_input, ext); | ||
| 683 | ext->mp_input->open = wiiext_mp_open; | ||
| 684 | ext->mp_input->close = wiiext_mp_close; | ||
| 685 | ext->mp_input->dev.parent = &wdata->hdev->dev; | ||
| 686 | ext->mp_input->id.bustype = wdata->hdev->bus; | ||
| 687 | ext->mp_input->id.vendor = wdata->hdev->vendor; | ||
| 688 | ext->mp_input->id.product = wdata->hdev->product; | ||
| 689 | ext->mp_input->id.version = wdata->hdev->version; | ||
| 690 | ext->mp_input->name = WIIMOTE_NAME " Motion+"; | ||
| 691 | |||
| 692 | set_bit(EV_ABS, ext->mp_input->evbit); | ||
| 693 | set_bit(ABS_RX, ext->mp_input->absbit); | ||
| 694 | set_bit(ABS_RY, ext->mp_input->absbit); | ||
| 695 | set_bit(ABS_RZ, ext->mp_input->absbit); | ||
| 696 | input_set_abs_params(ext->mp_input, ABS_RX, -160000, 160000, 4, 8); | ||
| 697 | input_set_abs_params(ext->mp_input, ABS_RY, -160000, 160000, 4, 8); | ||
| 698 | input_set_abs_params(ext->mp_input, ABS_RZ, -160000, 160000, 4, 8); | ||
| 699 | |||
| 700 | ret = input_register_device(ext->mp_input); | ||
| 701 | if (ret) { | ||
| 702 | input_free_device(ext->mp_input); | ||
| 703 | goto err_mp; | ||
| 704 | } | ||
| 705 | |||
| 706 | ret = device_create_file(&wdata->hdev->dev, &dev_attr_extension); | ||
| 707 | if (ret) | ||
| 708 | goto err_dev; | ||
| 709 | |||
| 710 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
| 711 | wdata->ext = ext; | ||
| 712 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
| 713 | |||
| 714 | return 0; | ||
| 715 | |||
| 716 | err_dev: | ||
| 717 | input_unregister_device(ext->mp_input); | ||
| 718 | err_mp: | ||
| 719 | input_unregister_device(ext->input); | ||
| 720 | err_input: | ||
| 721 | kfree(ext); | ||
| 722 | return ret; | ||
| 723 | } | ||
| 724 | |||
| 725 | /* Deinitializes the extension driver of a wiimote */ | ||
| 726 | void wiiext_deinit(struct wiimote_data *wdata) | ||
| 727 | { | ||
| 728 | struct wiimote_ext *ext = wdata->ext; | ||
| 729 | unsigned long flags; | ||
| 730 | |||
| 731 | if (!ext) | ||
| 732 | return; | ||
| 733 | |||
| 734 | /* | ||
| 735 | * We first unset wdata->ext to avoid further input from the wiimote | ||
| 736 | * core. The worker thread does not access this pointer so it is not | ||
| 737 | * affected by this. | ||
| 738 | * We kill the worker after this so it does not get respawned during | ||
| 739 | * deinitialization. | ||
| 740 | */ | ||
| 741 | |||
| 742 | spin_lock_irqsave(&wdata->state.lock, flags); | ||
| 743 | wdata->ext = NULL; | ||
| 744 | spin_unlock_irqrestore(&wdata->state.lock, flags); | ||
| 745 | |||
| 746 | device_remove_file(&wdata->hdev->dev, &dev_attr_extension); | ||
| 747 | input_unregister_device(ext->mp_input); | ||
| 748 | input_unregister_device(ext->input); | ||
| 749 | |||
| 750 | cancel_work_sync(&ext->worker); | ||
| 751 | kfree(ext); | ||
| 752 | } | ||
diff --git a/drivers/hid/hid-wiimote.h b/drivers/hid/hid-wiimote.h new file mode 100644 index 000000000000..c81dbeb086c5 --- /dev/null +++ b/drivers/hid/hid-wiimote.h | |||
| @@ -0,0 +1,208 @@ | |||
| 1 | #ifndef __HID_WIIMOTE_H | ||
| 2 | #define __HID_WIIMOTE_H | ||
| 3 | |||
| 4 | /* | ||
| 5 | * HID driver for Nintendo Wiimote devices | ||
| 6 | * Copyright (c) 2011 David Herrmann | ||
| 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; either version 2 of the License, or (at your option) | ||
| 13 | * any later version. | ||
| 14 | */ | ||
| 15 | |||
| 16 | #include <linux/completion.h> | ||
| 17 | #include <linux/device.h> | ||
| 18 | #include <linux/hid.h> | ||
| 19 | #include <linux/input.h> | ||
| 20 | #include <linux/leds.h> | ||
| 21 | #include <linux/module.h> | ||
| 22 | #include <linux/mutex.h> | ||
| 23 | #include <linux/power_supply.h> | ||
| 24 | #include <linux/spinlock.h> | ||
| 25 | |||
| 26 | #define WIIMOTE_NAME "Nintendo Wii Remote" | ||
| 27 | #define WIIMOTE_BUFSIZE 32 | ||
| 28 | |||
| 29 | #define WIIPROTO_FLAG_LED1 0x01 | ||
| 30 | #define WIIPROTO_FLAG_LED2 0x02 | ||
| 31 | #define WIIPROTO_FLAG_LED3 0x04 | ||
| 32 | #define WIIPROTO_FLAG_LED4 0x08 | ||
| 33 | #define WIIPROTO_FLAG_RUMBLE 0x10 | ||
| 34 | #define WIIPROTO_FLAG_ACCEL 0x20 | ||
| 35 | #define WIIPROTO_FLAG_IR_BASIC 0x40 | ||
| 36 | #define WIIPROTO_FLAG_IR_EXT 0x80 | ||
| 37 | #define WIIPROTO_FLAG_IR_FULL 0xc0 /* IR_BASIC | IR_EXT */ | ||
| 38 | #define WIIPROTO_FLAGS_LEDS (WIIPROTO_FLAG_LED1 | WIIPROTO_FLAG_LED2 | \ | ||
| 39 | WIIPROTO_FLAG_LED3 | WIIPROTO_FLAG_LED4) | ||
| 40 | #define WIIPROTO_FLAGS_IR (WIIPROTO_FLAG_IR_BASIC | WIIPROTO_FLAG_IR_EXT | \ | ||
| 41 | WIIPROTO_FLAG_IR_FULL) | ||
| 42 | |||
| 43 | /* return flag for led \num */ | ||
| 44 | #define WIIPROTO_FLAG_LED(num) (WIIPROTO_FLAG_LED1 << (num - 1)) | ||
| 45 | |||
| 46 | struct wiimote_buf { | ||
| 47 | __u8 data[HID_MAX_BUFFER_SIZE]; | ||
| 48 | size_t size; | ||
| 49 | }; | ||
| 50 | |||
| 51 | struct wiimote_state { | ||
| 52 | spinlock_t lock; | ||
| 53 | __u8 flags; | ||
| 54 | __u8 accel_split[2]; | ||
| 55 | __u8 drm; | ||
| 56 | |||
| 57 | /* synchronous cmd requests */ | ||
| 58 | struct mutex sync; | ||
| 59 | struct completion ready; | ||
| 60 | int cmd; | ||
| 61 | __u32 opt; | ||
| 62 | |||
| 63 | /* results of synchronous requests */ | ||
| 64 | __u8 cmd_battery; | ||
| 65 | __u8 cmd_err; | ||
| 66 | __u8 *cmd_read_buf; | ||
| 67 | __u8 cmd_read_size; | ||
| 68 | }; | ||
| 69 | |||
| 70 | struct wiimote_data { | ||
| 71 | struct hid_device *hdev; | ||
| 72 | struct input_dev *input; | ||
| 73 | struct led_classdev *leds[4]; | ||
| 74 | struct input_dev *accel; | ||
| 75 | struct input_dev *ir; | ||
| 76 | struct power_supply battery; | ||
| 77 | struct wiimote_ext *ext; | ||
| 78 | struct wiimote_debug *debug; | ||
| 79 | |||
| 80 | spinlock_t qlock; | ||
| 81 | __u8 head; | ||
| 82 | __u8 tail; | ||
| 83 | struct wiimote_buf outq[WIIMOTE_BUFSIZE]; | ||
| 84 | struct work_struct worker; | ||
| 85 | |||
| 86 | struct wiimote_state state; | ||
| 87 | }; | ||
| 88 | |||
| 89 | enum wiiproto_reqs { | ||
| 90 | WIIPROTO_REQ_NULL = 0x0, | ||
| 91 | WIIPROTO_REQ_RUMBLE = 0x10, | ||
| 92 | WIIPROTO_REQ_LED = 0x11, | ||
| 93 | WIIPROTO_REQ_DRM = 0x12, | ||
| 94 | WIIPROTO_REQ_IR1 = 0x13, | ||
| 95 | WIIPROTO_REQ_SREQ = 0x15, | ||
| 96 | WIIPROTO_REQ_WMEM = 0x16, | ||
| 97 | WIIPROTO_REQ_RMEM = 0x17, | ||
| 98 | WIIPROTO_REQ_IR2 = 0x1a, | ||
| 99 | WIIPROTO_REQ_STATUS = 0x20, | ||
| 100 | WIIPROTO_REQ_DATA = 0x21, | ||
| 101 | WIIPROTO_REQ_RETURN = 0x22, | ||
| 102 | WIIPROTO_REQ_DRM_K = 0x30, | ||
| 103 | WIIPROTO_REQ_DRM_KA = 0x31, | ||
| 104 | WIIPROTO_REQ_DRM_KE = 0x32, | ||
| 105 | WIIPROTO_REQ_DRM_KAI = 0x33, | ||
| 106 | WIIPROTO_REQ_DRM_KEE = 0x34, | ||
| 107 | WIIPROTO_REQ_DRM_KAE = 0x35, | ||
| 108 | WIIPROTO_REQ_DRM_KIE = 0x36, | ||
| 109 | WIIPROTO_REQ_DRM_KAIE = 0x37, | ||
| 110 | WIIPROTO_REQ_DRM_E = 0x3d, | ||
| 111 | WIIPROTO_REQ_DRM_SKAI1 = 0x3e, | ||
| 112 | WIIPROTO_REQ_DRM_SKAI2 = 0x3f, | ||
| 113 | WIIPROTO_REQ_MAX | ||
| 114 | }; | ||
| 115 | |||
| 116 | #define dev_to_wii(pdev) hid_get_drvdata(container_of(pdev, struct hid_device, \ | ||
| 117 | dev)) | ||
| 118 | |||
| 119 | extern void wiiproto_req_drm(struct wiimote_data *wdata, __u8 drm); | ||
| 120 | extern int wiimote_cmd_write(struct wiimote_data *wdata, __u32 offset, | ||
| 121 | const __u8 *wmem, __u8 size); | ||
| 122 | extern ssize_t wiimote_cmd_read(struct wiimote_data *wdata, __u32 offset, | ||
| 123 | __u8 *rmem, __u8 size); | ||
| 124 | |||
| 125 | #define wiiproto_req_rreg(wdata, os, sz) \ | ||
| 126 | wiiproto_req_rmem((wdata), false, (os), (sz)) | ||
| 127 | #define wiiproto_req_reeprom(wdata, os, sz) \ | ||
| 128 | wiiproto_req_rmem((wdata), true, (os), (sz)) | ||
| 129 | extern void wiiproto_req_rmem(struct wiimote_data *wdata, bool eeprom, | ||
| 130 | __u32 offset, __u16 size); | ||
| 131 | |||
| 132 | #ifdef CONFIG_HID_WIIMOTE_EXT | ||
| 133 | |||
| 134 | extern int wiiext_init(struct wiimote_data *wdata); | ||
| 135 | extern void wiiext_deinit(struct wiimote_data *wdata); | ||
| 136 | extern void wiiext_event(struct wiimote_data *wdata, bool plugged); | ||
| 137 | extern bool wiiext_active(struct wiimote_data *wdata); | ||
| 138 | extern void wiiext_handle(struct wiimote_data *wdata, const __u8 *payload); | ||
| 139 | |||
| 140 | #else | ||
| 141 | |||
| 142 | static inline int wiiext_init(void *u) { return 0; } | ||
| 143 | static inline void wiiext_deinit(void *u) { } | ||
| 144 | static inline void wiiext_event(void *u, bool p) { } | ||
| 145 | static inline bool wiiext_active(void *u) { return false; } | ||
| 146 | static inline void wiiext_handle(void *u, const __u8 *p) { } | ||
| 147 | |||
| 148 | #endif | ||
| 149 | |||
| 150 | #ifdef CONFIG_DEBUG_FS | ||
| 151 | |||
| 152 | extern int wiidebug_init(struct wiimote_data *wdata); | ||
| 153 | extern void wiidebug_deinit(struct wiimote_data *wdata); | ||
| 154 | |||
| 155 | #else | ||
| 156 | |||
| 157 | static inline int wiidebug_init(void *u) { return 0; } | ||
| 158 | static inline void wiidebug_deinit(void *u) { } | ||
| 159 | |||
| 160 | #endif | ||
| 161 | |||
| 162 | /* requires the state.lock spinlock to be held */ | ||
| 163 | static inline bool wiimote_cmd_pending(struct wiimote_data *wdata, int cmd, | ||
| 164 | __u32 opt) | ||
| 165 | { | ||
| 166 | return wdata->state.cmd == cmd && wdata->state.opt == opt; | ||
| 167 | } | ||
| 168 | |||
| 169 | /* requires the state.lock spinlock to be held */ | ||
| 170 | static inline void wiimote_cmd_complete(struct wiimote_data *wdata) | ||
| 171 | { | ||
| 172 | wdata->state.cmd = WIIPROTO_REQ_NULL; | ||
| 173 | complete(&wdata->state.ready); | ||
| 174 | } | ||
| 175 | |||
| 176 | static inline int wiimote_cmd_acquire(struct wiimote_data *wdata) | ||
| 177 | { | ||
| 178 | return mutex_lock_interruptible(&wdata->state.sync) ? -ERESTARTSYS : 0; | ||
| 179 | } | ||
| 180 | |||
| 181 | /* requires the state.lock spinlock to be held */ | ||
| 182 | static inline void wiimote_cmd_set(struct wiimote_data *wdata, int cmd, | ||
| 183 | __u32 opt) | ||
| 184 | { | ||
| 185 | INIT_COMPLETION(wdata->state.ready); | ||
| 186 | wdata->state.cmd = cmd; | ||
| 187 | wdata->state.opt = opt; | ||
| 188 | } | ||
| 189 | |||
| 190 | static inline void wiimote_cmd_release(struct wiimote_data *wdata) | ||
| 191 | { | ||
| 192 | mutex_unlock(&wdata->state.sync); | ||
| 193 | } | ||
| 194 | |||
| 195 | static inline int wiimote_cmd_wait(struct wiimote_data *wdata) | ||
| 196 | { | ||
| 197 | int ret; | ||
| 198 | |||
| 199 | ret = wait_for_completion_interruptible_timeout(&wdata->state.ready, HZ); | ||
| 200 | if (ret < 0) | ||
| 201 | return -ERESTARTSYS; | ||
| 202 | else if (ret == 0) | ||
| 203 | return -EIO; | ||
| 204 | else | ||
| 205 | return 0; | ||
| 206 | } | ||
| 207 | |||
| 208 | #endif | ||
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index b403fcef0b86..5bf91dbad59d 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c | |||
| @@ -197,16 +197,24 @@ static int usbhid_restart_out_queue(struct usbhid_device *usbhid) | |||
| 197 | { | 197 | { |
| 198 | struct hid_device *hid = usb_get_intfdata(usbhid->intf); | 198 | struct hid_device *hid = usb_get_intfdata(usbhid->intf); |
| 199 | int kicked; | 199 | int kicked; |
| 200 | int r; | ||
| 200 | 201 | ||
| 201 | if (!hid) | 202 | if (!hid) |
| 202 | return 0; | 203 | return 0; |
| 203 | 204 | ||
| 204 | if ((kicked = (usbhid->outhead != usbhid->outtail))) { | 205 | if ((kicked = (usbhid->outhead != usbhid->outtail))) { |
| 205 | dbg("Kicking head %d tail %d", usbhid->outhead, usbhid->outtail); | 206 | dbg("Kicking head %d tail %d", usbhid->outhead, usbhid->outtail); |
| 207 | |||
| 208 | r = usb_autopm_get_interface_async(usbhid->intf); | ||
| 209 | if (r < 0) | ||
| 210 | return r; | ||
| 211 | /* Asynchronously flush queue. */ | ||
| 212 | set_bit(HID_OUT_RUNNING, &usbhid->iofl); | ||
| 206 | if (hid_submit_out(hid)) { | 213 | if (hid_submit_out(hid)) { |
| 207 | clear_bit(HID_OUT_RUNNING, &usbhid->iofl); | 214 | clear_bit(HID_OUT_RUNNING, &usbhid->iofl); |
| 208 | wake_up(&usbhid->wait); | 215 | usb_autopm_put_interface_async(usbhid->intf); |
| 209 | } | 216 | } |
| 217 | wake_up(&usbhid->wait); | ||
| 210 | } | 218 | } |
| 211 | return kicked; | 219 | return kicked; |
| 212 | } | 220 | } |
| @@ -215,6 +223,7 @@ static int usbhid_restart_ctrl_queue(struct usbhid_device *usbhid) | |||
| 215 | { | 223 | { |
| 216 | struct hid_device *hid = usb_get_intfdata(usbhid->intf); | 224 | struct hid_device *hid = usb_get_intfdata(usbhid->intf); |
| 217 | int kicked; | 225 | int kicked; |
| 226 | int r; | ||
| 218 | 227 | ||
| 219 | WARN_ON(hid == NULL); | 228 | WARN_ON(hid == NULL); |
| 220 | if (!hid) | 229 | if (!hid) |
| @@ -222,10 +231,17 @@ static int usbhid_restart_ctrl_queue(struct usbhid_device *usbhid) | |||
| 222 | 231 | ||
| 223 | if ((kicked = (usbhid->ctrlhead != usbhid->ctrltail))) { | 232 | if ((kicked = (usbhid->ctrlhead != usbhid->ctrltail))) { |
| 224 | dbg("Kicking head %d tail %d", usbhid->ctrlhead, usbhid->ctrltail); | 233 | dbg("Kicking head %d tail %d", usbhid->ctrlhead, usbhid->ctrltail); |
| 234 | |||
| 235 | r = usb_autopm_get_interface_async(usbhid->intf); | ||
| 236 | if (r < 0) | ||
| 237 | return r; | ||
| 238 | /* Asynchronously flush queue. */ | ||
| 239 | set_bit(HID_CTRL_RUNNING, &usbhid->iofl); | ||
| 225 | if (hid_submit_ctrl(hid)) { | 240 | if (hid_submit_ctrl(hid)) { |
| 226 | clear_bit(HID_CTRL_RUNNING, &usbhid->iofl); | 241 | clear_bit(HID_CTRL_RUNNING, &usbhid->iofl); |
| 227 | wake_up(&usbhid->wait); | 242 | usb_autopm_put_interface_async(usbhid->intf); |
| 228 | } | 243 | } |
| 244 | wake_up(&usbhid->wait); | ||
| 229 | } | 245 | } |
| 230 | return kicked; | 246 | return kicked; |
| 231 | } | 247 | } |
| @@ -304,30 +320,21 @@ static int hid_submit_out(struct hid_device *hid) | |||
| 304 | report = usbhid->out[usbhid->outtail].report; | 320 | report = usbhid->out[usbhid->outtail].report; |
| 305 | raw_report = usbhid->out[usbhid->outtail].raw_report; | 321 | raw_report = usbhid->out[usbhid->outtail].raw_report; |
| 306 | 322 | ||
| 307 | r = usb_autopm_get_interface_async(usbhid->intf); | 323 | usbhid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + |
| 308 | if (r < 0) | 324 | 1 + (report->id > 0); |
| 309 | return -1; | 325 | usbhid->urbout->dev = hid_to_usb_dev(hid); |
| 310 | 326 | memcpy(usbhid->outbuf, raw_report, | |
| 311 | /* | 327 | usbhid->urbout->transfer_buffer_length); |
| 312 | * if the device hasn't been woken, we leave the output | 328 | kfree(raw_report); |
| 313 | * to resume() | ||
| 314 | */ | ||
| 315 | if (!test_bit(HID_REPORTED_IDLE, &usbhid->iofl)) { | ||
| 316 | usbhid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + (report->id > 0); | ||
| 317 | usbhid->urbout->dev = hid_to_usb_dev(hid); | ||
| 318 | memcpy(usbhid->outbuf, raw_report, usbhid->urbout->transfer_buffer_length); | ||
| 319 | kfree(raw_report); | ||
| 320 | 329 | ||
| 321 | dbg_hid("submitting out urb\n"); | 330 | dbg_hid("submitting out urb\n"); |
| 322 | 331 | ||
| 323 | if (usb_submit_urb(usbhid->urbout, GFP_ATOMIC)) { | 332 | r = usb_submit_urb(usbhid->urbout, GFP_ATOMIC); |
| 324 | hid_err(hid, "usb_submit_urb(out) failed\n"); | 333 | if (r < 0) { |
| 325 | usb_autopm_put_interface_async(usbhid->intf); | 334 | hid_err(hid, "usb_submit_urb(out) failed: %d\n", r); |
| 326 | return -1; | 335 | return r; |
| 327 | } | ||
| 328 | usbhid->last_out = jiffies; | ||
| 329 | } | 336 | } |
| 330 | 337 | usbhid->last_out = jiffies; | |
| 331 | return 0; | 338 | return 0; |
| 332 | } | 339 | } |
| 333 | 340 | ||
| @@ -343,50 +350,48 @@ static int hid_submit_ctrl(struct hid_device *hid) | |||
| 343 | raw_report = usbhid->ctrl[usbhid->ctrltail].raw_report; | 350 | raw_report = usbhid->ctrl[usbhid->ctrltail].raw_report; |
| 344 | dir = usbhid->ctrl[usbhid->ctrltail].dir; | 351 | dir = usbhid->ctrl[usbhid->ctrltail].dir; |
| 345 | 352 | ||
| 346 | r = usb_autopm_get_interface_async(usbhid->intf); | 353 | len = ((report->size - 1) >> 3) + 1 + (report->id > 0); |
| 347 | if (r < 0) | 354 | if (dir == USB_DIR_OUT) { |
| 348 | return -1; | 355 | usbhid->urbctrl->pipe = usb_sndctrlpipe(hid_to_usb_dev(hid), 0); |
| 349 | if (!test_bit(HID_REPORTED_IDLE, &usbhid->iofl)) { | 356 | usbhid->urbctrl->transfer_buffer_length = len; |
| 350 | len = ((report->size - 1) >> 3) + 1 + (report->id > 0); | 357 | memcpy(usbhid->ctrlbuf, raw_report, len); |
| 351 | if (dir == USB_DIR_OUT) { | 358 | kfree(raw_report); |
| 352 | usbhid->urbctrl->pipe = usb_sndctrlpipe(hid_to_usb_dev(hid), 0); | 359 | } else { |
| 353 | usbhid->urbctrl->transfer_buffer_length = len; | 360 | int maxpacket, padlen; |
| 354 | memcpy(usbhid->ctrlbuf, raw_report, len); | 361 | |
| 355 | kfree(raw_report); | 362 | usbhid->urbctrl->pipe = usb_rcvctrlpipe(hid_to_usb_dev(hid), 0); |
| 356 | } else { | 363 | maxpacket = usb_maxpacket(hid_to_usb_dev(hid), |
| 357 | int maxpacket, padlen; | 364 | usbhid->urbctrl->pipe, 0); |
| 358 | 365 | if (maxpacket > 0) { | |
| 359 | usbhid->urbctrl->pipe = usb_rcvctrlpipe(hid_to_usb_dev(hid), 0); | 366 | padlen = DIV_ROUND_UP(len, maxpacket); |
| 360 | maxpacket = usb_maxpacket(hid_to_usb_dev(hid), usbhid->urbctrl->pipe, 0); | 367 | padlen *= maxpacket; |
| 361 | if (maxpacket > 0) { | 368 | if (padlen > usbhid->bufsize) |
| 362 | padlen = DIV_ROUND_UP(len, maxpacket); | 369 | padlen = usbhid->bufsize; |
| 363 | padlen *= maxpacket; | 370 | } else |
| 364 | if (padlen > usbhid->bufsize) | 371 | padlen = 0; |
| 365 | padlen = usbhid->bufsize; | 372 | usbhid->urbctrl->transfer_buffer_length = padlen; |
| 366 | } else | ||
| 367 | padlen = 0; | ||
| 368 | usbhid->urbctrl->transfer_buffer_length = padlen; | ||
| 369 | } | ||
| 370 | usbhid->urbctrl->dev = hid_to_usb_dev(hid); | ||
| 371 | |||
| 372 | usbhid->cr->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE | dir; | ||
| 373 | usbhid->cr->bRequest = (dir == USB_DIR_OUT) ? HID_REQ_SET_REPORT : HID_REQ_GET_REPORT; | ||
| 374 | usbhid->cr->wValue = cpu_to_le16(((report->type + 1) << 8) | report->id); | ||
| 375 | usbhid->cr->wIndex = cpu_to_le16(usbhid->ifnum); | ||
| 376 | usbhid->cr->wLength = cpu_to_le16(len); | ||
| 377 | |||
| 378 | dbg_hid("submitting ctrl urb: %s wValue=0x%04x wIndex=0x%04x wLength=%u\n", | ||
| 379 | usbhid->cr->bRequest == HID_REQ_SET_REPORT ? "Set_Report" : "Get_Report", | ||
| 380 | usbhid->cr->wValue, usbhid->cr->wIndex, usbhid->cr->wLength); | ||
| 381 | |||
| 382 | if (usb_submit_urb(usbhid->urbctrl, GFP_ATOMIC)) { | ||
| 383 | usb_autopm_put_interface_async(usbhid->intf); | ||
| 384 | hid_err(hid, "usb_submit_urb(ctrl) failed\n"); | ||
| 385 | return -1; | ||
| 386 | } | ||
| 387 | usbhid->last_ctrl = jiffies; | ||
| 388 | } | 373 | } |
| 389 | 374 | usbhid->urbctrl->dev = hid_to_usb_dev(hid); | |
| 375 | |||
| 376 | usbhid->cr->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE | dir; | ||
| 377 | usbhid->cr->bRequest = (dir == USB_DIR_OUT) ? HID_REQ_SET_REPORT : | ||
| 378 | HID_REQ_GET_REPORT; | ||
| 379 | usbhid->cr->wValue = cpu_to_le16(((report->type + 1) << 8) | | ||
| 380 | report->id); | ||
| 381 | usbhid->cr->wIndex = cpu_to_le16(usbhid->ifnum); | ||
| 382 | usbhid->cr->wLength = cpu_to_le16(len); | ||
| 383 | |||
| 384 | dbg_hid("submitting ctrl urb: %s wValue=0x%04x wIndex=0x%04x wLength=%u\n", | ||
| 385 | usbhid->cr->bRequest == HID_REQ_SET_REPORT ? "Set_Report" : | ||
| 386 | "Get_Report", | ||
| 387 | usbhid->cr->wValue, usbhid->cr->wIndex, usbhid->cr->wLength); | ||
| 388 | |||
| 389 | r = usb_submit_urb(usbhid->urbctrl, GFP_ATOMIC); | ||
| 390 | if (r < 0) { | ||
| 391 | hid_err(hid, "usb_submit_urb(ctrl) failed: %d\n", r); | ||
| 392 | return r; | ||
| 393 | } | ||
| 394 | usbhid->last_ctrl = jiffies; | ||
| 390 | return 0; | 395 | return 0; |
| 391 | } | 396 | } |
| 392 | 397 | ||
| @@ -423,11 +428,8 @@ static void hid_irq_out(struct urb *urb) | |||
| 423 | else | 428 | else |
| 424 | usbhid->outtail = (usbhid->outtail + 1) & (HID_OUTPUT_FIFO_SIZE - 1); | 429 | usbhid->outtail = (usbhid->outtail + 1) & (HID_OUTPUT_FIFO_SIZE - 1); |
| 425 | 430 | ||
| 426 | if (usbhid->outhead != usbhid->outtail) { | 431 | if (usbhid->outhead != usbhid->outtail && !hid_submit_out(hid)) { |
| 427 | if (hid_submit_out(hid)) { | 432 | /* Successfully submitted next urb in queue */ |
| 428 | clear_bit(HID_OUT_RUNNING, &usbhid->iofl); | ||
| 429 | wake_up(&usbhid->wait); | ||
| 430 | } | ||
| 431 | spin_unlock_irqrestore(&usbhid->lock, flags); | 433 | spin_unlock_irqrestore(&usbhid->lock, flags); |
| 432 | return; | 434 | return; |
| 433 | } | 435 | } |
| @@ -474,13 +476,9 @@ static void hid_ctrl(struct urb *urb) | |||
| 474 | else | 476 | else |
| 475 | usbhid->ctrltail = (usbhid->ctrltail + 1) & (HID_CONTROL_FIFO_SIZE - 1); | 477 | usbhid->ctrltail = (usbhid->ctrltail + 1) & (HID_CONTROL_FIFO_SIZE - 1); |
| 476 | 478 | ||
| 477 | if (usbhid->ctrlhead != usbhid->ctrltail) { | 479 | if (usbhid->ctrlhead != usbhid->ctrltail && !hid_submit_ctrl(hid)) { |
| 478 | if (hid_submit_ctrl(hid)) { | 480 | /* Successfully submitted next urb in queue */ |
| 479 | clear_bit(HID_CTRL_RUNNING, &usbhid->iofl); | ||
| 480 | wake_up(&usbhid->wait); | ||
| 481 | } | ||
| 482 | spin_unlock(&usbhid->lock); | 481 | spin_unlock(&usbhid->lock); |
| 483 | usb_autopm_put_interface_async(usbhid->intf); | ||
| 484 | return; | 482 | return; |
| 485 | } | 483 | } |
| 486 | 484 | ||
| @@ -515,9 +513,23 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re | |||
| 515 | usbhid->out[usbhid->outhead].report = report; | 513 | usbhid->out[usbhid->outhead].report = report; |
| 516 | usbhid->outhead = head; | 514 | usbhid->outhead = head; |
| 517 | 515 | ||
| 516 | /* Try to awake from autosuspend... */ | ||
| 517 | if (usb_autopm_get_interface_async(usbhid->intf) < 0) | ||
| 518 | return; | ||
| 519 | |||
| 520 | /* | ||
| 521 | * But if still suspended, leave urb enqueued, don't submit. | ||
| 522 | * Submission will occur if/when resume() drains the queue. | ||
| 523 | */ | ||
| 524 | if (test_bit(HID_REPORTED_IDLE, &usbhid->iofl)) | ||
| 525 | return; | ||
| 526 | |||
| 518 | if (!test_and_set_bit(HID_OUT_RUNNING, &usbhid->iofl)) { | 527 | if (!test_and_set_bit(HID_OUT_RUNNING, &usbhid->iofl)) { |
| 519 | if (hid_submit_out(hid)) | 528 | if (hid_submit_out(hid)) { |
| 520 | clear_bit(HID_OUT_RUNNING, &usbhid->iofl); | 529 | clear_bit(HID_OUT_RUNNING, &usbhid->iofl); |
| 530 | usb_autopm_put_interface_async(usbhid->intf); | ||
| 531 | } | ||
| 532 | wake_up(&usbhid->wait); | ||
| 521 | } else { | 533 | } else { |
| 522 | /* | 534 | /* |
| 523 | * the queue is known to run | 535 | * the queue is known to run |
| @@ -549,9 +561,23 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re | |||
| 549 | usbhid->ctrl[usbhid->ctrlhead].dir = dir; | 561 | usbhid->ctrl[usbhid->ctrlhead].dir = dir; |
| 550 | usbhid->ctrlhead = head; | 562 | usbhid->ctrlhead = head; |
| 551 | 563 | ||
| 564 | /* Try to awake from autosuspend... */ | ||
| 565 | if (usb_autopm_get_interface_async(usbhid->intf) < 0) | ||
| 566 | return; | ||
| 567 | |||
| 568 | /* | ||
| 569 | * If already suspended, leave urb enqueued, but don't submit. | ||
| 570 | * Submission will occur if/when resume() drains the queue. | ||
| 571 | */ | ||
| 572 | if (test_bit(HID_REPORTED_IDLE, &usbhid->iofl)) | ||
| 573 | return; | ||
| 574 | |||
| 552 | if (!test_and_set_bit(HID_CTRL_RUNNING, &usbhid->iofl)) { | 575 | if (!test_and_set_bit(HID_CTRL_RUNNING, &usbhid->iofl)) { |
| 553 | if (hid_submit_ctrl(hid)) | 576 | if (hid_submit_ctrl(hid)) { |
| 554 | clear_bit(HID_CTRL_RUNNING, &usbhid->iofl); | 577 | clear_bit(HID_CTRL_RUNNING, &usbhid->iofl); |
| 578 | usb_autopm_put_interface_async(usbhid->intf); | ||
| 579 | } | ||
| 580 | wake_up(&usbhid->wait); | ||
| 555 | } else { | 581 | } else { |
| 556 | /* | 582 | /* |
| 557 | * the queue is known to run | 583 | * the queue is known to run |
| @@ -576,6 +602,30 @@ void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, uns | |||
| 576 | } | 602 | } |
| 577 | EXPORT_SYMBOL_GPL(usbhid_submit_report); | 603 | EXPORT_SYMBOL_GPL(usbhid_submit_report); |
| 578 | 604 | ||
| 605 | /* Workqueue routine to send requests to change LEDs */ | ||
| 606 | static void hid_led(struct work_struct *work) | ||
| 607 | { | ||
| 608 | struct usbhid_device *usbhid = | ||
| 609 | container_of(work, struct usbhid_device, led_work); | ||
| 610 | struct hid_device *hid = usbhid->hid; | ||
| 611 | struct hid_field *field; | ||
| 612 | unsigned long flags; | ||
| 613 | |||
| 614 | field = hidinput_get_led_field(hid); | ||
| 615 | if (!field) { | ||
| 616 | hid_warn(hid, "LED event field not found\n"); | ||
| 617 | return; | ||
| 618 | } | ||
| 619 | |||
| 620 | spin_lock_irqsave(&usbhid->lock, flags); | ||
| 621 | if (!test_bit(HID_DISCONNECTED, &usbhid->iofl)) { | ||
| 622 | usbhid->ledcount = hidinput_count_leds(hid); | ||
| 623 | hid_dbg(usbhid->hid, "New ledcount = %u\n", usbhid->ledcount); | ||
| 624 | __usbhid_submit_report(hid, field->report, USB_DIR_OUT); | ||
| 625 | } | ||
| 626 | spin_unlock_irqrestore(&usbhid->lock, flags); | ||
| 627 | } | ||
| 628 | |||
| 579 | static int usb_hidinput_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) | 629 | static int usb_hidinput_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) |
| 580 | { | 630 | { |
| 581 | struct hid_device *hid = input_get_drvdata(dev); | 631 | struct hid_device *hid = input_get_drvdata(dev); |
| @@ -595,17 +645,15 @@ static int usb_hidinput_input_event(struct input_dev *dev, unsigned int type, un | |||
| 595 | return -1; | 645 | return -1; |
| 596 | } | 646 | } |
| 597 | 647 | ||
| 648 | spin_lock_irqsave(&usbhid->lock, flags); | ||
| 598 | hid_set_field(field, offset, value); | 649 | hid_set_field(field, offset, value); |
| 599 | if (value) { | 650 | spin_unlock_irqrestore(&usbhid->lock, flags); |
| 600 | spin_lock_irqsave(&usbhid->lock, flags); | 651 | |
| 601 | usbhid->ledcount++; | 652 | /* |
| 602 | spin_unlock_irqrestore(&usbhid->lock, flags); | 653 | * Defer performing requested LED action. |
| 603 | } else { | 654 | * This is more likely gather all LED changes into a single URB. |
| 604 | spin_lock_irqsave(&usbhid->lock, flags); | 655 | */ |
| 605 | usbhid->ledcount--; | 656 | schedule_work(&usbhid->led_work); |
| 606 | spin_unlock_irqrestore(&usbhid->lock, flags); | ||
| 607 | } | ||
| 608 | usbhid_submit_report(hid, field->report, USB_DIR_OUT); | ||
| 609 | 657 | ||
| 610 | return 0; | 658 | return 0; |
| 611 | } | 659 | } |
| @@ -1100,7 +1148,7 @@ static void usbhid_stop(struct hid_device *hid) | |||
| 1100 | return; | 1148 | return; |
| 1101 | 1149 | ||
| 1102 | clear_bit(HID_STARTED, &usbhid->iofl); | 1150 | clear_bit(HID_STARTED, &usbhid->iofl); |
| 1103 | spin_lock_irq(&usbhid->lock); /* Sync with error handler */ | 1151 | spin_lock_irq(&usbhid->lock); /* Sync with error and led handlers */ |
| 1104 | set_bit(HID_DISCONNECTED, &usbhid->iofl); | 1152 | set_bit(HID_DISCONNECTED, &usbhid->iofl); |
| 1105 | spin_unlock_irq(&usbhid->lock); | 1153 | spin_unlock_irq(&usbhid->lock); |
| 1106 | usb_kill_urb(usbhid->urbin); | 1154 | usb_kill_urb(usbhid->urbin); |
| @@ -1234,6 +1282,8 @@ static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id * | |||
| 1234 | setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid); | 1282 | setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid); |
| 1235 | spin_lock_init(&usbhid->lock); | 1283 | spin_lock_init(&usbhid->lock); |
| 1236 | 1284 | ||
| 1285 | INIT_WORK(&usbhid->led_work, hid_led); | ||
| 1286 | |||
| 1237 | ret = hid_add_device(hid); | 1287 | ret = hid_add_device(hid); |
| 1238 | if (ret) { | 1288 | if (ret) { |
| 1239 | if (ret != -ENODEV) | 1289 | if (ret != -ENODEV) |
| @@ -1266,6 +1316,7 @@ static void hid_cancel_delayed_stuff(struct usbhid_device *usbhid) | |||
| 1266 | { | 1316 | { |
| 1267 | del_timer_sync(&usbhid->io_retry); | 1317 | del_timer_sync(&usbhid->io_retry); |
| 1268 | cancel_work_sync(&usbhid->reset_work); | 1318 | cancel_work_sync(&usbhid->reset_work); |
| 1319 | cancel_work_sync(&usbhid->led_work); | ||
| 1269 | } | 1320 | } |
| 1270 | 1321 | ||
| 1271 | static void hid_cease_io(struct usbhid_device *usbhid) | 1322 | static void hid_cease_io(struct usbhid_device *usbhid) |
| @@ -1367,16 +1418,6 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message) | |||
| 1367 | return -EIO; | 1418 | return -EIO; |
| 1368 | } | 1419 | } |
| 1369 | 1420 | ||
| 1370 | if (!ignoreled && PMSG_IS_AUTO(message)) { | ||
| 1371 | spin_lock_irq(&usbhid->lock); | ||
| 1372 | if (test_bit(HID_LED_ON, &usbhid->iofl)) { | ||
| 1373 | spin_unlock_irq(&usbhid->lock); | ||
| 1374 | usbhid_mark_busy(usbhid); | ||
| 1375 | return -EBUSY; | ||
| 1376 | } | ||
| 1377 | spin_unlock_irq(&usbhid->lock); | ||
| 1378 | } | ||
| 1379 | |||
| 1380 | hid_cancel_delayed_stuff(usbhid); | 1421 | hid_cancel_delayed_stuff(usbhid); |
| 1381 | hid_cease_io(usbhid); | 1422 | hid_cease_io(usbhid); |
| 1382 | 1423 | ||
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 5028d60a22a1..c831af937481 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c | |||
| @@ -47,6 +47,7 @@ static const struct hid_blacklist { | |||
| 47 | 47 | ||
| 48 | { USB_VENDOR_ID_AFATECH, USB_DEVICE_ID_AFATECH_AF9016, HID_QUIRK_FULLSPEED_INTERVAL }, | 48 | { USB_VENDOR_ID_AFATECH, USB_DEVICE_ID_AFATECH_AF9016, HID_QUIRK_FULLSPEED_INTERVAL }, |
| 49 | 49 | ||
| 50 | { USB_VENDOR_ID_EMS, USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II, HID_QUIRK_MULTI_INPUT }, | ||
| 50 | { USB_VENDOR_ID_ETURBOTOUCH, USB_DEVICE_ID_ETURBOTOUCH, HID_QUIRK_MULTI_INPUT }, | 51 | { USB_VENDOR_ID_ETURBOTOUCH, USB_DEVICE_ID_ETURBOTOUCH, HID_QUIRK_MULTI_INPUT }, |
| 51 | { USB_VENDOR_ID_GREENASIA, USB_DEVICE_ID_GREENASIA_DUAL_USB_JOYPAD, HID_QUIRK_MULTI_INPUT }, | 52 | { USB_VENDOR_ID_GREENASIA, USB_DEVICE_ID_GREENASIA_DUAL_USB_JOYPAD, HID_QUIRK_MULTI_INPUT }, |
| 52 | { USB_VENDOR_ID_PANTHERLORD, USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK, HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS }, | 53 | { USB_VENDOR_ID_PANTHERLORD, USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK, HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS }, |
| @@ -67,6 +68,9 @@ static const struct hid_blacklist { | |||
| 67 | { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_AXIS_295, HID_QUIRK_NOGET }, | 68 | { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_AXIS_295, HID_QUIRK_NOGET }, |
| 68 | { USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET }, | 69 | { USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET }, |
| 69 | { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET }, | 70 | { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET }, |
| 71 | { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NO_INIT_REPORTS }, | ||
| 72 | { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1, HID_QUIRK_NO_INIT_REPORTS }, | ||
| 73 | { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2, HID_QUIRK_NO_INIT_REPORTS }, | ||
| 70 | { USB_VENDOR_ID_PRODIGE, USB_DEVICE_ID_PRODIGE_CORDLESS, HID_QUIRK_NOGET }, | 74 | { USB_VENDOR_ID_PRODIGE, USB_DEVICE_ID_PRODIGE_CORDLESS, HID_QUIRK_NOGET }, |
| 71 | { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NOGET }, | 75 | { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NOGET }, |
| 72 | { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET }, | 76 | { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET }, |
diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h index 1673cac93d77..cb8f703efde5 100644 --- a/drivers/hid/usbhid/usbhid.h +++ b/drivers/hid/usbhid/usbhid.h | |||
| @@ -55,7 +55,6 @@ struct usb_interface *usbhid_find_interface(int minor); | |||
| 55 | #define HID_STARTED 8 | 55 | #define HID_STARTED 8 |
| 56 | #define HID_REPORTED_IDLE 9 | 56 | #define HID_REPORTED_IDLE 9 |
| 57 | #define HID_KEYS_PRESSED 10 | 57 | #define HID_KEYS_PRESSED 10 |
| 58 | #define HID_LED_ON 11 | ||
| 59 | 58 | ||
| 60 | /* | 59 | /* |
| 61 | * USB-specific HID struct, to be pointed to | 60 | * USB-specific HID struct, to be pointed to |
| @@ -97,6 +96,8 @@ struct usbhid_device { | |||
| 97 | struct work_struct reset_work; /* Task context for resets */ | 96 | struct work_struct reset_work; /* Task context for resets */ |
| 98 | wait_queue_head_t wait; /* For sleeping */ | 97 | wait_queue_head_t wait; /* For sleeping */ |
| 99 | int ledcount; /* counting the number of active leds */ | 98 | int ledcount; /* counting the number of active leds */ |
| 99 | |||
| 100 | struct work_struct led_work; /* Task context for setting LEDs */ | ||
| 100 | }; | 101 | }; |
| 101 | 102 | ||
| 102 | #define hid_to_usb_dev(hid_dev) \ | 103 | #define hid_to_usb_dev(hid_dev) \ |
diff --git a/drivers/hid/usbhid/usbkbd.c b/drivers/hid/usbhid/usbkbd.c index bc445d7e3bf5..796086980f4a 100644 --- a/drivers/hid/usbhid/usbkbd.c +++ b/drivers/hid/usbhid/usbkbd.c | |||
| @@ -64,6 +64,32 @@ static const unsigned char usb_kbd_keycode[256] = { | |||
| 64 | 150,158,159,128,136,177,178,176,142,152,173,140 | 64 | 150,158,159,128,136,177,178,176,142,152,173,140 |
| 65 | }; | 65 | }; |
| 66 | 66 | ||
| 67 | |||
| 68 | /** | ||
| 69 | * struct usb_kbd - state of each attached keyboard | ||
| 70 | * @dev: input device associated with this keyboard | ||
| 71 | * @usbdev: usb device associated with this keyboard | ||
| 72 | * @old: data received in the past from the @irq URB representing which | ||
| 73 | * keys were pressed. By comparing with the current list of keys | ||
| 74 | * that are pressed, we are able to see key releases. | ||
| 75 | * @irq: URB for receiving a list of keys that are pressed when a | ||
| 76 | * new key is pressed or a key that was pressed is released. | ||
| 77 | * @led: URB for sending LEDs (e.g. numlock, ...) | ||
| 78 | * @newleds: data that will be sent with the @led URB representing which LEDs | ||
| 79 | should be on | ||
| 80 | * @name: Name of the keyboard. @dev's name field points to this buffer | ||
| 81 | * @phys: Physical path of the keyboard. @dev's phys field points to this | ||
| 82 | * buffer | ||
| 83 | * @new: Buffer for the @irq URB | ||
| 84 | * @cr: Control request for @led URB | ||
| 85 | * @leds: Buffer for the @led URB | ||
| 86 | * @new_dma: DMA address for @irq URB | ||
| 87 | * @leds_dma: DMA address for @led URB | ||
| 88 | * @leds_lock: spinlock that protects @leds, @newleds, and @led_urb_submitted | ||
| 89 | * @led_urb_submitted: indicates whether @led is in progress, i.e. it has been | ||
| 90 | * submitted and its completion handler has not returned yet | ||
| 91 | * without resubmitting @led | ||
| 92 | */ | ||
| 67 | struct usb_kbd { | 93 | struct usb_kbd { |
| 68 | struct input_dev *dev; | 94 | struct input_dev *dev; |
| 69 | struct usb_device *usbdev; | 95 | struct usb_device *usbdev; |
| @@ -78,6 +104,10 @@ struct usb_kbd { | |||
| 78 | unsigned char *leds; | 104 | unsigned char *leds; |
| 79 | dma_addr_t new_dma; | 105 | dma_addr_t new_dma; |
| 80 | dma_addr_t leds_dma; | 106 | dma_addr_t leds_dma; |
| 107 | |||
| 108 | spinlock_t leds_lock; | ||
| 109 | bool led_urb_submitted; | ||
| 110 | |||
| 81 | }; | 111 | }; |
| 82 | 112 | ||
| 83 | static void usb_kbd_irq(struct urb *urb) | 113 | static void usb_kbd_irq(struct urb *urb) |
| @@ -136,44 +166,66 @@ resubmit: | |||
| 136 | static int usb_kbd_event(struct input_dev *dev, unsigned int type, | 166 | static int usb_kbd_event(struct input_dev *dev, unsigned int type, |
| 137 | unsigned int code, int value) | 167 | unsigned int code, int value) |
| 138 | { | 168 | { |
| 169 | unsigned long flags; | ||
| 139 | struct usb_kbd *kbd = input_get_drvdata(dev); | 170 | struct usb_kbd *kbd = input_get_drvdata(dev); |
| 140 | 171 | ||
| 141 | if (type != EV_LED) | 172 | if (type != EV_LED) |
| 142 | return -1; | 173 | return -1; |
| 143 | 174 | ||
| 175 | spin_lock_irqsave(&kbd->leds_lock, flags); | ||
| 144 | kbd->newleds = (!!test_bit(LED_KANA, dev->led) << 3) | (!!test_bit(LED_COMPOSE, dev->led) << 3) | | 176 | kbd->newleds = (!!test_bit(LED_KANA, dev->led) << 3) | (!!test_bit(LED_COMPOSE, dev->led) << 3) | |
| 145 | (!!test_bit(LED_SCROLLL, dev->led) << 2) | (!!test_bit(LED_CAPSL, dev->led) << 1) | | 177 | (!!test_bit(LED_SCROLLL, dev->led) << 2) | (!!test_bit(LED_CAPSL, dev->led) << 1) | |
| 146 | (!!test_bit(LED_NUML, dev->led)); | 178 | (!!test_bit(LED_NUML, dev->led)); |
| 147 | 179 | ||
| 148 | if (kbd->led->status == -EINPROGRESS) | 180 | if (kbd->led_urb_submitted){ |
| 181 | spin_unlock_irqrestore(&kbd->leds_lock, flags); | ||
| 149 | return 0; | 182 | return 0; |
| 183 | } | ||
| 150 | 184 | ||
| 151 | if (*(kbd->leds) == kbd->newleds) | 185 | if (*(kbd->leds) == kbd->newleds){ |
| 186 | spin_unlock_irqrestore(&kbd->leds_lock, flags); | ||
| 152 | return 0; | 187 | return 0; |
| 188 | } | ||
| 153 | 189 | ||
| 154 | *(kbd->leds) = kbd->newleds; | 190 | *(kbd->leds) = kbd->newleds; |
| 191 | |||
| 155 | kbd->led->dev = kbd->usbdev; | 192 | kbd->led->dev = kbd->usbdev; |
| 156 | if (usb_submit_urb(kbd->led, GFP_ATOMIC)) | 193 | if (usb_submit_urb(kbd->led, GFP_ATOMIC)) |
| 157 | pr_err("usb_submit_urb(leds) failed\n"); | 194 | pr_err("usb_submit_urb(leds) failed\n"); |
| 158 | 195 | else | |
| 196 | kbd->led_urb_submitted = true; | ||
| 197 | |||
| 198 | spin_unlock_irqrestore(&kbd->leds_lock, flags); | ||
| 199 | |||
| 159 | return 0; | 200 | return 0; |
| 160 | } | 201 | } |
| 161 | 202 | ||
| 162 | static void usb_kbd_led(struct urb *urb) | 203 | static void usb_kbd_led(struct urb *urb) |
| 163 | { | 204 | { |
| 205 | unsigned long flags; | ||
| 164 | struct usb_kbd *kbd = urb->context; | 206 | struct usb_kbd *kbd = urb->context; |
| 165 | 207 | ||
| 166 | if (urb->status) | 208 | if (urb->status) |
| 167 | hid_warn(urb->dev, "led urb status %d received\n", | 209 | hid_warn(urb->dev, "led urb status %d received\n", |
| 168 | urb->status); | 210 | urb->status); |
| 169 | 211 | ||
| 170 | if (*(kbd->leds) == kbd->newleds) | 212 | spin_lock_irqsave(&kbd->leds_lock, flags); |
| 213 | |||
| 214 | if (*(kbd->leds) == kbd->newleds){ | ||
| 215 | kbd->led_urb_submitted = false; | ||
| 216 | spin_unlock_irqrestore(&kbd->leds_lock, flags); | ||
| 171 | return; | 217 | return; |
| 218 | } | ||
| 172 | 219 | ||
| 173 | *(kbd->leds) = kbd->newleds; | 220 | *(kbd->leds) = kbd->newleds; |
| 221 | |||
| 174 | kbd->led->dev = kbd->usbdev; | 222 | kbd->led->dev = kbd->usbdev; |
| 175 | if (usb_submit_urb(kbd->led, GFP_ATOMIC)) | 223 | if (usb_submit_urb(kbd->led, GFP_ATOMIC)){ |
| 176 | hid_err(urb->dev, "usb_submit_urb(leds) failed\n"); | 224 | hid_err(urb->dev, "usb_submit_urb(leds) failed\n"); |
| 225 | kbd->led_urb_submitted = false; | ||
| 226 | } | ||
| 227 | spin_unlock_irqrestore(&kbd->leds_lock, flags); | ||
| 228 | |||
| 177 | } | 229 | } |
| 178 | 230 | ||
| 179 | static int usb_kbd_open(struct input_dev *dev) | 231 | static int usb_kbd_open(struct input_dev *dev) |
| @@ -252,6 +304,7 @@ static int usb_kbd_probe(struct usb_interface *iface, | |||
| 252 | 304 | ||
| 253 | kbd->usbdev = dev; | 305 | kbd->usbdev = dev; |
| 254 | kbd->dev = input_dev; | 306 | kbd->dev = input_dev; |
| 307 | spin_lock_init(&kbd->leds_lock); | ||
| 255 | 308 | ||
| 256 | if (dev->manufacturer) | 309 | if (dev->manufacturer) |
| 257 | strlcpy(kbd->name, dev->manufacturer, sizeof(kbd->name)); | 310 | strlcpy(kbd->name, dev->manufacturer, sizeof(kbd->name)); |
| @@ -334,6 +387,7 @@ static void usb_kbd_disconnect(struct usb_interface *intf) | |||
| 334 | if (kbd) { | 387 | if (kbd) { |
| 335 | usb_kill_urb(kbd->irq); | 388 | usb_kill_urb(kbd->irq); |
| 336 | input_unregister_device(kbd->dev); | 389 | input_unregister_device(kbd->dev); |
| 390 | usb_kill_urb(kbd->led); | ||
| 337 | usb_kbd_free_mem(interface_to_usbdev(intf), kbd); | 391 | usb_kbd_free_mem(interface_to_usbdev(intf), kbd); |
| 338 | kfree(kbd); | 392 | kfree(kbd); |
| 339 | } | 393 | } |
diff --git a/drivers/usb/misc/usbled.c b/drivers/usb/misc/usbled.c index 4af56fbc3c06..12d03e7ad636 100644 --- a/drivers/usb/misc/usbled.c +++ b/drivers/usb/misc/usbled.c | |||
| @@ -31,6 +31,8 @@ static const struct usb_device_id id_table[] = { | |||
| 31 | .driver_info = DELCOM_VISUAL_SIGNAL_INDICATOR }, | 31 | .driver_info = DELCOM_VISUAL_SIGNAL_INDICATOR }, |
| 32 | { USB_DEVICE(0x1d34, 0x0004), | 32 | { USB_DEVICE(0x1d34, 0x0004), |
| 33 | .driver_info = DREAM_CHEEKY_WEBMAIL_NOTIFIER }, | 33 | .driver_info = DREAM_CHEEKY_WEBMAIL_NOTIFIER }, |
| 34 | { USB_DEVICE(0x1d34, 0x000a), | ||
| 35 | .driver_info = DREAM_CHEEKY_WEBMAIL_NOTIFIER }, | ||
| 34 | { }, | 36 | { }, |
| 35 | }; | 37 | }; |
| 36 | MODULE_DEVICE_TABLE(usb, id_table); | 38 | MODULE_DEVICE_TABLE(usb, id_table); |
diff --git a/include/linux/hid.h b/include/linux/hid.h index c235e4e8767c..3a95da60fd3e 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h | |||
| @@ -72,6 +72,7 @@ | |||
| 72 | #include <linux/workqueue.h> | 72 | #include <linux/workqueue.h> |
| 73 | #include <linux/input.h> | 73 | #include <linux/input.h> |
| 74 | #include <linux/semaphore.h> | 74 | #include <linux/semaphore.h> |
| 75 | #include <linux/power_supply.h> | ||
| 75 | 76 | ||
| 76 | /* | 77 | /* |
| 77 | * We parse each description item into this structure. Short items data | 78 | * We parse each description item into this structure. Short items data |
| @@ -190,6 +191,7 @@ struct hid_item { | |||
| 190 | #define HID_UP_UNDEFINED 0x00000000 | 191 | #define HID_UP_UNDEFINED 0x00000000 |
| 191 | #define HID_UP_GENDESK 0x00010000 | 192 | #define HID_UP_GENDESK 0x00010000 |
| 192 | #define HID_UP_SIMULATION 0x00020000 | 193 | #define HID_UP_SIMULATION 0x00020000 |
| 194 | #define HID_UP_GENDEVCTRLS 0x00060000 | ||
| 193 | #define HID_UP_KEYBOARD 0x00070000 | 195 | #define HID_UP_KEYBOARD 0x00070000 |
| 194 | #define HID_UP_LED 0x00080000 | 196 | #define HID_UP_LED 0x00080000 |
| 195 | #define HID_UP_BUTTON 0x00090000 | 197 | #define HID_UP_BUTTON 0x00090000 |
| @@ -239,6 +241,8 @@ struct hid_item { | |||
| 239 | #define HID_GD_RIGHT 0x00010092 | 241 | #define HID_GD_RIGHT 0x00010092 |
| 240 | #define HID_GD_LEFT 0x00010093 | 242 | #define HID_GD_LEFT 0x00010093 |
| 241 | 243 | ||
| 244 | #define HID_DC_BATTERYSTRENGTH 0x00060020 | ||
| 245 | |||
| 242 | #define HID_DG_DIGITIZER 0x000d0001 | 246 | #define HID_DG_DIGITIZER 0x000d0001 |
| 243 | #define HID_DG_PEN 0x000d0002 | 247 | #define HID_DG_PEN 0x000d0002 |
| 244 | #define HID_DG_LIGHTPEN 0x000d0003 | 248 | #define HID_DG_LIGHTPEN 0x000d0003 |
| @@ -482,6 +486,19 @@ struct hid_device { /* device report descriptor */ | |||
| 482 | struct hid_driver *driver; | 486 | struct hid_driver *driver; |
| 483 | struct hid_ll_driver *ll_driver; | 487 | struct hid_ll_driver *ll_driver; |
| 484 | 488 | ||
| 489 | #ifdef CONFIG_HID_BATTERY_STRENGTH | ||
| 490 | /* | ||
| 491 | * Power supply information for HID devices which report | ||
| 492 | * battery strength. power_supply is registered iff | ||
| 493 | * battery.name is non-NULL. | ||
| 494 | */ | ||
| 495 | struct power_supply battery; | ||
| 496 | __s32 battery_min; | ||
| 497 | __s32 battery_max; | ||
| 498 | __s32 battery_report_type; | ||
| 499 | __s32 battery_report_id; | ||
| 500 | #endif | ||
| 501 | |||
| 485 | unsigned int status; /* see STAT flags above */ | 502 | unsigned int status; /* see STAT flags above */ |
| 486 | unsigned claimed; /* Claimed by hidinput, hiddev? */ | 503 | unsigned claimed; /* Claimed by hidinput, hiddev? */ |
| 487 | unsigned quirks; /* Various quirks the device can pull on us */ | 504 | unsigned quirks; /* Various quirks the device can pull on us */ |
| @@ -712,6 +729,8 @@ extern void hidinput_disconnect(struct hid_device *); | |||
| 712 | int hid_set_field(struct hid_field *, unsigned, __s32); | 729 | int hid_set_field(struct hid_field *, unsigned, __s32); |
| 713 | int hid_input_report(struct hid_device *, int type, u8 *, int, int); | 730 | int hid_input_report(struct hid_device *, int type, u8 *, int, int); |
| 714 | int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field); | 731 | int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field); |
| 732 | struct hid_field *hidinput_get_led_field(struct hid_device *hid); | ||
| 733 | unsigned int hidinput_count_leds(struct hid_device *hid); | ||
| 715 | void hid_output_report(struct hid_report *report, __u8 *data); | 734 | void hid_output_report(struct hid_report *report, __u8 *data); |
| 716 | struct hid_device *hid_allocate_device(void); | 735 | struct hid_device *hid_allocate_device(void); |
| 717 | struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id); | 736 | struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id); |
| @@ -719,6 +738,8 @@ int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size); | |||
| 719 | int hid_check_keys_pressed(struct hid_device *hid); | 738 | int hid_check_keys_pressed(struct hid_device *hid); |
| 720 | int hid_connect(struct hid_device *hid, unsigned int connect_mask); | 739 | int hid_connect(struct hid_device *hid, unsigned int connect_mask); |
| 721 | void hid_disconnect(struct hid_device *hid); | 740 | void hid_disconnect(struct hid_device *hid); |
| 741 | const struct hid_device_id *hid_match_id(struct hid_device *hdev, | ||
| 742 | const struct hid_device_id *id); | ||
| 722 | 743 | ||
| 723 | /** | 744 | /** |
| 724 | * hid_map_usage - map usage input bits | 745 | * hid_map_usage - map usage input bits |
