]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 30 Apr 2013 16:37:55 +0000 (09:37 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 30 Apr 2013 16:37:55 +0000 (09:37 -0700)
Pull HID updates from Jiri Kosina:

 - hid driver transport cleanup, finalizing the long-desired decoupling
   of core from transport layers, by Benjamin Tissoires and Henrik
   Rydberg

 - support for hybrid finger/pen multitouch HID devices, by Benjamin
   Tissoires

 - fix for long-standing issue in Logitech unifying driver sometimes not
   inializing properly due to device specifics, by Andrew de los Reyes

 - Wii remote driver updates to support 2nd generation of devices, by
   David Herrmann

 - support for Apple IR remote

 - roccat driver now supports new devices (Roccat Kone Pure, IskuFX), by
   Stefan Achatz

 - debugfs locking fixes in hid debug interface, by Jiri Kosina

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid: (43 commits)
  HID: protect hid_debug_list
  HID: debug: break out hid_dump_report() into hid-debug
  HID: Add PID for Japanese version of NE4K keyboard
  HID: hid-lg4ff add support for new version of DFGT wheel
  HID: icade: u16 which never < 0
  HID: clarify Magic Mouse Kconfig description
  HID: appleir: add support for Apple ir devices
  HID: roccat: added media key support for Kone
  HID: hid-lenovo-tpkbd: remove doubled hid_get_drvdata
  HID: i2c-hid: fix length for set/get report in i2c hid
  HID: wiimote: parse reduced status reports
  HID: wiimote: add 2nd generation Wii Remote IDs
  HID: wiimote: use unique battery names
  HID: hidraw: warn if userspace headers are outdated
  HID: multitouch: force BTN_STYLUS for pen devices
  HID: multitouch: append " Pen" to the name of the stylus input
  HID: multitouch: add handling for pen in dual-sensors device
  HID: multitouch: change touch sensor detection in mt_input_configured()
  HID: multitouch: do not map usage from non used reports
  HID: multitouch: breaks out touch handling in specific functions
  ...

61 files changed:
Documentation/ABI/testing/sysfs-driver-hid-roccat-isku
Documentation/ABI/testing/sysfs-driver-hid-roccat-konepure [new file with mode: 0644]
drivers/hid/Kconfig
drivers/hid/Makefile
drivers/hid/hid-apple.c
drivers/hid/hid-appleir.c [new file with mode: 0644]
drivers/hid/hid-axff.c
drivers/hid/hid-core.c
drivers/hid/hid-debug.c
drivers/hid/hid-dr.c
drivers/hid/hid-emsff.c
drivers/hid/hid-gaff.c
drivers/hid/hid-holtekff.c
drivers/hid/hid-icade.c
drivers/hid/hid-ids.h
drivers/hid/hid-input.c
drivers/hid/hid-kye.c
drivers/hid/hid-lenovo-tpkbd.c
drivers/hid/hid-lg2ff.c
drivers/hid/hid-lg3ff.c
drivers/hid/hid-lg4ff.c
drivers/hid/hid-lgff.c
drivers/hid/hid-logitech-dj.c
drivers/hid/hid-logitech-dj.h
drivers/hid/hid-magicmouse.c
drivers/hid/hid-microsoft.c
drivers/hid/hid-multitouch.c
drivers/hid/hid-ntrig.c
drivers/hid/hid-picolcd.h
drivers/hid/hid-picolcd_backlight.c
drivers/hid/hid-picolcd_cir.c
drivers/hid/hid-picolcd_core.c
drivers/hid/hid-picolcd_debugfs.c
drivers/hid/hid-picolcd_fb.c
drivers/hid/hid-picolcd_lcd.c
drivers/hid/hid-picolcd_leds.c
drivers/hid/hid-pl.c
drivers/hid/hid-prodikeys.c
drivers/hid/hid-roccat-isku.c
drivers/hid/hid-roccat-isku.h
drivers/hid/hid-roccat-kone.c
drivers/hid/hid-roccat-kone.h
drivers/hid/hid-roccat-konepure.c [new file with mode: 0644]
drivers/hid/hid-roccat-konepure.h [new file with mode: 0644]
drivers/hid/hid-roccat.c
drivers/hid/hid-sensor-hub.c
drivers/hid/hid-sjoy.c
drivers/hid/hid-speedlink.c
drivers/hid/hid-steelseries.c
drivers/hid/hid-thingm.c
drivers/hid/hid-tmff.c
drivers/hid/hid-wiimote-core.c
drivers/hid/hid-zpff.c
drivers/hid/i2c-hid/i2c-hid.c
drivers/hid/usbhid/hid-core.c
drivers/hid/usbhid/hid-pidff.c
drivers/hid/usbhid/hiddev.c
drivers/hid/usbhid/usbhid.h
include/linux/hid-debug.h
include/linux/hid.h
samples/hidraw/hid-example.c

index 9eca5a182e64df28a22187ae05ff829b53de8f52..c601d0f2ac4608ef98672e1400c4ec3c594c0794 100644 (file)
@@ -101,7 +101,8 @@ Date:               June 2011
 Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
 Description:   When written, this file lets one set the backlight intensity for
                a specific profile. Profile number is included in written data.
-               The data has to be 10 bytes long.
+               The data has to be 10 bytes long for Isku, IskuFX needs 16 bytes
+               of data.
                Before reading this file, control has to be written to select
                which profile to read.
 Users:         http://roccat.sourceforge.net
@@ -141,3 +142,12 @@ Description:       When written, this file lets one trigger easyshift functionality
                The data has to be 16 bytes long.
                This file is writeonly.
 Users:         http://roccat.sourceforge.net
+
+What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/isku/roccatisku<minor>/talkfx
+Date:          February 2013
+Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:   When written, this file lets one trigger temporary color schemes
+               from the host.
+               The data has to be 16 bytes long.
+               This file is writeonly.
+Users:         http://roccat.sourceforge.net
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-konepure b/Documentation/ABI/testing/sysfs-driver-hid-roccat-konepure
new file mode 100644 (file)
index 0000000..41a9b7f
--- /dev/null
@@ -0,0 +1,105 @@
+What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/konepure/roccatkonepure<minor>/actual_profile
+Date:          December 2012
+Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:   The mouse can store 5 profiles which can be switched by the
+               press of a button. actual_profile holds number of actual profile.
+               This value is persistent, so its value determines the profile
+               that's active when the mouse is powered on next time.
+               When written, the mouse activates the set profile immediately.
+               The data has to be 3 bytes long.
+               The mouse will reject invalid data.
+Users:         http://roccat.sourceforge.net
+
+What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/konepure/roccatkonepure<minor>/control
+Date:          December 2012
+Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:   When written, this file lets one select which data from which
+               profile will be read next. The data has to be 3 bytes long.
+               This file is writeonly.
+Users:         http://roccat.sourceforge.net
+
+What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/konepure/roccatkonepure<minor>/info
+Date:          December 2012
+Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:   When read, this file returns general data like firmware version.
+               When written, the device can be reset.
+               The data is 6 bytes long.
+Users:         http://roccat.sourceforge.net
+
+What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/konepure/roccatkonepure<minor>/macro
+Date:          December 2012
+Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:   The mouse can store a macro with max 500 key/button strokes
+               internally.
+               When written, this file lets one set the sequence for a specific
+               button for a specific profile. Button and profile numbers are
+               included in written data. The data has to be 2082 bytes long.
+               This file is writeonly.
+Users:         http://roccat.sourceforge.net
+
+What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/konepure/roccatkonepure<minor>/profile_buttons
+Date:          December 2012
+Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:   The mouse can store 5 profiles which can be switched by the
+               press of a button. A profile is split in settings and buttons.
+               profile_buttons holds information about button layout.
+               When written, this file lets one write the respective profile
+               buttons back to the mouse. The data has to be 59 bytes long.
+               The mouse will reject invalid data.
+               Which profile to write is determined by the profile number
+               contained in the data.
+               Before reading this file, control has to be written to select
+               which profile to read.
+Users:         http://roccat.sourceforge.net
+
+What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/konepure/roccatkonepure<minor>/profile_settings
+Date:          December 2012
+Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:   The mouse can store 5 profiles which can be switched by the
+               press of a button. A profile is split in settings and buttons.
+               profile_settings holds information like resolution, sensitivity
+               and light effects.
+               When written, this file lets one write the respective profile
+               settings back to the mouse. The data has to be 31 bytes long.
+               The mouse will reject invalid data.
+               Which profile to write is determined by the profile number
+               contained in the data.
+               Before reading this file, control has to be written to select
+               which profile to read.
+Users:         http://roccat.sourceforge.net
+
+What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/konepure/roccatkonepure<minor>/sensor
+Date:          December 2012
+Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:   The mouse has a tracking- and a distance-control-unit. These
+               can be activated/deactivated and the lift-off distance can be
+               set. The data has to be 6 bytes long.
+               This file is writeonly.
+Users:         http://roccat.sourceforge.net
+
+What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/konepure/roccatkonepure<minor>/talk
+Date:          December 2012
+Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:   Used to active some easy* functions of the mouse from outside.
+               The data has to be 16 bytes long.
+               This file is writeonly.
+Users:         http://roccat.sourceforge.net
+
+What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/konepure/roccatkonepure<minor>/tcu
+Date:          December 2012
+Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:   When written a calibration process for the tracking control unit
+               can be initiated/cancelled. Also lets one read/write sensor
+               registers.
+               The data has to be 4 bytes long.
+Users:         http://roccat.sourceforge.net
+
+What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/konepure/roccatkonepure<minor>/tcu_image
+Date:          December 2012
+Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:   When read the mouse returns a 30x30 pixel image of the
+               sampled underground. This works only in the course of a
+               calibration process initiated with tcu.
+               The returned data is 1028 bytes in size.
+               This file is readonly.
+Users:         http://roccat.sourceforge.net
index 5f07d85c4189fc4e0aa41ad5c3bf63e7d77b2ae8..fb52f3f6de80a377112ea0af5dfb8153772cc14e 100644 (file)
@@ -92,14 +92,14 @@ menu "Special HID drivers"
 
 config HID_A4TECH
        tristate "A4 tech mice" if EXPERT
-       depends on USB_HID
+       depends on HID
        default !EXPERT
        ---help---
        Support for A4 tech X5 and WOP-35 / Trust 450L mice.
 
 config HID_ACRUX
        tristate "ACRUX game controller support"
-       depends on USB_HID
+       depends on HID
        ---help---
        Say Y here if you want to enable support for ACRUX game controllers.
 
@@ -113,7 +113,7 @@ config HID_ACRUX_FF
 
 config HID_APPLE
        tristate "Apple {i,Power,Mac}Books" if EXPERT
-       depends on (USB_HID || BT_HIDP)
+       depends on HID
        default !EXPERT
        ---help---
        Support for some Apple devices which less or more break
@@ -122,36 +122,47 @@ config HID_APPLE
        Say Y here if you want support for keyboards of Apple iBooks, PowerBooks,
        MacBooks, MacBook Pros and Apple Aluminum.
 
+config HID_APPLEIR
+       tristate "Apple infrared receiver"
+       depends on (USB_HID)
+       ---help---
+       Support for Apple infrared remote control. All the Apple computers from
+         2005 onwards include such a port, except the unibody Macbook (2009),
+         and Mac Pros. This receiver is also used in the Apple TV set-top box
+         prior to the 2010 model.
+
+       Say Y here if you want support for Apple infrared remote control.
+
 config HID_AUREAL
        tristate "Aureal"
-       depends on USB_HID
+       depends on HID
        ---help---
        Support for Aureal Cy se W-01RN Remote Controller and other Aureal derived remotes.
 
 config HID_BELKIN
        tristate "Belkin Flip KVM and Wireless keyboard" if EXPERT
-       depends on USB_HID
+       depends on HID
        default !EXPERT
        ---help---
        Support for Belkin Flip KVM and Wireless keyboard.
 
 config HID_CHERRY
        tristate "Cherry Cymotion keyboard" if EXPERT
-       depends on USB_HID
+       depends on HID
        default !EXPERT
        ---help---
        Support for Cherry Cymotion keyboard.
 
 config HID_CHICONY
        tristate "Chicony Tactical pad" if EXPERT
-       depends on USB_HID
+       depends on HID
        default !EXPERT
        ---help---
        Support for Chicony Tactical pad.
 
 config HID_PRODIKEYS
        tristate "Prodikeys PC-MIDI Keyboard support"
-       depends on USB_HID && SND
+       depends on HID && SND
        select SND_RAWMIDI
        ---help---
        Support for Prodikeys PC-MIDI Keyboard device support.
@@ -166,14 +177,14 @@ config HID_PRODIKEYS
 
 config HID_CYPRESS
        tristate "Cypress mouse and barcode readers" if EXPERT
-       depends on USB_HID
+       depends on HID
        default !EXPERT
        ---help---
        Support for cypress mouse and barcode readers.
 
 config HID_DRAGONRISE
        tristate "DragonRise Inc. game controller"
-       depends on USB_HID
+       depends on HID
        ---help---
        Say Y here if you have DragonRise Inc. game controllers.
        These might be branded as:
@@ -192,7 +203,7 @@ config DRAGONRISE_FF
 
 config HID_EMS_FF
        tristate "EMS Production Inc. force feedback support"
-       depends on USB_HID
+       depends on HID
        select INPUT_FF_MEMLESS
        ---help---
        Say Y here if you want to enable force feedback support for devices by
@@ -202,13 +213,13 @@ config HID_EMS_FF
 
 config HID_ELECOM
        tristate "ELECOM BM084 bluetooth mouse"
-       depends on BT_HIDP
+       depends on HID
        ---help---
        Support for the ELECOM BM084 (bluetooth mouse).
 
 config HID_EZKEY
        tristate "Ezkey BTC 8193 keyboard" if EXPERT
-       depends on USB_HID
+       depends on HID
        default !EXPERT
        ---help---
        Support for Ezkey BTC 8193 keyboard.
@@ -231,7 +242,7 @@ config HOLTEK_FF
 
 config HID_KEYTOUCH
        tristate "Keytouch HID devices"
-       depends on USB_HID
+       depends on HID
        ---help---
        Support for Keytouch HID devices not fully compliant with
        the specification. Currently supported:
@@ -239,7 +250,7 @@ config HID_KEYTOUCH
 
 config HID_KYE
        tristate "KYE/Genius devices"
-       depends on USB_HID
+       depends on HID
        ---help---
        Support for KYE/Genius devices not fully compliant with HID standard:
        - Ergo Mouse
@@ -249,25 +260,25 @@ config HID_KYE
 
 config HID_UCLOGIC
        tristate "UC-Logic"
-       depends on USB_HID
+       depends on HID
        ---help---
        Support for UC-Logic tablets.
 
 config HID_WALTOP
        tristate "Waltop"
-       depends on USB_HID
+       depends on HID
        ---help---
        Support for Waltop tablets.
 
 config HID_GYRATION
        tristate "Gyration remote control"
-       depends on USB_HID
+       depends on HID
        ---help---
        Support for Gyration remote control.
 
 config HID_ICADE
        tristate "ION iCade arcade controller"
-       depends on BT_HIDP
+       depends on HID
        ---help---
        Support for the ION iCade arcade controller to work as a joystick.
 
@@ -276,20 +287,20 @@ config HID_ICADE
 
 config HID_TWINHAN
        tristate "Twinhan IR remote control"
-       depends on USB_HID
+       depends on HID
        ---help---
        Support for Twinhan IR remote control.
 
 config HID_KENSINGTON
        tristate "Kensington Slimblade Trackball" if EXPERT
-       depends on USB_HID
+       depends on HID
        default !EXPERT
        ---help---
        Support for Kensington Slimblade Trackball.
 
 config HID_LCPOWER
        tristate "LC-Power"
-       depends on USB_HID
+       depends on HID
        ---help---
        Support for LC-Power RC1000MCE RF remote control.
 
@@ -308,7 +319,7 @@ config HID_LENOVO_TPKBD
 
 config HID_LOGITECH
        tristate "Logitech devices" if EXPERT
-       depends on USB_HID
+       depends on HID
        default !EXPERT
        ---help---
        Support for Logitech devices that are not fully compliant with HID standard.
@@ -373,31 +384,31 @@ config LOGIWHEELS_FF
          - Logitech Formula Force EX
 
 config HID_MAGICMOUSE
-       tristate "Apple MagicMouse multi-touch support"
-       depends on BT_HIDP
+       tristate "Apple Magic Mouse/Trackpad multi-touch support"
+       depends on HID
        ---help---
-       Support for the Apple Magic Mouse multi-touch.
+       Support for the Apple Magic Mouse/Trackpad multi-touch.
 
        Say Y here if you want support for the multi-touch features of the
-       Apple Wireless "Magic" Mouse.
+       Apple Wireless "Magic" Mouse and the Apple Wireless "Magic" Trackpad.
 
 config HID_MICROSOFT
        tristate "Microsoft non-fully HID-compliant devices" if EXPERT
-       depends on USB_HID
+       depends on HID
        default !EXPERT
        ---help---
        Support for Microsoft devices that are not fully compliant with HID standard.
 
 config HID_MONTEREY
        tristate "Monterey Genius KB29E keyboard" if EXPERT
-       depends on USB_HID
+       depends on HID
        default !EXPERT
        ---help---
        Support for Monterey Genius KB29E.
 
 config HID_MULTITOUCH
        tristate "HID Multitouch panels"
-       depends on USB_HID
+       depends on HID
        ---help---
          Generic support for HID multitouch panels.
 
@@ -445,7 +456,7 @@ config HID_NTRIG
 
 config HID_ORTEK
        tristate "Ortek PKB-1700/WKB-2000/Skycable wireless keyboard and mouse trackpad"
-       depends on USB_HID
+       depends on HID
        ---help---
        There are certain devices which have LogicalMaximum wrong in the keyboard
        usage page of their report descriptor. The most prevailing ones so far
@@ -458,7 +469,7 @@ config HID_ORTEK
 
 config HID_PANTHERLORD
        tristate "Pantherlord/GreenAsia game controller"
-       depends on USB_HID
+       depends on HID
        ---help---
          Say Y here if you have a PantherLord/GreenAsia based game controller
          or adapter.
@@ -473,13 +484,13 @@ config PANTHERLORD_FF
 
 config HID_PETALYNX
        tristate "Petalynx Maxter remote control"
-       depends on USB_HID
+       depends on HID
        ---help---
        Support for Petalynx Maxter remote control.
 
 config HID_PICOLCD
        tristate "PicoLCD (graphic version)"
-       depends on USB_HID
+       depends on HID
        ---help---
          This provides support for Minibox PicoLCD devices, currently
          only the graphical ones are supported.
@@ -545,14 +556,14 @@ config HID_PICOLCD_CIR
 
 config HID_PRIMAX
        tristate "Primax non-fully HID-compliant devices"
-       depends on USB_HID
+       depends on HID
        ---help---
        Support for Primax devices that are not fully compliant with the
        HID standard.
 
 config HID_PS3REMOTE
        tristate "Sony PS3 BD Remote Control"
-       depends on BT_HIDP
+       depends on HID
        ---help---
        Support for the Sony PS3 Blue-ray Disk Remote Control and Logitech
        Harmony Adapter for PS3, which connect over Bluetooth.
@@ -569,7 +580,7 @@ config HID_ROCCAT
 
 config HID_SAITEK
        tristate "Saitek non-fully HID-compliant devices"
-       depends on USB_HID
+       depends on HID
        ---help---
        Support for Saitek devices that are not fully compliant with the
        HID standard.
@@ -578,7 +589,7 @@ config HID_SAITEK
 
 config HID_SAMSUNG
        tristate "Samsung InfraRed remote control or keyboards"
-       depends on USB_HID
+       depends on HID
        ---help---
        Support for Samsung InfraRed remote control or keyboards.
 
@@ -592,25 +603,25 @@ config HID_SONY
 
 config HID_SPEEDLINK
        tristate "Speedlink VAD Cezanne mouse support"
-       depends on USB_HID
+       depends on HID
        ---help---
        Support for Speedlink Vicious and Divine Cezanne mouse.
 
 config HID_STEELSERIES
        tristate "Steelseries SRW-S1 steering wheel support"
-       depends on USB_HID
+       depends on HID
        ---help---
        Support for Steelseries SRW-S1 steering wheel
 
 config HID_SUNPLUS
        tristate "Sunplus wireless desktop"
-       depends on USB_HID
+       depends on HID
        ---help---
        Support for Sunplus wireless desktop.
 
 config HID_GREENASIA
        tristate "GreenAsia (Product ID 0x12) game controller support"
-       depends on USB_HID
+       depends on HID
        ---help---
          Say Y here if you have a GreenAsia (Product ID 0x12) based game
          controller or adapter.
@@ -632,7 +643,7 @@ config HID_HYPERV_MOUSE
 
 config HID_SMARTJOYPLUS
        tristate "SmartJoy PLUS PS2/USB adapter support"
-       depends on USB_HID
+       depends on HID
        ---help---
        Support for SmartJoy PLUS PS2/USB adapter, Super Dual Box,
        Super Joy Box 3 Pro, Super Dual Box Pro, and Super Joy Box 5 Pro.
@@ -650,20 +661,20 @@ config SMARTJOYPLUS_FF
 
 config HID_TIVO
        tristate "TiVo Slide Bluetooth remote control support"
-       depends on (USB_HID || BT_HIDP)
+       depends on HID
        ---help---
        Say Y if you have a TiVo Slide Bluetooth remote control.
 
 config HID_TOPSEED
        tristate "TopSeed Cyberlink, BTC Emprex, Conceptronic remote control support"
-       depends on USB_HID
+       depends on HID
        ---help---
        Say Y if you have a TopSeed Cyberlink or BTC Emprex or Conceptronic
        CLLRCMCE remote control.
 
 config HID_THINGM
        tristate "ThingM blink(1) USB RGB LED"
-       depends on USB_HID
+       depends on HID
        depends on LEDS_CLASS
        ---help---
        Support for the ThingM blink(1) USB RGB LED. This driver registers a
@@ -673,7 +684,7 @@ config HID_THINGM
 
 config HID_THRUSTMASTER
        tristate "ThrustMaster devices support"
-       depends on USB_HID
+       depends on HID
        ---help---
          Say Y here if you have a THRUSTMASTER FireStore Dual Power 2 or
          a THRUSTMASTER Ferrari GT Rumble Wheel.
@@ -689,7 +700,7 @@ config THRUSTMASTER_FF
 
 config HID_WACOM
        tristate "Wacom Bluetooth devices support"
-       depends on BT_HIDP
+       depends on HID
        depends on LEDS_CLASS
        select POWER_SUPPLY
        ---help---
@@ -697,7 +708,7 @@ config HID_WACOM
 
 config HID_WIIMOTE
        tristate "Nintendo Wii Remote support"
-       depends on BT_HIDP
+       depends on HID
        depends on LEDS_CLASS
        select POWER_SUPPLY
        select INPUT_FF_MEMLESS
@@ -715,7 +726,7 @@ config HID_WIIMOTE_EXT
 
 config HID_ZEROPLUS
        tristate "Zeroplus based game controller support"
-       depends on USB_HID
+       depends on HID
        ---help---
          Say Y here if you have a Zeroplus based game controller.
 
@@ -729,16 +740,16 @@ config ZEROPLUS_FF
 
 config HID_ZYDACRON
        tristate "Zydacron remote control support"
-       depends on USB_HID
+       depends on HID
        ---help---
        Support for Zydacron remote control.
 
 config HID_SENSOR_HUB
        tristate "HID Sensors framework support"
-       depends on USB_HID && GENERIC_HARDIRQS
+       depends on HID && GENERIC_HARDIRQS
        select MFD_CORE
        default n
-       -- help---
+       ---help---
          Support for HID Sensor framework. This creates a MFD instance
          for a sensor hub and identifies all the sensors connected to it.
          Each sensor is registered as a MFD cell, so that sensor specific
index 72d1b0bc0a97398a9e0294c4f391553b979b9ffa..2065694f57abe482693371988781421404a2485e 100644 (file)
@@ -39,6 +39,7 @@ endif
 obj-$(CONFIG_HID_A4TECH)       += hid-a4tech.o
 obj-$(CONFIG_HID_ACRUX)                += hid-axff.o
 obj-$(CONFIG_HID_APPLE)                += hid-apple.o
+obj-$(CONFIG_HID_APPLEIR)      += hid-appleir.o
 obj-$(CONFIG_HID_AUREAL)        += hid-aureal.o
 obj-$(CONFIG_HID_BELKIN)       += hid-belkin.o
 obj-$(CONFIG_HID_CHERRY)       += hid-cherry.o
@@ -94,8 +95,8 @@ obj-$(CONFIG_HID_PRIMAX)      += hid-primax.o
 obj-$(CONFIG_HID_PS3REMOTE)    += hid-ps3remote.o
 obj-$(CONFIG_HID_ROCCAT)       += hid-roccat.o hid-roccat-common.o \
        hid-roccat-arvo.o hid-roccat-isku.o hid-roccat-kone.o \
-       hid-roccat-koneplus.o hid-roccat-kovaplus.o hid-roccat-lua.o \
-       hid-roccat-pyra.o hid-roccat-savu.o
+       hid-roccat-koneplus.o hid-roccat-konepure.o hid-roccat-kovaplus.o \
+       hid-roccat-lua.o hid-roccat-pyra.o hid-roccat-savu.o
 obj-$(CONFIG_HID_SAITEK)       += hid-saitek.o
 obj-$(CONFIG_HID_SAMSUNG)      += hid-samsung.o
 obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o
index 320a958d4139ce57fc386087a93bffa23054d13f..feae88b53fcd7597bc477aeef4dae7182f8f05ed 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/hid.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <linux/usb.h>
 
 #include "hid-ids.h"
 
@@ -390,10 +389,6 @@ static void apple_remove(struct hid_device *hdev)
 }
 
 static const struct hid_device_id apple_devices[] = {
-       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ATV_IRCONTROL),
-               .driver_data = APPLE_HIDDEV | APPLE_IGNORE_HIDINPUT },
-       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4),
-               .driver_data = APPLE_HIDDEV | APPLE_IGNORE_HIDINPUT },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE),
                .driver_data = APPLE_MIGHTYMOUSE | APPLE_INVERT_HWHEEL },
 
diff --git a/drivers/hid/hid-appleir.c b/drivers/hid/hid-appleir.c
new file mode 100644 (file)
index 0000000..a42e6a3
--- /dev/null
@@ -0,0 +1,352 @@
+/*
+ * HID driver for the apple ir device
+ *
+ * Original driver written by James McKenzie
+ * Ported to recent 2.6 kernel versions by Greg Kroah-Hartman <gregkh@suse.de>
+ * Updated to support newer remotes by Bastien Nocera <hadess@hadess.net>
+ * Ported to HID subsystem by Benjamin Tissoires <benjamin.tissoires@gmail.com>
+ *
+ * Copyright (C) 2006 James McKenzie
+ * Copyright (C) 2008 Greg Kroah-Hartman <greg@kroah.com>
+ * Copyright (C) 2008 Novell Inc.
+ * Copyright (C) 2010, 2012 Bastien Nocera <hadess@hadess.net>
+ * Copyright (C) 2013 Benjamin Tissoires <benjamin.tissoires@gmail.com>
+ * Copyright (C) 2013 Red Hat Inc. All Rights Reserved
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+#include "hid-ids.h"
+
+MODULE_AUTHOR("James McKenzie");
+MODULE_AUTHOR("Benjamin Tissoires <benjamin.tissoires@redhat.com>");
+MODULE_DESCRIPTION("HID Apple IR remote controls");
+MODULE_LICENSE("GPL");
+
+#define KEY_MASK               0x0F
+#define TWO_PACKETS_MASK       0x40
+
+/*
+ * James McKenzie has two devices both of which report the following
+ * 25 87 ee 83 0a      +
+ * 25 87 ee 83 0c      -
+ * 25 87 ee 83 09      <<
+ * 25 87 ee 83 06      >>
+ * 25 87 ee 83 05      >"
+ * 25 87 ee 83 03      menu
+ * 26 00 00 00 00      for key repeat
+ */
+
+/*
+ * Thomas Glanzmann reports the following responses
+ * 25 87 ee ca 0b      +
+ * 25 87 ee ca 0d      -
+ * 25 87 ee ca 08      <<
+ * 25 87 ee ca 07      >>
+ * 25 87 ee ca 04      >"
+ * 25 87 ee ca 02      menu
+ * 26 00 00 00 00       for key repeat
+ *
+ * He also observes the following event sometimes
+ * sent after a key is release, which I interpret
+ * as a flat battery message
+ * 25 87 e0 ca 06      flat battery
+ */
+
+/*
+ * Alexandre Karpenko reports the following responses for Device ID 0x8242
+ * 25 87 ee 47 0b      +
+ * 25 87 ee 47 0d      -
+ * 25 87 ee 47 08      <<
+ * 25 87 ee 47 07      >>
+ * 25 87 ee 47 04      >"
+ * 25 87 ee 47 02      menu
+ * 26 87 ee 47 **      for key repeat (** is the code of the key being held)
+ */
+
+/*
+ * Bastien Nocera's remote
+ * 25 87 ee 91 5f      followed by
+ * 25 87 ee 91 05      gives you >"
+ *
+ * 25 87 ee 91 5c      followed by
+ * 25 87 ee 91 05      gives you the middle button
+ */
+
+/*
+ * Fabien Andre's remote
+ * 25 87 ee a3 5e      followed by
+ * 25 87 ee a3 04      gives you >"
+ *
+ * 25 87 ee a3 5d      followed by
+ * 25 87 ee a3 04      gives you the middle button
+ */
+
+static const unsigned short appleir_key_table[] = {
+       KEY_RESERVED,
+       KEY_MENU,
+       KEY_PLAYPAUSE,
+       KEY_FORWARD,
+       KEY_BACK,
+       KEY_VOLUMEUP,
+       KEY_VOLUMEDOWN,
+       KEY_RESERVED,
+       KEY_RESERVED,
+       KEY_RESERVED,
+       KEY_RESERVED,
+       KEY_RESERVED,
+       KEY_RESERVED,
+       KEY_RESERVED,
+       KEY_ENTER,
+       KEY_PLAYPAUSE,
+       KEY_RESERVED,
+};
+
+struct appleir {
+       struct input_dev *input_dev;
+       struct hid_device *hid;
+       unsigned short keymap[ARRAY_SIZE(appleir_key_table)];
+       struct timer_list key_up_timer; /* timer for key up */
+       spinlock_t lock;                /* protects .current_key */
+       int current_key;                /* the currently pressed key */
+       int prev_key_idx;               /* key index in a 2 packets message */
+};
+
+static int get_key(int data)
+{
+       /*
+        * The key is coded accross bits 2..9:
+        *
+        * 0x00 or 0x01 (        )      key:  0         -> KEY_RESERVED
+        * 0x02 or 0x03 (  menu  )      key:  1         -> KEY_MENU
+        * 0x04 or 0x05 (   >"   )      key:  2         -> KEY_PLAYPAUSE
+        * 0x06 or 0x07 (   >>   )      key:  3         -> KEY_FORWARD
+        * 0x08 or 0x09 (   <<   )      key:  4         -> KEY_BACK
+        * 0x0a or 0x0b (    +   )      key:  5         -> KEY_VOLUMEUP
+        * 0x0c or 0x0d (    -   )      key:  6         -> KEY_VOLUMEDOWN
+        * 0x0e or 0x0f (        )      key:  7         -> KEY_RESERVED
+        * 0x50 or 0x51 (        )      key:  8         -> KEY_RESERVED
+        * 0x52 or 0x53 (        )      key:  9         -> KEY_RESERVED
+        * 0x54 or 0x55 (        )      key: 10         -> KEY_RESERVED
+        * 0x56 or 0x57 (        )      key: 11         -> KEY_RESERVED
+        * 0x58 or 0x59 (        )      key: 12         -> KEY_RESERVED
+        * 0x5a or 0x5b (        )      key: 13         -> KEY_RESERVED
+        * 0x5c or 0x5d ( middle )      key: 14         -> KEY_ENTER
+        * 0x5e or 0x5f (   >"   )      key: 15         -> KEY_PLAYPAUSE
+        *
+        * Packets starting with 0x5 are part of a two-packets message,
+        * we notify the caller by sending a negative value.
+        */
+       int key = (data >> 1) & KEY_MASK;
+
+       if ((data & TWO_PACKETS_MASK))
+               /* Part of a 2 packets-command */
+               key = -key;
+
+       return key;
+}
+
+static void key_up(struct hid_device *hid, struct appleir *appleir, int key)
+{
+       input_report_key(appleir->input_dev, key, 0);
+       input_sync(appleir->input_dev);
+}
+
+static void key_down(struct hid_device *hid, struct appleir *appleir, int key)
+{
+       input_report_key(appleir->input_dev, key, 1);
+       input_sync(appleir->input_dev);
+}
+
+static void battery_flat(struct appleir *appleir)
+{
+       dev_err(&appleir->input_dev->dev, "possible flat battery?\n");
+}
+
+static void key_up_tick(unsigned long data)
+{
+       struct appleir *appleir = (struct appleir *)data;
+       struct hid_device *hid = appleir->hid;
+       unsigned long flags;
+
+       spin_lock_irqsave(&appleir->lock, flags);
+       if (appleir->current_key) {
+               key_up(hid, appleir, appleir->current_key);
+               appleir->current_key = 0;
+       }
+       spin_unlock_irqrestore(&appleir->lock, flags);
+}
+
+static int appleir_raw_event(struct hid_device *hid, struct hid_report *report,
+        u8 *data, int len)
+{
+       struct appleir *appleir = hid_get_drvdata(hid);
+       static const u8 keydown[] = { 0x25, 0x87, 0xee };
+       static const u8 keyrepeat[] = { 0x26, };
+       static const u8 flatbattery[] = { 0x25, 0x87, 0xe0 };
+       unsigned long flags;
+
+       if (len != 5)
+               goto out;
+
+       if (!memcmp(data, keydown, sizeof(keydown))) {
+               int index;
+
+               spin_lock_irqsave(&appleir->lock, flags);
+               /*
+                * If we already have a key down, take it up before marking
+                * this one down
+                */
+               if (appleir->current_key)
+                       key_up(hid, appleir, appleir->current_key);
+
+               /* Handle dual packet commands */
+               if (appleir->prev_key_idx > 0)
+                       index = appleir->prev_key_idx;
+               else
+                       index = get_key(data[4]);
+
+               if (index >= 0) {
+                       appleir->current_key = appleir->keymap[index];
+
+                       key_down(hid, appleir, appleir->current_key);
+                       /*
+                        * Remote doesn't do key up, either pull them up, in
+                        * the test above, or here set a timer which pulls
+                        * them up after 1/8 s
+                        */
+                       mod_timer(&appleir->key_up_timer, jiffies + HZ / 8);
+                       appleir->prev_key_idx = 0;
+               } else
+                       /* Remember key for next packet */
+                       appleir->prev_key_idx = -index;
+               spin_unlock_irqrestore(&appleir->lock, flags);
+               goto out;
+       }
+
+       appleir->prev_key_idx = 0;
+
+       if (!memcmp(data, keyrepeat, sizeof(keyrepeat))) {
+               key_down(hid, appleir, appleir->current_key);
+               /*
+                * Remote doesn't do key up, either pull them up, in the test
+                * above, or here set a timer which pulls them up after 1/8 s
+                */
+               mod_timer(&appleir->key_up_timer, jiffies + HZ / 8);
+               goto out;
+       }
+
+       if (!memcmp(data, flatbattery, sizeof(flatbattery))) {
+               battery_flat(appleir);
+               /* Fall through */
+       }
+
+out:
+       /* let hidraw and hiddev handle the report */
+       return 0;
+}
+
+static void appleir_input_configured(struct hid_device *hid,
+               struct hid_input *hidinput)
+{
+       struct input_dev *input_dev = hidinput->input;
+       struct appleir *appleir = hid_get_drvdata(hid);
+       int i;
+
+       appleir->input_dev = input_dev;
+
+       input_dev->keycode = appleir->keymap;
+       input_dev->keycodesize = sizeof(unsigned short);
+       input_dev->keycodemax = ARRAY_SIZE(appleir->keymap);
+
+       input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+
+       memcpy(appleir->keymap, appleir_key_table, sizeof(appleir->keymap));
+       for (i = 0; i < ARRAY_SIZE(appleir_key_table); i++)
+               set_bit(appleir->keymap[i], input_dev->keybit);
+       clear_bit(KEY_RESERVED, input_dev->keybit);
+}
+
+static int appleir_input_mapping(struct hid_device *hid,
+               struct hid_input *hi, struct hid_field *field,
+               struct hid_usage *usage, unsigned long **bit, int *max)
+{
+       return -1;
+}
+
+static int appleir_probe(struct hid_device *hid, const struct hid_device_id *id)
+{
+       int ret;
+       struct appleir *appleir;
+
+       appleir = kzalloc(sizeof(struct appleir), GFP_KERNEL);
+       if (!appleir) {
+               ret = -ENOMEM;
+               goto allocfail;
+       }
+
+       appleir->hid = hid;
+
+       spin_lock_init(&appleir->lock);
+       setup_timer(&appleir->key_up_timer,
+                   key_up_tick, (unsigned long) appleir);
+
+       hid_set_drvdata(hid, appleir);
+
+       ret = hid_parse(hid);
+       if (ret) {
+               hid_err(hid, "parse failed\n");
+               goto fail;
+       }
+
+       ret = hid_hw_start(hid, HID_CONNECT_DEFAULT | HID_CONNECT_HIDDEV_FORCE);
+       if (ret) {
+               hid_err(hid, "hw start failed\n");
+               goto fail;
+       }
+
+       return 0;
+fail:
+       kfree(appleir);
+allocfail:
+       return ret;
+}
+
+static void appleir_remove(struct hid_device *hid)
+{
+       struct appleir *appleir = hid_get_drvdata(hid);
+       hid_hw_stop(hid);
+       del_timer_sync(&appleir->key_up_timer);
+       kfree(appleir);
+}
+
+static const struct hid_device_id appleir_devices[] = {
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL2) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL3) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL5) },
+       { }
+};
+MODULE_DEVICE_TABLE(hid, appleir_devices);
+
+static struct hid_driver appleir_driver = {
+       .name = "appleir",
+       .id_table = appleir_devices,
+       .raw_event = appleir_raw_event,
+       .input_configured = appleir_input_configured,
+       .probe = appleir_probe,
+       .remove = appleir_remove,
+       .input_mapping = appleir_input_mapping,
+};
+module_hid_driver(appleir_driver);
index 62f0cee032bada140bdcfcd84418c366c54c6015..64ab94a55aa796515958206986a991003a750069 100644 (file)
 
 #include <linux/input.h>
 #include <linux/slab.h>
-#include <linux/usb.h>
 #include <linux/hid.h>
 #include <linux/module.h>
 
 #include "hid-ids.h"
 
 #ifdef CONFIG_HID_ACRUX_FF
-#include "usbhid/usbhid.h"
 
 struct axff_device {
        struct hid_report *report;
@@ -68,7 +66,7 @@ static int axff_play(struct input_dev *dev, void *data, struct ff_effect *effect
        }
 
        dbg_hid("running with 0x%02x 0x%02x", left, right);
-       usbhid_submit_report(hid, axff->report, USB_DIR_OUT);
+       hid_hw_request(hid, axff->report, HID_REQ_SET_REPORT);
 
        return 0;
 }
@@ -114,7 +112,7 @@ static int axff_init(struct hid_device *hid)
                goto err_free_mem;
 
        axff->report = report;
-       usbhid_submit_report(hid, axff->report, USB_DIR_OUT);
+       hid_hw_request(hid, axff->report, HID_REQ_SET_REPORT);
 
        hid_info(hid, "Force Feedback for ACRUX game controllers by Sergei Kolzun <x0r@dv-life.ru>\n");
 
index aa341d135867eea541c9ffdd7113f75641eef5c4..6961bbeab3edb0c9a75767865c87bc2a6a6b4386 100644 (file)
@@ -728,8 +728,7 @@ static int hid_scan_report(struct hid_device *hid)
                } else if (page == HID_UP_SENSOR &&
                        item.type == HID_ITEM_TYPE_MAIN &&
                        item.tag == HID_MAIN_ITEM_TAG_BEGIN_COLLECTION &&
-                       (item_udata(&item) & 0xff) == HID_COLLECTION_PHYSICAL &&
-                       (hid->bus == BUS_USB || hid->bus == BUS_I2C))
+                       (item_udata(&item) & 0xff) == HID_COLLECTION_PHYSICAL)
                        hid->group = HID_GROUP_SENSOR_HUB;
        }
 
@@ -1260,14 +1259,12 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i
        struct hid_report_enum *report_enum;
        struct hid_driver *hdrv;
        struct hid_report *report;
-       char *buf;
-       unsigned int i;
        int ret = 0;
 
        if (!hid)
                return -ENODEV;
 
-       if (down_trylock(&hid->driver_lock))
+       if (down_trylock(&hid->driver_input_lock))
                return -EBUSY;
 
        if (!hid->driver) {
@@ -1284,28 +1281,9 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i
        }
 
        /* Avoid unnecessary overhead if debugfs is disabled */
-       if (list_empty(&hid->debug_list))
-               goto nomem;
-
-       buf = kmalloc(sizeof(char) * HID_DEBUG_BUFSIZE, GFP_ATOMIC);
-
-       if (!buf)
-               goto nomem;
-
-       /* dump the report */
-       snprintf(buf, HID_DEBUG_BUFSIZE - 1,
-                       "\nreport (size %u) (%snumbered) = ", size, report_enum->numbered ? "" : "un");
-       hid_debug_event(hid, buf);
-
-       for (i = 0; i < size; i++) {
-               snprintf(buf, HID_DEBUG_BUFSIZE - 1,
-                               " %02x", data[i]);
-               hid_debug_event(hid, buf);
-       }
-       hid_debug_event(hid, "\n");
-       kfree(buf);
+       if (!list_empty(&hid->debug_list))
+               hid_dump_report(hid, type, data, size);
 
-nomem:
        report = hid_get_report(report_enum, data);
 
        if (!report) {
@@ -1324,7 +1302,7 @@ nomem:
        ret = hid_report_raw_event(hid, type, data, size, interrupt);
 
 unlock:
-       up(&hid->driver_lock);
+       up(&hid->driver_input_lock);
        return ret;
 }
 EXPORT_SYMBOL_GPL(hid_input_report);
@@ -1502,8 +1480,6 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D) },
        { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_RP_649) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0x0802) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ATV_IRCONTROL) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICMOUSE) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICTRACKPAD) },
@@ -1527,6 +1503,11 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL2) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL3) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL5) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS) },
@@ -1654,6 +1635,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K_JP) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_LK6K) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K) },
@@ -1687,6 +1669,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ARVO) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKU) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPURE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KOVAPLUS) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_LUA) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRED) },
@@ -1747,6 +1730,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
 
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO, USB_DEVICE_ID_NINTENDO_WIIMOTE) },
+       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO, USB_DEVICE_ID_NINTENDO_WIIMOTE2) },
        { }
 };
 
@@ -1845,6 +1829,11 @@ static int hid_device_probe(struct device *dev)
 
        if (down_interruptible(&hdev->driver_lock))
                return -EINTR;
+       if (down_interruptible(&hdev->driver_input_lock)) {
+               ret = -EINTR;
+               goto unlock_driver_lock;
+       }
+       hdev->io_started = false;
 
        if (!hdev->driver) {
                id = hid_match_device(hdev, hdrv);
@@ -1867,6 +1856,9 @@ static int hid_device_probe(struct device *dev)
                }
        }
 unlock:
+       if (!hdev->io_started)
+               up(&hdev->driver_input_lock);
+unlock_driver_lock:
        up(&hdev->driver_lock);
        return ret;
 }
@@ -1875,9 +1867,15 @@ static int hid_device_remove(struct device *dev)
 {
        struct hid_device *hdev = container_of(dev, struct hid_device, dev);
        struct hid_driver *hdrv;
+       int ret = 0;
 
        if (down_interruptible(&hdev->driver_lock))
                return -EINTR;
+       if (down_interruptible(&hdev->driver_input_lock)) {
+               ret = -EINTR;
+               goto unlock_driver_lock;
+       }
+       hdev->io_started = false;
 
        hdrv = hdev->driver;
        if (hdrv) {
@@ -1889,8 +1887,11 @@ static int hid_device_remove(struct device *dev)
                hdev->driver = NULL;
        }
 
+       if (!hdev->io_started)
+               up(&hdev->driver_input_lock);
+unlock_driver_lock:
        up(&hdev->driver_lock);
-       return 0;
+       return ret;
 }
 
 static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
@@ -2340,7 +2341,9 @@ struct hid_device *hid_allocate_device(void)
 
        init_waitqueue_head(&hdev->debug_wait);
        INIT_LIST_HEAD(&hdev->debug_list);
+       mutex_init(&hdev->debug_list_lock);
        sema_init(&hdev->driver_lock, 1);
+       sema_init(&hdev->driver_input_lock, 1);
 
        return hdev;
 }
index 933fff0fff1ffc1f2dce372eeb0f6905688a947c..7e56cb3855e329696abea711445bffe588d101f6 100644 (file)
@@ -580,17 +580,49 @@ void hid_debug_event(struct hid_device *hdev, char *buf)
        int i;
        struct hid_debug_list *list;
 
+       mutex_lock(&hdev->debug_list_lock);
        list_for_each_entry(list, &hdev->debug_list, node) {
                for (i = 0; i < strlen(buf); i++)
                        list->hid_debug_buf[(list->tail + i) % HID_DEBUG_BUFSIZE] =
                                buf[i];
                list->tail = (list->tail + i) % HID_DEBUG_BUFSIZE;
         }
+       mutex_unlock(&hdev->debug_list_lock);
 
        wake_up_interruptible(&hdev->debug_wait);
 }
 EXPORT_SYMBOL_GPL(hid_debug_event);
 
+void hid_dump_report(struct hid_device *hid, int type, u8 *data,
+               int size)
+{
+       struct hid_report_enum *report_enum;
+       char *buf;
+       unsigned int i;
+
+       buf = kmalloc(sizeof(char) * HID_DEBUG_BUFSIZE, GFP_ATOMIC);
+
+       if (!buf)
+               return;
+
+       report_enum = hid->report_enum + type;
+
+       /* dump the report */
+       snprintf(buf, HID_DEBUG_BUFSIZE - 1,
+                       "\nreport (size %u) (%snumbered) = ", size,
+                       report_enum->numbered ? "" : "un");
+       hid_debug_event(hid, buf);
+
+       for (i = 0; i < size; i++) {
+               snprintf(buf, HID_DEBUG_BUFSIZE - 1,
+                               " %02x", data[i]);
+               hid_debug_event(hid, buf);
+       }
+       hid_debug_event(hid, "\n");
+       kfree(buf);
+}
+EXPORT_SYMBOL_GPL(hid_dump_report);
+
 void hid_dump_input(struct hid_device *hdev, struct hid_usage *usage, __s32 value)
 {
        char *buf;
@@ -960,7 +992,9 @@ static int hid_debug_events_open(struct inode *inode, struct file *file)
        file->private_data = list;
        mutex_init(&list->read_mutex);
 
+       mutex_lock(&list->hdev->debug_list_lock);
        list_add_tail(&list->node, &list->hdev->debug_list);
+       mutex_unlock(&list->hdev->debug_list_lock);
 
 out:
        return err;
@@ -1055,7 +1089,9 @@ static int hid_debug_events_release(struct inode *inode, struct file *file)
 {
        struct hid_debug_list *list = file->private_data;
 
+       mutex_lock(&list->hdev->debug_list_lock);
        list_del(&list->node);
+       mutex_unlock(&list->hdev->debug_list_lock);
        kfree(list->hid_debug_buf);
        kfree(list);
 
index 0fe8f65ef01a64c7d68155946498a28acbeaf63e..ce0644424f587707e68023f066eefecc50048d6b 100644 (file)
 
 #include <linux/input.h>
 #include <linux/slab.h>
-#include <linux/usb.h>
 #include <linux/hid.h>
 #include <linux/module.h>
 
 #include "hid-ids.h"
 
 #ifdef CONFIG_DRAGONRISE_FF
-#include "usbhid/usbhid.h"
 
 struct drff_device {
        struct hid_report *report;
@@ -68,7 +66,7 @@ static int drff_play(struct input_dev *dev, void *data,
                drff->report->field[0]->value[1] = 0x00;
                drff->report->field[0]->value[2] = weak;
                drff->report->field[0]->value[4] = strong;
-               usbhid_submit_report(hid, drff->report, USB_DIR_OUT);
+               hid_hw_request(hid, drff->report, HID_REQ_SET_REPORT);
 
                drff->report->field[0]->value[0] = 0xfa;
                drff->report->field[0]->value[1] = 0xfe;
@@ -80,7 +78,7 @@ static int drff_play(struct input_dev *dev, void *data,
        drff->report->field[0]->value[2] = 0x00;
        drff->report->field[0]->value[4] = 0x00;
        dbg_hid("running with 0x%02x 0x%02x", strong, weak);
-       usbhid_submit_report(hid, drff->report, USB_DIR_OUT);
+       hid_hw_request(hid, drff->report, HID_REQ_SET_REPORT);
 
        return 0;
 }
@@ -132,7 +130,7 @@ static int drff_init(struct hid_device *hid)
        drff->report->field[0]->value[4] = 0x00;
        drff->report->field[0]->value[5] = 0x00;
        drff->report->field[0]->value[6] = 0x00;
-       usbhid_submit_report(hid, drff->report, USB_DIR_OUT);
+       hid_hw_request(hid, drff->report, HID_REQ_SET_REPORT);
 
        hid_info(hid, "Force Feedback for DragonRise Inc. "
                 "game controllers by Richard Walmsley <richwalm@gmail.com>\n");
index 2e093ab99b435885c1f4d0ba5c6511ffe64993b9..d82d75bb11f78b591483233bc294aaf3a5939a72 100644 (file)
 
 #include <linux/hid.h>
 #include <linux/input.h>
-#include <linux/usb.h>
 #include <linux/module.h>
 
 #include "hid-ids.h"
-#include "usbhid/usbhid.h"
 
 struct emsff_device {
        struct hid_report *report;
@@ -52,7 +50,7 @@ static int emsff_play(struct input_dev *dev, void *data,
        emsff->report->field[0]->value[2] = strong;
 
        dbg_hid("running with 0x%02x 0x%02x\n", strong, weak);
-       usbhid_submit_report(hid, emsff->report, USB_DIR_OUT);
+       hid_hw_request(hid, emsff->report, HID_REQ_SET_REPORT);
 
        return 0;
 }
@@ -104,7 +102,7 @@ static int emsff_init(struct hid_device *hid)
        emsff->report->field[0]->value[4] = 0x00;
        emsff->report->field[0]->value[5] = 0x00;
        emsff->report->field[0]->value[6] = 0x00;
-       usbhid_submit_report(hid, emsff->report, USB_DIR_OUT);
+       hid_hw_request(hid, emsff->report, HID_REQ_SET_REPORT);
 
        hid_info(hid, "force feedback for EMS based devices by Ignaz Forster <ignaz.forster@gmx.de>\n");
 
index 04d2e6aca77841983ba16bce0d1b312f2fb2e1bc..2d8cead3adcaadf68e30ea9a4f37c7fc21452d50 100644 (file)
 
 #include <linux/input.h>
 #include <linux/slab.h>
-#include <linux/usb.h>
 #include <linux/hid.h>
 #include <linux/module.h>
 #include "hid-ids.h"
 
 #ifdef CONFIG_GREENASIA_FF
-#include "usbhid/usbhid.h"
 
 struct gaff_device {
        struct hid_report *report;
@@ -63,14 +61,14 @@ static int hid_gaff_play(struct input_dev *dev, void *data,
        gaff->report->field[0]->value[4] = left;
        gaff->report->field[0]->value[5] = 0;
        dbg_hid("running with 0x%02x 0x%02x", left, right);
-       usbhid_submit_report(hid, gaff->report, USB_DIR_OUT);
+       hid_hw_request(hid, gaff->report, HID_REQ_SET_REPORT);
 
        gaff->report->field[0]->value[0] = 0xfa;
        gaff->report->field[0]->value[1] = 0xfe;
        gaff->report->field[0]->value[2] = 0x0;
        gaff->report->field[0]->value[4] = 0x0;
 
-       usbhid_submit_report(hid, gaff->report, USB_DIR_OUT);
+       hid_hw_request(hid, gaff->report, HID_REQ_SET_REPORT);
 
        return 0;
 }
@@ -122,12 +120,12 @@ static int gaff_init(struct hid_device *hid)
        gaff->report->field[0]->value[1] = 0x00;
        gaff->report->field[0]->value[2] = 0x00;
        gaff->report->field[0]->value[3] = 0x00;
-       usbhid_submit_report(hid, gaff->report, USB_DIR_OUT);
+       hid_hw_request(hid, gaff->report, HID_REQ_SET_REPORT);
 
        gaff->report->field[0]->value[0] = 0xfa;
        gaff->report->field[0]->value[1] = 0xfe;
 
-       usbhid_submit_report(hid, gaff->report, USB_DIR_OUT);
+       hid_hw_request(hid, gaff->report, HID_REQ_SET_REPORT);
 
        hid_info(hid, "Force Feedback for GreenAsia 0x12 devices by Lukasz Lubojanski <lukasz@lubojanski.info>\n");
 
index f34d1186a3e1b16b4604c5f057ab411cff1bcc2f..9a8f051245258973f53ad84f8debef8b2f6db7e9 100644 (file)
 #include <linux/input.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <linux/usb.h>
 
 #include "hid-ids.h"
 
 #ifdef CONFIG_HOLTEK_FF
-#include "usbhid/usbhid.h"
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Anssi Hannula <anssi.hannula@iki.fi>");
@@ -102,7 +100,7 @@ static void holtekff_send(struct holtekff_device *holtekff,
 
        dbg_hid("sending %*ph\n", 7, data);
 
-       usbhid_submit_report(hid, holtekff->field->report, USB_DIR_OUT);
+       hid_hw_request(hid, holtekff->field->report, HID_REQ_SET_REPORT);
 }
 
 static int holtekff_play(struct input_dev *dev, void *data,
index 09dcc04595f35c7798b68aed97fdf79f64947328..76b5a7570780b8110b0904277c262f3f995fd8cf 100644 (file)
@@ -159,7 +159,7 @@ static const struct icade_key icade_usage_table[30] = {
 
 static const struct icade_key *icade_find_translation(u16 from)
 {
-       if (from < 0 || from > ICADE_MAX_USAGE)
+       if (from > ICADE_MAX_USAGE)
                return NULL;
        return &icade_usage_table[from];
 }
index 5309fd5eb0ebae7357044046f91ec9e0efe7e345..38535c9243d532b36d8cd321638fd4f2aeabb9c4 100644 (file)
 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO   0x0256
 #define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY   0x030a
 #define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY    0x030b
-#define USB_DEVICE_ID_APPLE_ATV_IRCONTROL      0x8241
+#define USB_DEVICE_ID_APPLE_IRCONTROL  0x8240
+#define USB_DEVICE_ID_APPLE_IRCONTROL2 0x1440
+#define USB_DEVICE_ID_APPLE_IRCONTROL3 0x8241
 #define USB_DEVICE_ID_APPLE_IRCONTROL4 0x8242
+#define USB_DEVICE_ID_APPLE_IRCONTROL5 0x8243
 
 #define USB_VENDOR_ID_ASUS             0x0486
 #define USB_DEVICE_ID_ASUS_T91MT       0x0185
 #define USB_DEVICE_ID_SIDEWINDER_GV    0x003b
 #define USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0 0x009d
 #define USB_DEVICE_ID_MS_NE4K          0x00db
+#define USB_DEVICE_ID_MS_NE4K_JP       0x00dc
 #define USB_DEVICE_ID_MS_LK6K          0x00f9
 #define USB_DEVICE_ID_MS_PRESENTER_8K_BT       0x0701
 #define USB_DEVICE_ID_MS_PRESENTER_8K_USB      0x0713
 
 #define USB_VENDOR_ID_NINTENDO         0x057e
 #define USB_DEVICE_ID_NINTENDO_WIIMOTE 0x0306
+#define USB_DEVICE_ID_NINTENDO_WIIMOTE2        0x0330
 
 #define USB_VENDOR_ID_NOVATEK          0x0603
 #define USB_DEVICE_ID_NOVATEK_PCT      0x0600
 #define USB_VENDOR_ID_ROCCAT           0x1e7d
 #define USB_DEVICE_ID_ROCCAT_ARVO      0x30d4
 #define USB_DEVICE_ID_ROCCAT_ISKU      0x319c
+#define USB_DEVICE_ID_ROCCAT_ISKUFX    0x3264
 #define USB_DEVICE_ID_ROCCAT_KONE      0x2ced
 #define USB_DEVICE_ID_ROCCAT_KONEPLUS  0x2d51
+#define USB_DEVICE_ID_ROCCAT_KONEPURE  0x2dbe
 #define USB_DEVICE_ID_ROCCAT_KONEXTD   0x2e22
 #define USB_DEVICE_ID_ROCCAT_KOVAPLUS  0x2d50
 #define USB_DEVICE_ID_ROCCAT_LUA       0x2c2e
index 21b196c394b197d222e0d1f58ac52f37d65b3e5d..945b8158ec4c7f556d6c9db8753762ac958276c1 100644 (file)
@@ -1198,6 +1198,67 @@ static struct hid_input *hidinput_allocate(struct hid_device *hid)
        return hidinput;
 }
 
+static bool hidinput_has_been_populated(struct hid_input *hidinput)
+{
+       int i;
+       unsigned long r = 0;
+
+       for (i = 0; i < BITS_TO_LONGS(EV_CNT); i++)
+               r |= hidinput->input->evbit[i];
+
+       for (i = 0; i < BITS_TO_LONGS(KEY_CNT); i++)
+               r |= hidinput->input->keybit[i];
+
+       for (i = 0; i < BITS_TO_LONGS(REL_CNT); i++)
+               r |= hidinput->input->relbit[i];
+
+       for (i = 0; i < BITS_TO_LONGS(ABS_CNT); i++)
+               r |= hidinput->input->absbit[i];
+
+       for (i = 0; i < BITS_TO_LONGS(MSC_CNT); i++)
+               r |= hidinput->input->mscbit[i];
+
+       for (i = 0; i < BITS_TO_LONGS(LED_CNT); i++)
+               r |= hidinput->input->ledbit[i];
+
+       for (i = 0; i < BITS_TO_LONGS(SND_CNT); i++)
+               r |= hidinput->input->sndbit[i];
+
+       for (i = 0; i < BITS_TO_LONGS(FF_CNT); i++)
+               r |= hidinput->input->ffbit[i];
+
+       for (i = 0; i < BITS_TO_LONGS(SW_CNT); i++)
+               r |= hidinput->input->swbit[i];
+
+       return !!r;
+}
+
+static void hidinput_cleanup_hidinput(struct hid_device *hid,
+               struct hid_input *hidinput)
+{
+       struct hid_report *report;
+       int i, k;
+
+       list_del(&hidinput->list);
+       input_free_device(hidinput->input);
+
+       for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) {
+               if (k == HID_OUTPUT_REPORT &&
+                       hid->quirks & HID_QUIRK_SKIP_OUTPUT_REPORTS)
+                       continue;
+
+               list_for_each_entry(report, &hid->report_enum[k].report_list,
+                                   list) {
+
+                       for (i = 0; i < report->maxfield; i++)
+                               if (report->field[i]->hidinput == hidinput)
+                                       report->field[i]->hidinput = NULL;
+               }
+       }
+
+       kfree(hidinput);
+}
+
 /*
  * Register the input device; print a message.
  * Configure the input layer interface
@@ -1249,6 +1310,10 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
                                        hidinput_configure_usage(hidinput, report->field[i],
                                                                 report->field[i]->usage + j);
 
+                       if ((hid->quirks & HID_QUIRK_NO_EMPTY_INPUT) &&
+                           !hidinput_has_been_populated(hidinput))
+                               continue;
+
                        if (hid->quirks & HID_QUIRK_MULTI_INPUT) {
                                /* This will leave hidinput NULL, so that it
                                 * allocates another one if we have more inputs on
@@ -1265,6 +1330,18 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
                }
        }
 
+       if (hidinput && (hid->quirks & HID_QUIRK_NO_EMPTY_INPUT) &&
+           !hidinput_has_been_populated(hidinput)) {
+               /* no need to register an input device not populated */
+               hidinput_cleanup_hidinput(hid, hidinput);
+               hidinput = NULL;
+       }
+
+       if (list_empty(&hid->inputs)) {
+               hid_err(hid, "No inputs registered, leaving\n");
+               goto out_unwind;
+       }
+
        if (hidinput) {
                if (drv->input_configured)
                        drv->input_configured(hid, hidinput);
index ef72daecfa16337aa66b2a712d6c64457d4db777..6af90dbdc3d45e1295db182588c6a8bbae2978ca 100644 (file)
@@ -16,8 +16,6 @@
 #include <linux/device.h>
 #include <linux/hid.h>
 #include <linux/module.h>
-#include <linux/usb.h>
-#include "usbhid/usbhid.h"
 
 #include "hid-ids.h"
 
@@ -361,7 +359,7 @@ static int kye_tablet_enable(struct hid_device *hdev)
        value[4] = 0x00;
        value[5] = 0x00;
        value[6] = 0x00;
-       usbhid_submit_report(hdev, report, USB_DIR_OUT);
+       hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
 
        return 0;
 }
index 956c3b135f64fe61e4a4636e2e81e911ad3ee141..07837f5a4eb88adaae7ba8c20f4517a15754b440 100644 (file)
@@ -68,7 +68,7 @@ static int tpkbd_features_set(struct hid_device *hdev)
        report->field[2]->value[0] = data_pointer->sensitivity;
        report->field[3]->value[0] = data_pointer->press_speed;
 
-       usbhid_submit_report(hdev, report, USB_DIR_OUT);
+       hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
        return 0;
 }
 
@@ -228,8 +228,6 @@ static ssize_t pointer_press_speed_show(struct device *dev,
        struct hid_device *hdev = container_of(dev, struct hid_device, dev);
        struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
 
-       data_pointer = hid_get_drvdata(hdev);
-
        return snprintf(buf, PAGE_SIZE, "%u\n",
                data_pointer->press_speed);
 }
@@ -332,7 +330,7 @@ static void tpkbd_led_brightness_set(struct led_classdev *led_cdev,
        report = hdev->report_enum[HID_OUTPUT_REPORT].report_id_hash[3];
        report->field[0]->value[0] = (data_pointer->led_state >> 0) & 1;
        report->field[0]->value[1] = (data_pointer->led_state >> 1) & 1;
-       usbhid_submit_report(hdev, report, USB_DIR_OUT);
+       hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
 }
 
 static int tpkbd_probe_tp(struct hid_device *hdev)
index 3c31bc650e5d6e8b957618fb9d9dd306f677c22f..b3cd1507dda2eab0eb09c0c48e006505eabac153 100644 (file)
 
 #include <linux/input.h>
 #include <linux/slab.h>
-#include <linux/usb.h>
 #include <linux/hid.h>
 
-#include "usbhid/usbhid.h"
 #include "hid-lg.h"
 
 struct lg2ff_device {
@@ -56,7 +54,7 @@ static int play_effect(struct input_dev *dev, void *data,
                lg2ff->report->field[0]->value[4] = 0x00;
        }
 
-       usbhid_submit_report(hid, lg2ff->report, USB_DIR_OUT);
+       hid_hw_request(hid, lg2ff->report, HID_REQ_SET_REPORT);
        return 0;
 }
 
@@ -108,7 +106,7 @@ int lg2ff_init(struct hid_device *hid)
        report->field[0]->value[5] = 0x00;
        report->field[0]->value[6] = 0x00;
 
-       usbhid_submit_report(hid, report, USB_DIR_OUT);
+       hid_hw_request(hid, report, HID_REQ_SET_REPORT);
 
        hid_info(hid, "Force feedback for Logitech RumblePad/Rumblepad 2 by Anssi Hannula <anssi.hannula@gmail.com>\n");
 
index f98644c26c1dfc2ccc181a23fee0d94b6c6e03ef..e52f181f6aa14dd4fd8229ce2ecb379ccf80533c 100644 (file)
 
 
 #include <linux/input.h>
-#include <linux/usb.h>
 #include <linux/hid.h>
 
-#include "usbhid/usbhid.h"
 #include "hid-lg.h"
 
 /*
@@ -92,7 +90,7 @@ static int hid_lg3ff_play(struct input_dev *dev, void *data,
                report->field[0]->value[1] = (unsigned char)(-x);
                report->field[0]->value[31] = (unsigned char)(-y);
 
-               usbhid_submit_report(hid, report, USB_DIR_OUT);
+               hid_hw_request(hid, report, HID_REQ_SET_REPORT);
                break;
        }
        return 0;
@@ -118,7 +116,7 @@ static void hid_lg3ff_set_autocenter(struct input_dev *dev, u16 magnitude)
        report->field[0]->value[33] = 0x7F;
        report->field[0]->value[34] = 0x7F;
 
-       usbhid_submit_report(hid, report, USB_DIR_OUT);
+       hid_hw_request(hid, report, HID_REQ_SET_REPORT);
 }
 
 
index 65a6ec8d37421343d597f2a42234a84532205ae0..0ddae2a00d59a595b4d7ad436dc8cedcfdde7b71 100644 (file)
@@ -34,6 +34,7 @@
 
 #define DFGT_REV_MAJ 0x13
 #define DFGT_REV_MIN 0x22
+#define DFGT2_REV_MIN 0x26
 #define DFP_REV_MAJ 0x11
 #define DFP_REV_MIN 0x06
 #define FFEX_REV_MAJ 0x21
@@ -125,6 +126,7 @@ static const struct lg4ff_native_cmd native_g27 = {
 
 static const struct lg4ff_usb_revision lg4ff_revs[] = {
        {DFGT_REV_MAJ, DFGT_REV_MIN, &native_dfgt},     /* Driving Force GT */
+       {DFGT_REV_MAJ, DFGT2_REV_MIN, &native_dfgt},    /* Driving Force GT v2 */
        {DFP_REV_MAJ,  DFP_REV_MIN,  &native_dfp},      /* Driving Force Pro */
        {G25_REV_MAJ,  G25_REV_MIN,  &native_g25},      /* G25 */
        {G27_REV_MAJ,  G27_REV_MIN,  &native_g27},      /* G27 */
@@ -202,7 +204,7 @@ static int hid_lg4ff_play(struct input_dev *dev, void *data, struct ff_effect *e
                value[5] = 0x00;
                value[6] = 0x00;
 
-               usbhid_submit_report(hid, report, USB_DIR_OUT);
+               hid_hw_request(hid, report, HID_REQ_SET_REPORT);
                break;
        }
        return 0;
@@ -225,7 +227,7 @@ static void hid_lg4ff_set_autocenter_default(struct input_dev *dev, u16 magnitud
        value[5] = 0x00;
        value[6] = 0x00;
 
-       usbhid_submit_report(hid, report, USB_DIR_OUT);
+       hid_hw_request(hid, report, HID_REQ_SET_REPORT);
 }
 
 /* Sends autocentering command compatible with Formula Force EX */
@@ -245,7 +247,7 @@ static void hid_lg4ff_set_autocenter_ffex(struct input_dev *dev, u16 magnitude)
        value[5] = 0x00;
        value[6] = 0x00;
 
-       usbhid_submit_report(hid, report, USB_DIR_OUT);
+       hid_hw_request(hid, report, HID_REQ_SET_REPORT);
 }
 
 /* Sends command to set range compatible with G25/G27/Driving Force GT */
@@ -265,7 +267,7 @@ static void hid_lg4ff_set_range_g25(struct hid_device *hid, u16 range)
        value[5] = 0x00;
        value[6] = 0x00;
 
-       usbhid_submit_report(hid, report, USB_DIR_OUT);
+       hid_hw_request(hid, report, HID_REQ_SET_REPORT);
 }
 
 /* Sends commands to set range compatible with Driving Force Pro wheel */
@@ -294,7 +296,7 @@ static void hid_lg4ff_set_range_dfp(struct hid_device *hid, __u16 range)
                report->field[0]->value[1] = 0x02;
                full_range = 200;
        }
-       usbhid_submit_report(hid, report, USB_DIR_OUT);
+       hid_hw_request(hid, report, HID_REQ_SET_REPORT);
 
        /* Prepare "fine" limit command */
        value[0] = 0x81;
@@ -306,7 +308,7 @@ static void hid_lg4ff_set_range_dfp(struct hid_device *hid, __u16 range)
        value[6] = 0x00;
 
        if (range == 200 || range == 900) {     /* Do not apply any fine limit */
-               usbhid_submit_report(hid, report, USB_DIR_OUT);
+               hid_hw_request(hid, report, HID_REQ_SET_REPORT);
                return;
        }
 
@@ -320,7 +322,7 @@ static void hid_lg4ff_set_range_dfp(struct hid_device *hid, __u16 range)
        value[5] = (start_right & 0xe) << 4 | (start_left & 0xe);
        value[6] = 0xff;
 
-       usbhid_submit_report(hid, report, USB_DIR_OUT);
+       hid_hw_request(hid, report, HID_REQ_SET_REPORT);
 }
 
 static void hid_lg4ff_switch_native(struct hid_device *hid, const struct lg4ff_native_cmd *cmd)
@@ -334,7 +336,7 @@ static void hid_lg4ff_switch_native(struct hid_device *hid, const struct lg4ff_n
                for (i = 0; i < 7; i++)
                        report->field[0]->value[i] = cmd->cmd[j++];
 
-               usbhid_submit_report(hid, report, USB_DIR_OUT);
+               hid_hw_request(hid, report, HID_REQ_SET_REPORT);
        }
 }
 
@@ -410,7 +412,7 @@ static void lg4ff_set_leds(struct hid_device *hid, __u8 leds)
        value[4] = 0x00;
        value[5] = 0x00;
        value[6] = 0x00;
-       usbhid_submit_report(hid, report, USB_DIR_OUT);
+       hid_hw_request(hid, report, HID_REQ_SET_REPORT);
 }
 
 static void lg4ff_led_set_brightness(struct led_classdev *led_cdev,
index 27bc54f92f4484d7efc0ef687d70082c725b337f..d7ea8c845b4038ec2a943baa6f169ade22e82e3d 100644 (file)
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/input.h>
-#include <linux/usb.h>
 #include <linux/hid.h>
 
-#include "usbhid/usbhid.h"
 #include "hid-lg.h"
 
 struct dev_type {
@@ -89,7 +87,7 @@ static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *ef
                report->field[0]->value[2] = x;
                report->field[0]->value[3] = y;
                dbg_hid("(x, y)=(%04x, %04x)\n", x, y);
-               usbhid_submit_report(hid, report, USB_DIR_OUT);
+               hid_hw_request(hid, report, HID_REQ_SET_REPORT);
                break;
 
        case FF_RUMBLE:
@@ -104,7 +102,7 @@ static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *ef
                report->field[0]->value[2] = left;
                report->field[0]->value[3] = right;
                dbg_hid("(left, right)=(%04x, %04x)\n", left, right);
-               usbhid_submit_report(hid, report, USB_DIR_OUT);
+               hid_hw_request(hid, report, HID_REQ_SET_REPORT);
                break;
        }
        return 0;
@@ -124,7 +122,7 @@ static void hid_lgff_set_autocenter(struct input_dev *dev, u16 magnitude)
        *value++ = 0x80;
        *value++ = 0x00;
        *value = 0x00;
-       usbhid_submit_report(hid, report, USB_DIR_OUT);
+       hid_hw_request(hid, report, HID_REQ_SET_REPORT);
 }
 
 int lgff_init(struct hid_device* hid)
index 8758f38c948c2022b45da342f15025228ea6b22d..5207591a598c05944a348be2252c4a346e0e5cfa 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/module.h>
 #include <linux/usb.h>
 #include <asm/unaligned.h>
-#include "usbhid/usbhid.h"
 #include "hid-ids.h"
 #include "hid-logitech-dj.h"
 
@@ -193,7 +192,6 @@ static struct hid_ll_driver logi_dj_ll_driver;
 static int logi_dj_output_hidraw_report(struct hid_device *hid, u8 * buf,
                                        size_t count,
                                        unsigned char report_type);
-static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev);
 
 static void logi_dj_recv_destroy_djhid_device(struct dj_receiver_dev *djrcv_dev,
                                                struct dj_report *dj_report)
@@ -234,7 +232,6 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev,
        if (dj_report->report_params[DEVICE_PAIRED_PARAM_SPFUNCTION] &
            SPFUNCTION_DEVICE_LIST_EMPTY) {
                dbg_hid("%s: device list is empty\n", __func__);
-               djrcv_dev->querying_devices = false;
                return;
        }
 
@@ -245,12 +242,6 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev,
                return;
        }
 
-       if (djrcv_dev->paired_dj_devices[dj_report->device_index]) {
-               /* The device is already known. No need to reallocate it. */
-               dbg_hid("%s: device is already known\n", __func__);
-               return;
-       }
-
        dj_hiddev = hid_allocate_device();
        if (IS_ERR(dj_hiddev)) {
                dev_err(&djrcv_hdev->dev, "%s: hid_allocate_device failed\n",
@@ -314,7 +305,6 @@ static void delayedwork_callback(struct work_struct *work)
        struct dj_report dj_report;
        unsigned long flags;
        int count;
-       int retval;
 
        dbg_hid("%s\n", __func__);
 
@@ -347,25 +337,6 @@ static void delayedwork_callback(struct work_struct *work)
                logi_dj_recv_destroy_djhid_device(djrcv_dev, &dj_report);
                break;
        default:
-       /* A normal report (i. e. not belonging to a pair/unpair notification)
-        * arriving here, means that the report arrived but we did not have a
-        * paired dj_device associated to the report's device_index, this
-        * means that the original "device paired" notification corresponding
-        * to this dj_device never arrived to this driver. The reason is that
-        * hid-core discards all packets coming from a device while probe() is
-        * executing. */
-       if (!djrcv_dev->paired_dj_devices[dj_report.device_index]) {
-               /* ok, we don't know the device, just re-ask the
-                * receiver for the list of connected devices. */
-               retval = logi_dj_recv_query_paired_devices(djrcv_dev);
-               if (!retval) {
-                       /* everything went fine, so just leave */
-                       break;
-               }
-               dev_err(&djrcv_dev->hdev->dev,
-                       "%s:logi_dj_recv_query_paired_devices "
-                       "error:%d\n", __func__, retval);
-               }
                dbg_hid("%s: unexpected report type\n", __func__);
        }
 }
@@ -396,12 +367,6 @@ static void logi_dj_recv_forward_null_report(struct dj_receiver_dev *djrcv_dev,
        if (!djdev) {
                dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]"
                        " is NULL, index %d\n", dj_report->device_index);
-               kfifo_in(&djrcv_dev->notif_fifo, dj_report, sizeof(struct dj_report));
-
-               if (schedule_work(&djrcv_dev->work) == 0) {
-                       dbg_hid("%s: did not schedule the work item, was already "
-                       "queued\n", __func__);
-               }
                return;
        }
 
@@ -432,12 +397,6 @@ static void logi_dj_recv_forward_report(struct dj_receiver_dev *djrcv_dev,
        if (dj_device == NULL) {
                dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]"
                        " is NULL, index %d\n", dj_report->device_index);
-               kfifo_in(&djrcv_dev->notif_fifo, dj_report, sizeof(struct dj_report));
-
-               if (schedule_work(&djrcv_dev->work) == 0) {
-                       dbg_hid("%s: did not schedule the work item, was already "
-                       "queued\n", __func__);
-               }
                return;
        }
 
@@ -475,7 +434,7 @@ static int logi_dj_recv_send_report(struct dj_receiver_dev *djrcv_dev,
        for (i = 0; i < report->field[0]->report_count; i++)
                report->field[0]->value[i] = data[i];
 
-       usbhid_submit_report(hdev, report, USB_DIR_OUT);
+       hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
 
        return 0;
 }
@@ -485,10 +444,6 @@ static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev)
        struct dj_report *dj_report;
        int retval;
 
-       /* no need to protect djrcv_dev->querying_devices */
-       if (djrcv_dev->querying_devices)
-               return 0;
-
        dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL);
        if (!dj_report)
                return -ENOMEM;
@@ -500,7 +455,6 @@ static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev)
        return retval;
 }
 
-
 static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev,
                                          unsigned timeout)
 {
@@ -644,7 +598,7 @@ static int logi_dj_ll_input_event(struct input_dev *dev, unsigned int type,
        hid_set_field(report->field[0], 1, REPORT_TYPE_LEDS);
        hid_set_field(report->field[0], 2, data[1]);
 
-       usbhid_submit_report(dj_rcv_hiddev, report, USB_DIR_OUT);
+       hid_hw_request(dj_rcv_hiddev, report, HID_REQ_SET_REPORT);
 
        return 0;
 
@@ -809,6 +763,9 @@ static int logi_dj_probe(struct hid_device *hdev,
                goto llopen_failed;
        }
 
+       /* Allow incoming packets to arrive: */
+       hid_device_io_start(hdev);
+
        retval = logi_dj_recv_query_paired_devices(djrcv_dev);
        if (retval < 0) {
                dev_err(&hdev->dev, "%s:logi_dj_recv_query_paired_devices "
index 4a4000340ce1ed8cf6be1f81ee8e0f21d8ba5f5a..fd28a5e0ca3b84b8407791421b25f8b17bf7815a 100644 (file)
@@ -101,7 +101,6 @@ struct dj_receiver_dev {
        struct work_struct work;
        struct kfifo notif_fifo;
        spinlock_t lock;
-       bool querying_devices;
 };
 
 struct dj_device {
index a8ce44296cfddaf34a486a7c78edde4836cd3115..5bc37343eb22b3de7f3cca6163c6f1fd9a10dd4b 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/input/mt.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <linux/usb.h>
 
 #include "hid-ids.h"
 
index 29d27f65a1184b55cf40c8ca3c0940a5548d8324..551795b7da1d0cb93adbae8262803b779abe916d 100644 (file)
@@ -195,6 +195,8 @@ static const struct hid_device_id ms_devices[] = {
                .driver_data = MS_HIDINPUT },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K),
                .driver_data = MS_ERGONOMY },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K_JP),
+               .driver_data = MS_ERGONOMY },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_LK6K),
                .driver_data = MS_ERGONOMY | MS_RDESC },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB),
index 82e9211b3ca97cfec8f316d33870f22f6fac0617..dc3ae5c56f563bf7735ba4c6ee4bffa0f24ccdd0 100644 (file)
@@ -2,8 +2,9 @@
  *  HID driver for multitouch panels
  *
  *  Copyright (c) 2010-2012 Stephane Chatty <chatty@enac.fr>
- *  Copyright (c) 2010-2012 Benjamin Tissoires <benjamin.tissoires@gmail.com>
+ *  Copyright (c) 2010-2013 Benjamin Tissoires <benjamin.tissoires@gmail.com>
  *  Copyright (c) 2010-2012 Ecole Nationale de l'Aviation Civile, France
+ *  Copyright (c) 2012-2013 Red Hat, Inc
  *
  *  This code is partly based on hid-egalax.c:
  *
  * any later version.
  */
 
+/*
+ * This driver is regularly tested thanks to the tool hid-test[1].
+ * This tool relies on hid-replay[2] and a database of hid devices[3].
+ * Please run these regression tests before patching this module so that
+ * your patch won't break existing known devices.
+ *
+ * [1] https://github.com/bentiss/hid-test
+ * [2] https://github.com/bentiss/hid-replay
+ * [3] https://github.com/bentiss/hid-devices
+ */
+
 #include <linux/device.h>
 #include <linux/hid.h>
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/usb.h>
 #include <linux/input/mt.h>
-#include "usbhid/usbhid.h"
+#include <linux/string.h>
 
 
 MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
@@ -86,9 +98,9 @@ struct mt_device {
                                           multitouch fields */
        int cc_index;   /* contact count field index in the report */
        int cc_value_index;     /* contact count value index in the field */
-       unsigned last_field_index;      /* last field index of the report */
        unsigned last_slot_field;       /* the last field of a slot */
        unsigned mt_report_id;  /* the report ID of the multitouch device */
+       unsigned pen_report_id; /* the report ID of the pen device */
        __s8 inputmode;         /* InputMode HID feature, -1 if non-existent */
        __s8 inputmode_index;   /* InputMode HID feature index in the report */
        __s8 maxcontact_report_id;      /* Maximum Contact Number HID feature,
@@ -104,6 +116,9 @@ struct mt_device {
        unsigned mt_flags;      /* flags to pass to input-mt */
 };
 
+static void mt_post_parse_default_settings(struct mt_device *td);
+static void mt_post_parse(struct mt_device *td);
+
 /* classes of device behavior */
 #define MT_CLS_DEFAULT                         0x0001
 
@@ -246,6 +261,14 @@ static struct mt_class mt_classes[] = {
        { }
 };
 
+static void mt_free_input_name(struct hid_input *hi)
+{
+       struct hid_device *hdev = hi->report->device;
+
+       if (hi->input->name != hdev->name)
+               kfree(hi->input->name);
+}
+
 static ssize_t mt_show_quirks(struct device *dev,
                           struct device_attribute *attr,
                           char *buf)
@@ -354,7 +377,53 @@ static void mt_store_field(struct hid_usage *usage, struct mt_device *td,
        f->usages[f->length++] = usage->hid;
 }
 
-static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+static int mt_pen_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+               struct hid_field *field, struct hid_usage *usage,
+               unsigned long **bit, int *max)
+{
+       struct mt_device *td = hid_get_drvdata(hdev);
+
+       td->pen_report_id = field->report->id;
+
+       return 0;
+}
+
+static int mt_pen_input_mapped(struct hid_device *hdev, struct hid_input *hi,
+               struct hid_field *field, struct hid_usage *usage,
+               unsigned long **bit, int *max)
+{
+       return 0;
+}
+
+static int mt_pen_event(struct hid_device *hid, struct hid_field *field,
+                               struct hid_usage *usage, __s32 value)
+{
+       /* let hid-input handle it */
+       return 0;
+}
+
+static void mt_pen_report(struct hid_device *hid, struct hid_report *report)
+{
+       struct hid_field *field = report->field[0];
+
+       input_sync(field->hidinput->input);
+}
+
+static void mt_pen_input_configured(struct hid_device *hdev,
+                                       struct hid_input *hi)
+{
+       char *name = kzalloc(strlen(hi->input->name) + 5, GFP_KERNEL);
+       if (name) {
+               sprintf(name, "%s Pen", hi->input->name);
+               mt_free_input_name(hi);
+               hi->input->name = name;
+       }
+
+       /* force BTN_STYLUS to allow tablet matching in udev */
+       __set_bit(BTN_STYLUS, hi->input->keybit);
+}
+
+static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
                struct hid_field *field, struct hid_usage *usage,
                unsigned long **bit, int *max)
 {
@@ -363,13 +432,8 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
        int code;
        struct hid_usage *prev_usage = NULL;
 
-       /* Only map fields from TouchScreen or TouchPad collections.
-       * We need to ignore fields that belong to other collections
-       * such as Mouse that might have the same GenericDesktop usages. */
        if (field->application == HID_DG_TOUCHSCREEN)
                td->mt_flags |= INPUT_MT_DIRECT;
-       else if (field->application != HID_DG_TOUCHPAD)
-               return 0;
 
        /*
         * Model touchscreens providing buttons as touchpads.
@@ -378,12 +442,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
            (usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON)
                td->mt_flags |= INPUT_MT_POINTER;
 
-       /* eGalax devices provide a Digitizer.Stylus input which overrides
-        * the correct Digitizers.Finger X/Y ranges.
-        * Let's just ignore this input. */
-       if (field->physical == HID_DG_STYLUS)
-               return -1;
-
        if (usage->usage_index)
                prev_usage = &field->usage[usage->usage_index - 1];
 
@@ -405,7 +463,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
                        }
 
                        mt_store_field(usage, td, hi);
-                       td->last_field_index = field->index;
                        return 1;
                case HID_GD_Y:
                        if (prev_usage && (prev_usage->hid == usage->hid)) {
@@ -421,7 +478,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
                        }
 
                        mt_store_field(usage, td, hi);
-                       td->last_field_index = field->index;
                        return 1;
                }
                return 0;
@@ -436,21 +492,17 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
                                        ABS_MT_DISTANCE, 0, 1, 0, 0);
                        }
                        mt_store_field(usage, td, hi);
-                       td->last_field_index = field->index;
                        return 1;
                case HID_DG_CONFIDENCE:
                        mt_store_field(usage, td, hi);
-                       td->last_field_index = field->index;
                        return 1;
                case HID_DG_TIPSWITCH:
                        hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
                        input_set_capability(hi->input, EV_KEY, BTN_TOUCH);
                        mt_store_field(usage, td, hi);
-                       td->last_field_index = field->index;
                        return 1;
                case HID_DG_CONTACTID:
                        mt_store_field(usage, td, hi);
-                       td->last_field_index = field->index;
                        td->touches_by_report++;
                        td->mt_report_id = field->report->id;
                        return 1;
@@ -461,7 +513,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
                                set_abs(hi->input, ABS_MT_TOUCH_MAJOR, field,
                                        cls->sn_width);
                        mt_store_field(usage, td, hi);
-                       td->last_field_index = field->index;
                        return 1;
                case HID_DG_HEIGHT:
                        hid_map_usage(hi, usage, bit, max,
@@ -473,7 +524,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
                                        ABS_MT_ORIENTATION, 0, 1, 0, 0);
                        }
                        mt_store_field(usage, td, hi);
-                       td->last_field_index = field->index;
                        return 1;
                case HID_DG_TIPPRESSURE:
                        hid_map_usage(hi, usage, bit, max,
@@ -481,17 +531,14 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
                        set_abs(hi->input, ABS_MT_PRESSURE, field,
                                cls->sn_pressure);
                        mt_store_field(usage, td, hi);
-                       td->last_field_index = field->index;
                        return 1;
                case HID_DG_CONTACTCOUNT:
                        td->cc_index = field->index;
                        td->cc_value_index = usage->usage_index;
-                       td->last_field_index = field->index;
                        return 1;
                case HID_DG_CONTACTMAX:
                        /* we don't set td->last_slot_field as contactcount and
                         * contact max are global to the report */
-                       td->last_field_index = field->index;
                        return -1;
                case HID_DG_TOUCH:
                        /* Legacy devices use TIPSWITCH and not TOUCH.
@@ -515,7 +562,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
        return 0;
 }
 
-static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi,
+static int mt_touch_input_mapped(struct hid_device *hdev, struct hid_input *hi,
                struct hid_field *field, struct hid_usage *usage,
                unsigned long **bit, int *max)
 {
@@ -606,7 +653,7 @@ static void mt_sync_frame(struct mt_device *td, struct input_dev *input)
        td->num_received = 0;
 }
 
-static int mt_event(struct hid_device *hid, struct hid_field *field,
+static int mt_touch_event(struct hid_device *hid, struct hid_field *field,
                                struct hid_usage *usage, __s32 value)
 {
        /* we will handle the hidinput part later, now remains hiddev */
@@ -680,29 +727,19 @@ static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field,
                if (usage->usage_index + 1 == field->report_count) {
                        /* we only take into account the last report. */
                        if (usage->hid == td->last_slot_field)
-                               mt_complete_slot(td, input);
-
-                       if (field->index == td->last_field_index
-                               && td->num_received >= td->num_expected)
-                               mt_sync_frame(td, field->hidinput->input);
+                               mt_complete_slot(td, field->hidinput->input);
                }
 
        }
 }
 
-static void mt_report(struct hid_device *hid, struct hid_report *report)
+static void mt_touch_report(struct hid_device *hid, struct hid_report *report)
 {
        struct mt_device *td = hid_get_drvdata(hid);
        struct hid_field *field;
        unsigned count;
        int r, n;
 
-       if (report->id != td->mt_report_id)
-               return;
-
-       if (!(hid->claimed & HID_CLAIMED_INPUT))
-               return;
-
        /*
         * Includes multi-packet support where subsequent
         * packets are sent with zero contactcount.
@@ -725,6 +762,91 @@ static void mt_report(struct hid_device *hid, struct hid_report *report)
                        mt_process_mt_event(hid, field, &field->usage[n],
                                        field->value[n]);
        }
+
+       if (td->num_received >= td->num_expected)
+               mt_sync_frame(td, report->field[0]->hidinput->input);
+}
+
+static void mt_touch_input_configured(struct hid_device *hdev,
+                                       struct hid_input *hi)
+{
+       struct mt_device *td = hid_get_drvdata(hdev);
+       struct mt_class *cls = &td->mtclass;
+       struct input_dev *input = hi->input;
+
+       if (!td->maxcontacts)
+               td->maxcontacts = MT_DEFAULT_MAXCONTACT;
+
+       mt_post_parse(td);
+       if (td->serial_maybe)
+               mt_post_parse_default_settings(td);
+
+       if (cls->is_indirect)
+               td->mt_flags |= INPUT_MT_POINTER;
+
+       if (cls->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP)
+               td->mt_flags |= INPUT_MT_DROP_UNUSED;
+
+       input_mt_init_slots(input, td->maxcontacts, td->mt_flags);
+
+       td->mt_flags = 0;
+}
+
+static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+               struct hid_field *field, struct hid_usage *usage,
+               unsigned long **bit, int *max)
+{
+       /* Only map fields from TouchScreen or TouchPad collections.
+       * We need to ignore fields that belong to other collections
+       * such as Mouse that might have the same GenericDesktop usages. */
+       if (field->application != HID_DG_TOUCHSCREEN &&
+           field->application != HID_DG_PEN &&
+           field->application != HID_DG_TOUCHPAD)
+               return -1;
+
+       if (field->physical == HID_DG_STYLUS)
+               return mt_pen_input_mapping(hdev, hi, field, usage, bit, max);
+
+       return mt_touch_input_mapping(hdev, hi, field, usage, bit, max);
+}
+
+static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi,
+               struct hid_field *field, struct hid_usage *usage,
+               unsigned long **bit, int *max)
+{
+       if (field->physical == HID_DG_STYLUS)
+               return mt_pen_input_mapped(hdev, hi, field, usage, bit, max);
+
+       return mt_touch_input_mapped(hdev, hi, field, usage, bit, max);
+}
+
+static int mt_event(struct hid_device *hid, struct hid_field *field,
+                               struct hid_usage *usage, __s32 value)
+{
+       struct mt_device *td = hid_get_drvdata(hid);
+
+       if (field->report->id == td->mt_report_id)
+               return mt_touch_event(hid, field, usage, value);
+
+       if (field->report->id == td->pen_report_id)
+               return mt_pen_event(hid, field, usage, value);
+
+       /* ignore other reports */
+       return 1;
+}
+
+static void mt_report(struct hid_device *hid, struct hid_report *report)
+{
+       struct mt_device *td = hid_get_drvdata(hid);
+
+       if (!(hid->claimed & HID_CLAIMED_INPUT))
+               return;
+
+       if (report->id == td->mt_report_id)
+               mt_touch_report(hid, report);
+
+       if (report->id == td->pen_report_id)
+               mt_pen_report(hid, report);
 }
 
 static void mt_set_input_mode(struct hid_device *hdev)
@@ -740,7 +862,7 @@ static void mt_set_input_mode(struct hid_device *hdev)
        r = re->report_id_hash[td->inputmode];
        if (r) {
                r->field[0]->value[td->inputmode_index] = 0x02;
-               usbhid_submit_report(hdev, r, USB_DIR_OUT);
+               hid_hw_request(hdev, r, HID_REQ_SET_REPORT);
        }
 }
 
@@ -765,7 +887,7 @@ static void mt_set_maxcontacts(struct hid_device *hdev)
                max = min(fieldmax, max);
                if (r->field[0]->value[0] != max) {
                        r->field[0]->value[0] = max;
-                       usbhid_submit_report(hdev, r, USB_DIR_OUT);
+                       hid_hw_request(hdev, r, HID_REQ_SET_REPORT);
                }
        }
 }
@@ -801,32 +923,18 @@ static void mt_post_parse(struct mt_device *td)
 }
 
 static void mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
-
 {
        struct mt_device *td = hid_get_drvdata(hdev);
-       struct mt_class *cls = &td->mtclass;
-       struct input_dev *input = hi->input;
+       char *name = kstrdup(hdev->name, GFP_KERNEL);
 
-       /* Only initialize slots for MT input devices */
-       if (!test_bit(ABS_MT_POSITION_X, input->absbit))
-               return;
+       if (name)
+               hi->input->name = name;
 
-       if (!td->maxcontacts)
-               td->maxcontacts = MT_DEFAULT_MAXCONTACT;
+       if (hi->report->id == td->mt_report_id)
+               mt_touch_input_configured(hdev, hi);
 
-       mt_post_parse(td);
-       if (td->serial_maybe)
-               mt_post_parse_default_settings(td);
-
-       if (cls->is_indirect)
-               td->mt_flags |= INPUT_MT_POINTER;
-
-       if (cls->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP)
-               td->mt_flags |= INPUT_MT_DROP_UNUSED;
-
-       input_mt_init_slots(input, td->maxcontacts, td->mt_flags);
-
-       td->mt_flags = 0;
+       if (hi->report->id == td->pen_report_id)
+               mt_pen_input_configured(hdev, hi);
 }
 
 static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
@@ -834,6 +942,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
        int ret, i;
        struct mt_device *td;
        struct mt_class *mtclass = mt_classes; /* MT_CLS_DEFAULT */
+       struct hid_input *hi;
 
        for (i = 0; mt_classes[i].name ; i++) {
                if (id->driver_data == mt_classes[i].name) {
@@ -847,6 +956,14 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
         */
        hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC;
 
+       /*
+        * This allows the driver to handle different input sensors
+        * that emits events through different reports on the same HID
+        * device.
+        */
+       hdev->quirks |= HID_QUIRK_MULTI_INPUT;
+       hdev->quirks |= HID_QUIRK_NO_EMPTY_INPUT;
+
        td = kzalloc(sizeof(struct mt_device), GFP_KERNEL);
        if (!td) {
                dev_err(&hdev->dev, "cannot allocate multitouch data\n");
@@ -856,6 +973,8 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
        td->inputmode = -1;
        td->maxcontact_report_id = -1;
        td->cc_index = -1;
+       td->mt_report_id = -1;
+       td->pen_report_id = -1;
        hid_set_drvdata(hdev, td);
 
        td->fields = kzalloc(sizeof(struct mt_fields), GFP_KERNEL);
@@ -874,7 +993,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
 
        ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
        if (ret)
-               goto fail;
+               goto hid_fail;
 
        ret = sysfs_create_group(&hdev->dev.kobj, &mt_attribute_group);
 
@@ -886,6 +1005,9 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
 
        return 0;
 
+hid_fail:
+       list_for_each_entry(hi, &hdev->inputs, list)
+               mt_free_input_name(hi);
 fail:
        kfree(td->fields);
        kfree(td);
@@ -902,26 +1024,11 @@ static int mt_reset_resume(struct hid_device *hdev)
 
 static int mt_resume(struct hid_device *hdev)
 {
-       struct usb_interface *intf;
-       struct usb_host_interface *interface;
-       struct usb_device *dev;
-
-       if (hdev->bus != BUS_USB)
-               return 0;
-
-       intf = to_usb_interface(hdev->dev.parent);
-       interface = intf->cur_altsetting;
-       dev = hid_to_usb_dev(hdev);
-
        /* Some Elan legacy devices require SET_IDLE to be set on resume.
         * It should be safe to send it to other devices too.
         * Tested on 3M, Stantum, Cypress, Zytronic, eGalax, and Elan panels. */
 
-       usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-                       HID_REQ_SET_IDLE,
-                       USB_TYPE_CLASS | USB_RECIP_INTERFACE,
-                       0, interface->desc.bInterfaceNumber,
-                       NULL, 0, USB_CTRL_SET_TIMEOUT);
+       hid_hw_idle(hdev, 0, 0, HID_REQ_SET_IDLE);
 
        return 0;
 }
@@ -930,8 +1037,14 @@ static int mt_resume(struct hid_device *hdev)
 static void mt_remove(struct hid_device *hdev)
 {
        struct mt_device *td = hid_get_drvdata(hdev);
+       struct hid_input *hi;
+
        sysfs_remove_group(&hdev->dev.kobj, &mt_attribute_group);
        hid_hw_stop(hdev);
+
+       list_for_each_entry(hi, &hdev->inputs, list)
+               mt_free_input_name(hi);
+
        kfree(td);
        hid_set_drvdata(hdev, NULL);
 }
index 7757e82416e7f2270a1ebba2ef44070161424985..ef95102515e4d499143dd02a831481902d674b1e 100644 (file)
@@ -118,8 +118,8 @@ static inline int ntrig_get_mode(struct hid_device *hdev)
        if (!report)
                return -EINVAL;
 
-       usbhid_submit_report(hdev, report, USB_DIR_IN);
-       usbhid_wait_io(hdev);
+       hid_hw_request(hdev, report, HID_REQ_GET_REPORT);
+       hid_hw_wait(hdev);
        return (int)report->field[0]->value[0];
 }
 
@@ -137,7 +137,7 @@ static inline void ntrig_set_mode(struct hid_device *hdev, const int mode)
        if (!report)
                return;
 
-       usbhid_submit_report(hdev, report, USB_DIR_IN);
+       hid_hw_request(hdev, report, HID_REQ_GET_REPORT);
 }
 
 static void ntrig_report_version(struct hid_device *hdev)
@@ -937,8 +937,8 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id)
        if (report) {
                /* Let the device settle to ensure the wakeup message gets
                 * through */
-               usbhid_wait_io(hdev);
-               usbhid_submit_report(hdev, report, USB_DIR_IN);
+               hid_hw_wait(hdev);
+               hid_hw_request(hdev, report, HID_REQ_GET_REPORT);
 
                /*
                 * Sanity check: if the current mode is invalid reset it to
index 020cef69f6a13e07df8d8f9911b4c060b0773461..e56d847b2ef1996dfee6c5f60c39401db35dcf15 100644 (file)
@@ -142,10 +142,10 @@ struct hid_report *picolcd_report(int id, struct hid_device *hdev, int dir);
 #ifdef CONFIG_DEBUG_FS
 void picolcd_debug_out_report(struct picolcd_data *data,
                struct hid_device *hdev, struct hid_report *report);
-#define usbhid_submit_report(a, b, c) \
+#define hid_hw_request(a, b, c) \
        do { \
                picolcd_debug_out_report(hid_get_drvdata(a), a, b); \
-               usbhid_submit_report(a, b, c); \
+               hid_hw_request(a, b, c); \
        } while (0)
 
 void picolcd_debug_raw_event(struct picolcd_data *data,
@@ -302,7 +302,7 @@ static inline int picolcd_init_cir(struct picolcd_data *data, struct hid_report
 static inline void picolcd_exit_cir(struct picolcd_data *data)
 {
 }
-#endif /* CONFIG_HID_PICOLCD_LIRC */
+#endif /* CONFIG_HID_PICOLCD_CIR */
 
 int picolcd_reset(struct hid_device *hdev);
 struct picolcd_pending *picolcd_send_and_wait(struct hid_device *hdev,
index b91f30945f9c8eb6a6c10da73186040895d5eb3e..a32c5f86b0b3f667466b921f1ed4581ad1857b1e 100644 (file)
@@ -18,8 +18,6 @@
  ***************************************************************************/
 
 #include <linux/hid.h>
-#include "usbhid/usbhid.h"
-#include <linux/usb.h>
 
 #include <linux/fb.h>
 #include <linux/backlight.h>
@@ -46,7 +44,7 @@ static int picolcd_set_brightness(struct backlight_device *bdev)
        spin_lock_irqsave(&data->lock, flags);
        hid_set_field(report->field[0], 0, data->lcd_power == FB_BLANK_UNBLANK ? data->lcd_brightness : 0);
        if (!(data->status & PICOLCD_FAILED))
-               usbhid_submit_report(data->hdev, report, USB_DIR_OUT);
+               hid_hw_request(data->hdev, report, HID_REQ_SET_REPORT);
        spin_unlock_irqrestore(&data->lock, flags);
        return 0;
 }
index a79e95bb9fb69db2803a9f5c4ee8abccfbfc7f4b..e346038f0f111eaf1b47571552df952d10537760 100644 (file)
@@ -21,8 +21,6 @@
 #include <linux/hid-debug.h>
 #include <linux/input.h>
 #include "hid-ids.h"
-#include "usbhid/usbhid.h"
-#include <linux/usb.h>
 
 #include <linux/fb.h>
 #include <linux/vmalloc.h>
index 31cd93fc3d4bff26fb0275d102c90270483289e7..b48092d0e1394a73f4c4ef66a21bc490f4b686f0 100644 (file)
@@ -21,8 +21,6 @@
 #include <linux/hid-debug.h>
 #include <linux/input.h>
 #include "hid-ids.h"
-#include "usbhid/usbhid.h"
-#include <linux/usb.h>
 
 #include <linux/fb.h>
 #include <linux/vmalloc.h>
@@ -110,7 +108,7 @@ struct picolcd_pending *picolcd_send_and_wait(struct hid_device *hdev,
                work = NULL;
        } else {
                data->pending = work;
-               usbhid_submit_report(data->hdev, report, USB_DIR_OUT);
+               hid_hw_request(data->hdev, report, HID_REQ_SET_REPORT);
                spin_unlock_irqrestore(&data->lock, flags);
                wait_for_completion_interruptible_timeout(&work->ready, HZ*2);
                spin_lock_irqsave(&data->lock, flags);
@@ -244,7 +242,7 @@ int picolcd_reset(struct hid_device *hdev)
                spin_unlock_irqrestore(&data->lock, flags);
                return -ENODEV;
        }
-       usbhid_submit_report(hdev, report, USB_DIR_OUT);
+       hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
        spin_unlock_irqrestore(&data->lock, flags);
 
        error = picolcd_check_version(hdev);
@@ -303,7 +301,7 @@ static ssize_t picolcd_operation_mode_store(struct device *dev,
        spin_lock_irqsave(&data->lock, flags);
        hid_set_field(report->field[0], 0, timeout & 0xff);
        hid_set_field(report->field[0], 1, (timeout >> 8) & 0xff);
-       usbhid_submit_report(data->hdev, report, USB_DIR_OUT);
+       hid_hw_request(data->hdev, report, HID_REQ_SET_REPORT);
        spin_unlock_irqrestore(&data->lock, flags);
        return count;
 }
index 4809aa1bdb9c7551161cee1160c75d15131aca3e..59ab8e157e6b249d025ea26d4bd0ba4b2bb7f227 100644 (file)
@@ -19,8 +19,6 @@
 
 #include <linux/hid.h>
 #include <linux/hid-debug.h>
-#include "usbhid/usbhid.h"
-#include <linux/usb.h>
 
 #include <linux/fb.h>
 #include <linux/seq_file.h>
index eb003574b634790b3f5c97cf03c7cba300e3f9fb..591f6b22aa947190a9e728b650caa40090cc9595 100644 (file)
@@ -19,8 +19,6 @@
 
 #include <linux/hid.h>
 #include <linux/vmalloc.h>
-#include "usbhid/usbhid.h"
-#include <linux/usb.h>
 
 #include <linux/fb.h>
 #include <linux/module.h>
@@ -143,8 +141,8 @@ static int picolcd_fb_send_tile(struct picolcd_data *data, u8 *vbitmap,
                else
                        hid_set_field(report2->field[0], 4 + i - 32, tdata[i]);
 
-       usbhid_submit_report(data->hdev, report1, USB_DIR_OUT);
-       usbhid_submit_report(data->hdev, report2, USB_DIR_OUT);
+       hid_hw_request(data->hdev, report1, HID_REQ_SET_REPORT);
+       hid_hw_request(data->hdev, report2, HID_REQ_SET_REPORT);
        spin_unlock_irqrestore(&data->lock, flags);
        return 0;
 }
@@ -214,7 +212,7 @@ int picolcd_fb_reset(struct picolcd_data *data, int clear)
                                hid_set_field(report->field[0], j, mapcmd[j]);
                        else
                                hid_set_field(report->field[0], j, 0);
-               usbhid_submit_report(data->hdev, report, USB_DIR_OUT);
+               hid_hw_request(data->hdev, report, HID_REQ_SET_REPORT);
        }
        spin_unlock_irqrestore(&data->lock, flags);
 
@@ -270,7 +268,7 @@ static void picolcd_fb_update(struct fb_info *info)
                                mutex_unlock(&info->lock);
                                if (!data)
                                        return;
-                               usbhid_wait_io(data->hdev);
+                               hid_hw_wait(data->hdev);
                                mutex_lock(&info->lock);
                                n = 0;
                        }
@@ -288,7 +286,7 @@ static void picolcd_fb_update(struct fb_info *info)
                spin_unlock_irqrestore(&fbdata->lock, flags);
                mutex_unlock(&info->lock);
                if (data)
-                       usbhid_wait_io(data->hdev);
+                       hid_hw_wait(data->hdev);
                return;
        }
 out:
index 2d0ddc5ac65fe1b6d47f236c97a19a32585aee04..89821c2da6d76b766347ae629314d68df3033942 100644 (file)
@@ -18,8 +18,6 @@
  ***************************************************************************/
 
 #include <linux/hid.h>
-#include "usbhid/usbhid.h"
-#include <linux/usb.h>
 
 #include <linux/fb.h>
 #include <linux/lcd.h>
@@ -48,7 +46,7 @@ static int picolcd_set_contrast(struct lcd_device *ldev, int contrast)
        spin_lock_irqsave(&data->lock, flags);
        hid_set_field(report->field[0], 0, data->lcd_contrast);
        if (!(data->status & PICOLCD_FAILED))
-               usbhid_submit_report(data->hdev, report, USB_DIR_OUT);
+               hid_hw_request(data->hdev, report, HID_REQ_SET_REPORT);
        spin_unlock_irqrestore(&data->lock, flags);
        return 0;
 }
index 28cb6a4f96342c788d637f913b7649c2ab0510dc..e994f9c290128942a578a92e8934b2cc76effa86 100644 (file)
@@ -21,8 +21,6 @@
 #include <linux/hid-debug.h>
 #include <linux/input.h>
 #include "hid-ids.h"
-#include "usbhid/usbhid.h"
-#include <linux/usb.h>
 
 #include <linux/fb.h>
 #include <linux/vmalloc.h>
@@ -55,7 +53,7 @@ void picolcd_leds_set(struct picolcd_data *data)
        spin_lock_irqsave(&data->lock, flags);
        hid_set_field(report->field[0], 0, data->led_state);
        if (!(data->status & PICOLCD_FAILED))
-               usbhid_submit_report(data->hdev, report, USB_DIR_OUT);
+               hid_hw_request(data->hdev, report, HID_REQ_SET_REPORT);
        spin_unlock_irqrestore(&data->lock, flags);
 }
 
index b0199d27787b69a328d09488e5802f6e51b781a2..d29112fa5cd51a86b4c29c31398874cc5a726e3d 100644 (file)
 #include <linux/input.h>
 #include <linux/slab.h>
 #include <linux/module.h>
-#include <linux/usb.h>
 #include <linux/hid.h>
 
 #include "hid-ids.h"
 
 #ifdef CONFIG_PANTHERLORD_FF
-#include "usbhid/usbhid.h"
 
 struct plff_device {
        struct hid_report *report;
@@ -75,7 +73,7 @@ static int hid_plff_play(struct input_dev *dev, void *data,
        *plff->strong = left;
        *plff->weak = right;
        debug("running with 0x%02x 0x%02x", left, right);
-       usbhid_submit_report(hid, plff->report, USB_DIR_OUT);
+       hid_hw_request(hid, plff->report, HID_REQ_SET_REPORT);
 
        return 0;
 }
@@ -169,7 +167,7 @@ static int plff_init(struct hid_device *hid)
 
                *strong = 0x00;
                *weak = 0x00;
-               usbhid_submit_report(hid, plff->report, USB_DIR_OUT);
+               hid_hw_request(hid, plff->report, HID_REQ_SET_REPORT);
        }
 
        hid_info(hid, "Force feedback for PantherLord/GreenAsia devices by Anssi Hannula <anssi.hannula@gmail.com>\n");
index 4e1c4bcbdc039763ce170dbb7913bd56fd003d4d..7ed82805641477e5556dff5f12898f2f42095559 100644 (file)
@@ -26,7 +26,6 @@
 #include <sound/core.h>
 #include <sound/initval.h>
 #include <sound/rawmidi.h>
-#include "usbhid/usbhid.h"
 #include "hid-ids.h"
 
 
@@ -306,7 +305,7 @@ static void pcmidi_submit_output_report(struct pcmidi_snd *pm, int state)
        report->field[0]->value[0] = 0x01;
        report->field[0]->value[1] = state;
 
-       usbhid_submit_report(hdev, report, USB_DIR_OUT);
+       hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
 }
 
 static int pcmidi_handle_report1(struct pcmidi_snd *pm, u8 *data)
index 1219998a02d66e98ca11cecf0c740044b6801deb..8023751d525766ae16b32f8a8943f8c5f9b0796e 100644 (file)
@@ -130,14 +130,14 @@ static ssize_t isku_sysfs_read(struct file *fp, struct kobject *kobj,
        if (off >= real_size)
                return 0;
 
-       if (off != 0 || count != real_size)
+       if (off != 0 || count > real_size)
                return -EINVAL;
 
        mutex_lock(&isku->isku_lock);
-       retval = isku_receive(usb_dev, command, buf, real_size);
+       retval = isku_receive(usb_dev, command, buf, count);
        mutex_unlock(&isku->isku_lock);
 
-       return retval ? retval : real_size;
+       return retval ? retval : count;
 }
 
 static ssize_t isku_sysfs_write(struct file *fp, struct kobject *kobj,
@@ -150,15 +150,15 @@ static ssize_t isku_sysfs_write(struct file *fp, struct kobject *kobj,
        struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
        int retval;
 
-       if (off != 0 || count != real_size)
+       if (off != 0 || count > real_size)
                return -EINVAL;
 
        mutex_lock(&isku->isku_lock);
        retval = roccat_common2_send_with_status(usb_dev, command,
-                       (void *)buf, real_size);
+                       (void *)buf, count);
        mutex_unlock(&isku->isku_lock);
 
-       return retval ? retval : real_size;
+       return retval ? retval : count;
 }
 
 #define ISKU_SYSFS_W(thingy, THINGY) \
@@ -216,6 +216,7 @@ ISKU_SYSFS_RW(light, LIGHT)
 ISKU_SYSFS_RW(key_mask, KEY_MASK)
 ISKU_SYSFS_RW(last_set, LAST_SET)
 ISKU_SYSFS_W(talk, TALK)
+ISKU_SYSFS_W(talkfx, TALKFX)
 ISKU_SYSFS_R(info, INFO)
 ISKU_SYSFS_W(control, CONTROL)
 ISKU_SYSFS_W(reset, RESET)
@@ -232,6 +233,7 @@ static struct bin_attribute isku_bin_attributes[] = {
        ISKU_BIN_ATTR_RW(key_mask, KEY_MASK),
        ISKU_BIN_ATTR_RW(last_set, LAST_SET),
        ISKU_BIN_ATTR_W(talk, TALK),
+       ISKU_BIN_ATTR_W(talkfx, TALKFX),
        ISKU_BIN_ATTR_R(info, INFO),
        ISKU_BIN_ATTR_W(control, CONTROL),
        ISKU_BIN_ATTR_W(reset, RESET),
@@ -405,6 +407,7 @@ static int isku_raw_event(struct hid_device *hdev,
 
 static const struct hid_device_id isku_devices[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKU) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKUFX) },
        { }
 };
 
@@ -443,5 +446,5 @@ module_init(isku_init);
 module_exit(isku_exit);
 
 MODULE_AUTHOR("Stefan Achatz");
-MODULE_DESCRIPTION("USB Roccat Isku driver");
+MODULE_DESCRIPTION("USB Roccat Isku/FX driver");
 MODULE_LICENSE("GPL v2");
index cf6896c838679d7ec5527a7cb94037e16c1fd78a..53056860d4d859f53f391f7081191c3821376a2b 100644 (file)
@@ -25,10 +25,11 @@ enum {
        ISKU_SIZE_KEYS_MACRO = 0x23,
        ISKU_SIZE_KEYS_CAPSLOCK = 0x06,
        ISKU_SIZE_LAST_SET = 0x14,
-       ISKU_SIZE_LIGHT = 0x0a,
+       ISKU_SIZE_LIGHT = 0x10,
        ISKU_SIZE_MACRO = 0x823,
        ISKU_SIZE_RESET = 0x03,
        ISKU_SIZE_TALK = 0x10,
+       ISKU_SIZE_TALKFX = 0x10,
 };
 
 enum {
@@ -59,6 +60,7 @@ enum isku_commands {
        ISKU_COMMAND_LAST_SET = 0x14,
        ISKU_COMMAND_15 = 0x15,
        ISKU_COMMAND_TALK = 0x16,
+       ISKU_COMMAND_TALKFX = 0x17,
        ISKU_COMMAND_FIRMWARE_WRITE = 0x1b,
        ISKU_COMMAND_FIRMWARE_WRITE_CONTROL = 0x1c,
 };
index 9ce2d0b615a4ec969ad2f4329927023abdba6118..7fae070788fa2e4b03fb9281e792aaf9e24065a4 100644 (file)
@@ -818,8 +818,9 @@ static void kone_report_to_chrdev(struct kone_device const *kone,
                                (uint8_t *)&roccat_report);
                break;
        case kone_mouse_event_call_overlong_macro:
+       case kone_mouse_event_multimedia:
                if (event->value == kone_keystroke_action_press) {
-                       roccat_report.event = kone_mouse_event_call_overlong_macro;
+                       roccat_report.event = event->event;
                        roccat_report.value = kone->actual_profile;
                        roccat_report.key = event->macro_key;
                        roccat_report_event(kone->chrdev_minor,
index 64abb5b8a59a5909a759f3ef37e232a8991fb902..52c6167d023e6cca841b4efe2f9319d934780a43 100644 (file)
@@ -169,6 +169,7 @@ enum kone_mouse_events {
        /* TODO clarify meaning and occurence of kone_mouse_event_calibration */
        kone_mouse_event_calibration = 0xc0,
        kone_mouse_event_call_overlong_macro = 0xe0,
+       kone_mouse_event_multimedia = 0xe1,
        /* switch events notify if user changed values with mousebutton click */
        kone_mouse_event_switch_dpi = 0xf0,
        kone_mouse_event_switch_profile = 0xf1
diff --git a/drivers/hid/hid-roccat-konepure.c b/drivers/hid/hid-roccat-konepure.c
new file mode 100644 (file)
index 0000000..c79d0b0
--- /dev/null
@@ -0,0 +1,304 @@
+/*
+ * Roccat KonePure driver for Linux
+ *
+ * Copyright (c) 2012 Stefan Achatz <erazor_de@users.sourceforge.net>
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+/*
+ * Roccat KonePure is a smaller version of KoneXTD with less buttons and lights.
+ */
+
+#include <linux/device.h>
+#include <linux/input.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/hid-roccat.h>
+#include "hid-ids.h"
+#include "hid-roccat-common.h"
+#include "hid-roccat-konepure.h"
+
+static struct class *konepure_class;
+
+static ssize_t konepure_sysfs_read(struct file *fp, struct kobject *kobj,
+               char *buf, loff_t off, size_t count,
+               size_t real_size, uint command)
+{
+       struct device *dev =
+                       container_of(kobj, struct device, kobj)->parent->parent;
+       struct konepure_device *konepure = hid_get_drvdata(dev_get_drvdata(dev));
+       struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
+       int retval;
+
+       if (off >= real_size)
+               return 0;
+
+       if (off != 0 || count != real_size)
+               return -EINVAL;
+
+       mutex_lock(&konepure->konepure_lock);
+       retval = roccat_common2_receive(usb_dev, command, buf, real_size);
+       mutex_unlock(&konepure->konepure_lock);
+
+       return retval ? retval : real_size;
+}
+
+static ssize_t konepure_sysfs_write(struct file *fp, struct kobject *kobj,
+               void const *buf, loff_t off, size_t count,
+               size_t real_size, uint command)
+{
+       struct device *dev =
+                       container_of(kobj, struct device, kobj)->parent->parent;
+       struct konepure_device *konepure = hid_get_drvdata(dev_get_drvdata(dev));
+       struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
+       int retval;
+
+       if (off != 0 || count != real_size)
+               return -EINVAL;
+
+       mutex_lock(&konepure->konepure_lock);
+       retval = roccat_common2_send_with_status(usb_dev, command,
+                       (void *)buf, real_size);
+       mutex_unlock(&konepure->konepure_lock);
+
+       return retval ? retval : real_size;
+}
+
+#define KONEPURE_SYSFS_W(thingy, THINGY) \
+static ssize_t konepure_sysfs_write_ ## thingy(struct file *fp, \
+               struct kobject *kobj, struct bin_attribute *attr, char *buf, \
+               loff_t off, size_t count) \
+{ \
+       return konepure_sysfs_write(fp, kobj, buf, off, count, \
+                       KONEPURE_SIZE_ ## THINGY, KONEPURE_COMMAND_ ## THINGY); \
+}
+
+#define KONEPURE_SYSFS_R(thingy, THINGY) \
+static ssize_t konepure_sysfs_read_ ## thingy(struct file *fp, \
+               struct kobject *kobj, struct bin_attribute *attr, char *buf, \
+               loff_t off, size_t count) \
+{ \
+       return konepure_sysfs_read(fp, kobj, buf, off, count, \
+                       KONEPURE_SIZE_ ## THINGY, KONEPURE_COMMAND_ ## THINGY); \
+}
+
+#define KONEPURE_SYSFS_RW(thingy, THINGY) \
+KONEPURE_SYSFS_W(thingy, THINGY) \
+KONEPURE_SYSFS_R(thingy, THINGY)
+
+#define KONEPURE_BIN_ATTRIBUTE_RW(thingy, THINGY) \
+{ \
+       .attr = { .name = #thingy, .mode = 0660 }, \
+       .size = KONEPURE_SIZE_ ## THINGY, \
+       .read = konepure_sysfs_read_ ## thingy, \
+       .write = konepure_sysfs_write_ ## thingy \
+}
+
+#define KONEPURE_BIN_ATTRIBUTE_R(thingy, THINGY) \
+{ \
+       .attr = { .name = #thingy, .mode = 0440 }, \
+       .size = KONEPURE_SIZE_ ## THINGY, \
+       .read = konepure_sysfs_read_ ## thingy, \
+}
+
+#define KONEPURE_BIN_ATTRIBUTE_W(thingy, THINGY) \
+{ \
+       .attr = { .name = #thingy, .mode = 0220 }, \
+       .size = KONEPURE_SIZE_ ## THINGY, \
+       .write = konepure_sysfs_write_ ## thingy \
+}
+
+KONEPURE_SYSFS_RW(actual_profile, ACTUAL_PROFILE)
+KONEPURE_SYSFS_W(control, CONTROL)
+KONEPURE_SYSFS_RW(info, INFO)
+KONEPURE_SYSFS_W(talk, TALK)
+KONEPURE_SYSFS_W(macro, MACRO)
+KONEPURE_SYSFS_RW(sensor, SENSOR)
+KONEPURE_SYSFS_RW(tcu, TCU)
+KONEPURE_SYSFS_R(tcu_image, TCU_IMAGE)
+KONEPURE_SYSFS_RW(profile_settings, PROFILE_SETTINGS)
+KONEPURE_SYSFS_RW(profile_buttons, PROFILE_BUTTONS)
+
+static struct bin_attribute konepure_bin_attributes[] = {
+       KONEPURE_BIN_ATTRIBUTE_RW(actual_profile, ACTUAL_PROFILE),
+       KONEPURE_BIN_ATTRIBUTE_W(control, CONTROL),
+       KONEPURE_BIN_ATTRIBUTE_RW(info, INFO),
+       KONEPURE_BIN_ATTRIBUTE_W(talk, TALK),
+       KONEPURE_BIN_ATTRIBUTE_W(macro, MACRO),
+       KONEPURE_BIN_ATTRIBUTE_RW(sensor, SENSOR),
+       KONEPURE_BIN_ATTRIBUTE_RW(tcu, TCU),
+       KONEPURE_BIN_ATTRIBUTE_R(tcu_image, TCU_IMAGE),
+       KONEPURE_BIN_ATTRIBUTE_RW(profile_settings, PROFILE_SETTINGS),
+       KONEPURE_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS),
+       __ATTR_NULL
+};
+
+static int konepure_init_konepure_device_struct(struct usb_device *usb_dev,
+               struct konepure_device *konepure)
+{
+       mutex_init(&konepure->konepure_lock);
+
+       return 0;
+}
+
+static int konepure_init_specials(struct hid_device *hdev)
+{
+       struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
+       struct usb_device *usb_dev = interface_to_usbdev(intf);
+       struct konepure_device *konepure;
+       int retval;
+
+       if (intf->cur_altsetting->desc.bInterfaceProtocol
+                       != USB_INTERFACE_PROTOCOL_MOUSE) {
+               hid_set_drvdata(hdev, NULL);
+               return 0;
+       }
+
+       konepure = kzalloc(sizeof(*konepure), GFP_KERNEL);
+       if (!konepure) {
+               hid_err(hdev, "can't alloc device descriptor\n");
+               return -ENOMEM;
+       }
+       hid_set_drvdata(hdev, konepure);
+
+       retval = konepure_init_konepure_device_struct(usb_dev, konepure);
+       if (retval) {
+               hid_err(hdev, "couldn't init struct konepure_device\n");
+               goto exit_free;
+       }
+
+       retval = roccat_connect(konepure_class, hdev,
+                       sizeof(struct konepure_mouse_report_button));
+       if (retval < 0) {
+               hid_err(hdev, "couldn't init char dev\n");
+       } else {
+               konepure->chrdev_minor = retval;
+               konepure->roccat_claimed = 1;
+       }
+
+       return 0;
+exit_free:
+       kfree(konepure);
+       return retval;
+}
+
+static void konepure_remove_specials(struct hid_device *hdev)
+{
+       struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
+       struct konepure_device *konepure;
+
+       if (intf->cur_altsetting->desc.bInterfaceProtocol
+                       != USB_INTERFACE_PROTOCOL_MOUSE)
+               return;
+
+       konepure = hid_get_drvdata(hdev);
+       if (konepure->roccat_claimed)
+               roccat_disconnect(konepure->chrdev_minor);
+       kfree(konepure);
+}
+
+static int konepure_probe(struct hid_device *hdev,
+               const struct hid_device_id *id)
+{
+       int retval;
+
+       retval = hid_parse(hdev);
+       if (retval) {
+               hid_err(hdev, "parse failed\n");
+               goto exit;
+       }
+
+       retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+       if (retval) {
+               hid_err(hdev, "hw start failed\n");
+               goto exit;
+       }
+
+       retval = konepure_init_specials(hdev);
+       if (retval) {
+               hid_err(hdev, "couldn't install mouse\n");
+               goto exit_stop;
+       }
+
+       return 0;
+
+exit_stop:
+       hid_hw_stop(hdev);
+exit:
+       return retval;
+}
+
+static void konepure_remove(struct hid_device *hdev)
+{
+       konepure_remove_specials(hdev);
+       hid_hw_stop(hdev);
+}
+
+static int konepure_raw_event(struct hid_device *hdev,
+               struct hid_report *report, u8 *data, int size)
+{
+       struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
+       struct konepure_device *konepure = hid_get_drvdata(hdev);
+
+       if (intf->cur_altsetting->desc.bInterfaceProtocol
+                       != USB_INTERFACE_PROTOCOL_MOUSE)
+               return 0;
+
+       if (data[0] != KONEPURE_MOUSE_REPORT_NUMBER_BUTTON)
+               return 0;
+
+       if (konepure != NULL && konepure->roccat_claimed)
+               roccat_report_event(konepure->chrdev_minor, data);
+
+       return 0;
+}
+
+static const struct hid_device_id konepure_devices[] = {
+       { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPURE) },
+       { }
+};
+
+MODULE_DEVICE_TABLE(hid, konepure_devices);
+
+static struct hid_driver konepure_driver = {
+               .name = "konepure",
+               .id_table = konepure_devices,
+               .probe = konepure_probe,
+               .remove = konepure_remove,
+               .raw_event = konepure_raw_event
+};
+
+static int __init konepure_init(void)
+{
+       int retval;
+
+       konepure_class = class_create(THIS_MODULE, "konepure");
+       if (IS_ERR(konepure_class))
+               return PTR_ERR(konepure_class);
+       konepure_class->dev_bin_attrs = konepure_bin_attributes;
+
+       retval = hid_register_driver(&konepure_driver);
+       if (retval)
+               class_destroy(konepure_class);
+       return retval;
+}
+
+static void __exit konepure_exit(void)
+{
+       hid_unregister_driver(&konepure_driver);
+       class_destroy(konepure_class);
+}
+
+module_init(konepure_init);
+module_exit(konepure_exit);
+
+MODULE_AUTHOR("Stefan Achatz");
+MODULE_DESCRIPTION("USB Roccat KonePure driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/hid/hid-roccat-konepure.h b/drivers/hid/hid-roccat-konepure.h
new file mode 100644 (file)
index 0000000..2cd24e9
--- /dev/null
@@ -0,0 +1,72 @@
+#ifndef __HID_ROCCAT_KONEPURE_H
+#define __HID_ROCCAT_KONEPURE_H
+
+/*
+ * Copyright (c) 2012 Stefan Achatz <erazor_de@users.sourceforge.net>
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#include <linux/types.h>
+
+enum {
+       KONEPURE_SIZE_ACTUAL_PROFILE = 0x03,
+       KONEPURE_SIZE_CONTROL = 0x03,
+       KONEPURE_SIZE_FIRMWARE_WRITE = 0x0402,
+       KONEPURE_SIZE_INFO = 0x06,
+       KONEPURE_SIZE_MACRO = 0x0822,
+       KONEPURE_SIZE_PROFILE_SETTINGS = 0x1f,
+       KONEPURE_SIZE_PROFILE_BUTTONS = 0x3b,
+       KONEPURE_SIZE_SENSOR = 0x06,
+       KONEPURE_SIZE_TALK = 0x10,
+       KONEPURE_SIZE_TCU = 0x04,
+       KONEPURE_SIZE_TCU_IMAGE = 0x0404,
+};
+
+enum konepure_control_requests {
+       KONEPURE_CONTROL_REQUEST_GENERAL = 0x80,
+       KONEPURE_CONTROL_REQUEST_BUTTONS = 0x90,
+};
+
+enum konepure_commands {
+       KONEPURE_COMMAND_CONTROL = 0x04,
+       KONEPURE_COMMAND_ACTUAL_PROFILE = 0x05,
+       KONEPURE_COMMAND_PROFILE_SETTINGS = 0x06,
+       KONEPURE_COMMAND_PROFILE_BUTTONS = 0x07,
+       KONEPURE_COMMAND_MACRO = 0x08,
+       KONEPURE_COMMAND_INFO = 0x09,
+       KONEPURE_COMMAND_TCU = 0x0c,
+       KONEPURE_COMMAND_TCU_IMAGE = 0x0c,
+       KONEPURE_COMMAND_E = 0x0e,
+       KONEPURE_COMMAND_SENSOR = 0x0f,
+       KONEPURE_COMMAND_TALK = 0x10,
+       KONEPURE_COMMAND_FIRMWARE_WRITE = 0x1b,
+       KONEPURE_COMMAND_FIRMWARE_WRITE_CONTROL = 0x1c,
+};
+
+enum {
+       KONEPURE_MOUSE_REPORT_NUMBER_BUTTON = 3,
+};
+
+struct konepure_mouse_report_button {
+       uint8_t report_number; /* always KONEPURE_MOUSE_REPORT_NUMBER_BUTTON */
+       uint8_t zero;
+       uint8_t type;
+       uint8_t data1;
+       uint8_t data2;
+       uint8_t zero2;
+       uint8_t unknown[2];
+} __packed;
+
+struct konepure_device {
+       int roccat_claimed;
+       int chrdev_minor;
+       struct mutex konepure_lock;
+};
+
+#endif
index d7437ef5c69516adff07654a9c7b0fc636fa44a5..b59b3df9ca95042b52870abac4b92d432e26a905 100644 (file)
@@ -242,7 +242,6 @@ static int roccat_release(struct inode *inode, struct file *file)
  * roccat_report_event() - output data to readers
  * @minor: minor device number returned by roccat_connect()
  * @data: pointer to data
- * @len: size of data
  *
  * Return value is zero on success, a negative error code on failure.
  *
@@ -290,6 +289,7 @@ EXPORT_SYMBOL_GPL(roccat_report_event);
  * @class: the class thats used to create the device. Meant to hold device
  * specific sysfs attributes.
  * @hid: the hid device the char device should be connected to.
+ * @report_size: size of reports
  *
  * Return value is minor device number in Range [0, ROCCAT_MAX_DEVICES] on
  * success, a negative error code on failure.
index 6679788bf75ac0b93126de3b7cac920289c618bb..ca74981073271effdddc72ba1f173acea27ebbf9 100644 (file)
@@ -18,8 +18,6 @@
  */
 #include <linux/device.h>
 #include <linux/hid.h>
-#include <linux/usb.h>
-#include "usbhid/usbhid.h"
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/mfd/core.h>
@@ -204,8 +202,8 @@ int sensor_hub_set_feature(struct hid_sensor_hub_device *hsdev, u32 report_id,
                goto done_proc;
        }
        hid_set_field(report->field[field_index], 0, value);
-       usbhid_submit_report(hsdev->hdev, report, USB_DIR_OUT);
-       usbhid_wait_io(hsdev->hdev);
+       hid_hw_request(hsdev->hdev, report, HID_REQ_SET_REPORT);
+       hid_hw_wait(hsdev->hdev);
 
 done_proc:
        mutex_unlock(&data->mutex);
@@ -227,8 +225,8 @@ int sensor_hub_get_feature(struct hid_sensor_hub_device *hsdev, u32 report_id,
                ret = -EINVAL;
                goto done_proc;
        }
-       usbhid_submit_report(hsdev->hdev, report, USB_DIR_IN);
-       usbhid_wait_io(hsdev->hdev);
+       hid_hw_request(hsdev->hdev, report, HID_REQ_GET_REPORT);
+       hid_hw_wait(hsdev->hdev);
        *value = report->field[field_index]->value[0];
 
 done_proc:
@@ -262,7 +260,7 @@ int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev,
                spin_unlock_irqrestore(&data->lock, flags);
                goto err_free;
        }
-       usbhid_submit_report(hsdev->hdev, report, USB_DIR_IN);
+       hid_hw_request(hsdev->hdev, report, HID_REQ_GET_REPORT);
        spin_unlock_irqrestore(&data->lock, flags);
        wait_for_completion_interruptible_timeout(&data->pending.ready, HZ*5);
        switch (data->pending.raw_size) {
index 28f774003f0381a97c58df8ab44ad11393a14d91..37845eccddb566e138ee503876a0a0351918b131 100644 (file)
 
 #include <linux/input.h>
 #include <linux/slab.h>
-#include <linux/usb.h>
 #include <linux/hid.h>
 #include <linux/module.h>
 #include "hid-ids.h"
 
 #ifdef CONFIG_SMARTJOYPLUS_FF
-#include "usbhid/usbhid.h"
 
 struct sjoyff_device {
        struct hid_report *report;
@@ -57,7 +55,7 @@ static int hid_sjoyff_play(struct input_dev *dev, void *data,
        sjoyff->report->field[0]->value[1] = right;
        sjoyff->report->field[0]->value[2] = left;
        dev_dbg(&dev->dev, "running with 0x%02x 0x%02x\n", left, right);
-       usbhid_submit_report(hid, sjoyff->report, USB_DIR_OUT);
+       hid_hw_request(hid, sjoyff->report, HID_REQ_SET_REPORT);
 
        return 0;
 }
@@ -115,7 +113,7 @@ static int sjoyff_init(struct hid_device *hid)
                sjoyff->report->field[0]->value[0] = 0x01;
                sjoyff->report->field[0]->value[1] = 0x00;
                sjoyff->report->field[0]->value[2] = 0x00;
-               usbhid_submit_report(hid, sjoyff->report, USB_DIR_OUT);
+               hid_hw_request(hid, sjoyff->report, HID_REQ_SET_REPORT);
        }
 
        hid_info(hid, "Force feedback for SmartJoy PLUS PS2/USB adapter\n");
index e94371a059cb3b65f53580d83f5dc40e51ee493c..a2f587d004e1e6afccadcd424a2ac5af202a74b6 100644 (file)
 #include <linux/device.h>
 #include <linux/hid.h>
 #include <linux/module.h>
-#include <linux/usb.h>
 
 #include "hid-ids.h"
-#include "usbhid/usbhid.h"
 
 static const struct hid_device_id speedlink_devices[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_X_TENSIONS, USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE)},
index 2ed995cda44a8763a11c4c5aba0e69277dfb1069..9b0efb0083feaf4a1f258226aad0426c7b961721 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/hid.h>
 #include <linux/module.h>
 
-#include "usbhid/usbhid.h"
 #include "hid-ids.h"
 
 #if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE)
@@ -132,7 +131,7 @@ static void steelseries_srws1_set_leds(struct hid_device *hdev, __u16 leds)
        value[14] = 0x00;
        value[15] = 0x00;
 
-       usbhid_submit_report(hdev, report, USB_DIR_OUT);
+       hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
 
        /* Note: LED change does not show on device until the device is read/polled */
 }
@@ -378,16 +377,5 @@ static struct hid_driver steelseries_srws1_driver = {
        .report_fixup = steelseries_srws1_report_fixup
 };
 
-static int __init steelseries_srws1_init(void)
-{
-       return hid_register_driver(&steelseries_srws1_driver);
-}
-
-static void __exit steelseries_srws1_exit(void)
-{
-       hid_unregister_driver(&steelseries_srws1_driver);
-}
-
-module_init(steelseries_srws1_init);
-module_exit(steelseries_srws1_exit);
+module_hid_driver(steelseries_srws1_driver);
 MODULE_LICENSE("GPL");
index 2055a52e9a20f4682866c65b972a6ad96afce8e8..99342cfa0ea2f82591831aaa21fcd9b4e11915c3 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/hid.h>
 #include <linux/leds.h>
 #include <linux/module.h>
-#include <linux/usb.h>
 
 #include "hid-ids.h"
 
index e4fcf3f702a519b95fdc9ca8ea73d1d80a777c42..b83376077d72282ac3373fe700e8d273d303fc1f 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/hid.h>
 #include <linux/input.h>
 #include <linux/slab.h>
-#include <linux/usb.h>
 #include <linux/module.h>
 
 #include "hid-ids.h"
@@ -46,7 +45,6 @@ static const signed short ff_joystick[] = {
 };
 
 #ifdef CONFIG_THRUSTMASTER_FF
-#include "usbhid/usbhid.h"
 
 /* Usages for thrustmaster devices I know about */
 #define THRUSTMASTER_USAGE_FF  (HID_UP_GENDESK | 0xbb)
@@ -103,7 +101,7 @@ static int tmff_play(struct input_dev *dev, void *data,
                dbg_hid("(x, y)=(%04x, %04x)\n", x, y);
                ff_field->value[0] = x;
                ff_field->value[1] = y;
-               usbhid_submit_report(hid, tmff->report, USB_DIR_OUT);
+               hid_hw_request(hid, tmff->report, HID_REQ_SET_REPORT);
                break;
 
        case FF_RUMBLE:
@@ -117,7 +115,7 @@ static int tmff_play(struct input_dev *dev, void *data,
                dbg_hid("(left,right)=(%08x, %08x)\n", left, right);
                ff_field->value[0] = left;
                ff_field->value[1] = right;
-               usbhid_submit_report(hid, tmff->report, USB_DIR_OUT);
+               hid_hw_request(hid, tmff->report, HID_REQ_SET_REPORT);
                break;
        }
        return 0;
index 0fb8ab93db68e275091a49462bd0bd40a356dded..e5ee1f20bbd9eea45ce3f585e88031e06c8ac1a8 100644 (file)
@@ -789,12 +789,20 @@ static void __ir_to_input(struct wiimote_data *wdata, const __u8 *ir,
        input_report_abs(wdata->ir, yid, y);
 }
 
-static void handler_status(struct wiimote_data *wdata, const __u8 *payload)
+/* reduced status report with "BB BB" key data only */
+static void handler_status_K(struct wiimote_data *wdata,
+                            const __u8 *payload)
 {
        handler_keys(wdata, payload);
 
        /* on status reports the drm is reset so we need to resend the drm */
        wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
+}
+
+/* extended status report with "BB BB LF 00 00 VV" data */
+static void handler_status(struct wiimote_data *wdata, const __u8 *payload)
+{
+       handler_status_K(wdata, payload);
 
        wiiext_event(wdata, payload[2] & 0x02);
 
@@ -804,6 +812,12 @@ static void handler_status(struct wiimote_data *wdata, const __u8 *payload)
        }
 }
 
+/* reduced generic report with "BB BB" key data only */
+static void handler_generic_K(struct wiimote_data *wdata, const __u8 *payload)
+{
+       handler_keys(wdata, payload);
+}
+
 static void handler_data(struct wiimote_data *wdata, const __u8 *payload)
 {
        __u16 offset = payload[3] << 8 | payload[4];
@@ -947,16 +961,26 @@ struct wiiproto_handler {
 
 static struct wiiproto_handler handlers[] = {
        { .id = WIIPROTO_REQ_STATUS, .size = 6, .func = handler_status },
+       { .id = WIIPROTO_REQ_STATUS, .size = 2, .func = handler_status_K },
        { .id = WIIPROTO_REQ_DATA, .size = 21, .func = handler_data },
+       { .id = WIIPROTO_REQ_DATA, .size = 2, .func = handler_generic_K },
        { .id = WIIPROTO_REQ_RETURN, .size = 4, .func = handler_return },
+       { .id = WIIPROTO_REQ_RETURN, .size = 2, .func = handler_generic_K },
        { .id = WIIPROTO_REQ_DRM_K, .size = 2, .func = handler_keys },
        { .id = WIIPROTO_REQ_DRM_KA, .size = 5, .func = handler_drm_KA },
+       { .id = WIIPROTO_REQ_DRM_KA, .size = 2, .func = handler_generic_K },
        { .id = WIIPROTO_REQ_DRM_KE, .size = 10, .func = handler_drm_KE },
+       { .id = WIIPROTO_REQ_DRM_KE, .size = 2, .func = handler_generic_K },
        { .id = WIIPROTO_REQ_DRM_KAI, .size = 17, .func = handler_drm_KAI },
+       { .id = WIIPROTO_REQ_DRM_KAI, .size = 2, .func = handler_generic_K },
        { .id = WIIPROTO_REQ_DRM_KEE, .size = 21, .func = handler_drm_KEE },
+       { .id = WIIPROTO_REQ_DRM_KEE, .size = 2, .func = handler_generic_K },
        { .id = WIIPROTO_REQ_DRM_KAE, .size = 21, .func = handler_drm_KAE },
+       { .id = WIIPROTO_REQ_DRM_KAE, .size = 2, .func = handler_generic_K },
        { .id = WIIPROTO_REQ_DRM_KIE, .size = 21, .func = handler_drm_KIE },
+       { .id = WIIPROTO_REQ_DRM_KIE, .size = 2, .func = handler_generic_K },
        { .id = WIIPROTO_REQ_DRM_KAIE, .size = 21, .func = handler_drm_KAIE },
+       { .id = WIIPROTO_REQ_DRM_KAIE, .size = 2, .func = handler_generic_K },
        { .id = WIIPROTO_REQ_DRM_E, .size = 21, .func = handler_drm_E },
        { .id = WIIPROTO_REQ_DRM_SKAI1, .size = 21, .func = handler_drm_SKAI1 },
        { .id = WIIPROTO_REQ_DRM_SKAI2, .size = 21, .func = handler_drm_SKAI2 },
@@ -970,7 +994,6 @@ static int wiimote_hid_event(struct hid_device *hdev, struct hid_report *report,
        struct wiiproto_handler *h;
        int i;
        unsigned long flags;
-       bool handled = false;
 
        if (size < 1)
                return -EINVAL;
@@ -981,11 +1004,11 @@ static int wiimote_hid_event(struct hid_device *hdev, struct hid_report *report,
                h = &handlers[i];
                if (h->id == raw_data[0] && h->size < size) {
                        h->func(wdata, &raw_data[1]);
-                       handled = true;
+                       break;
                }
        }
 
-       if (!handled)
+       if (!handlers[i].id)
                hid_warn(hdev, "Unhandled report %hhu size %d\n", raw_data[0],
                                                                        size);
 
@@ -1160,6 +1183,7 @@ static void wiimote_destroy(struct wiimote_data *wdata)
        wiimote_leds_destroy(wdata);
 
        power_supply_unregister(&wdata->battery);
+       kfree(wdata->battery.name);
        input_unregister_device(wdata->accel);
        input_unregister_device(wdata->ir);
        input_unregister_device(wdata->input);
@@ -1216,9 +1240,14 @@ static int wiimote_hid_probe(struct hid_device *hdev,
        wdata->battery.properties = wiimote_battery_props;
        wdata->battery.num_properties = ARRAY_SIZE(wiimote_battery_props);
        wdata->battery.get_property = wiimote_battery_get_property;
-       wdata->battery.name = "wiimote_battery";
        wdata->battery.type = POWER_SUPPLY_TYPE_BATTERY;
        wdata->battery.use_for_apm = 0;
+       wdata->battery.name = kasprintf(GFP_KERNEL, "wiimote_battery_%s",
+                                       wdata->hdev->uniq);
+       if (!wdata->battery.name) {
+               ret = -ENOMEM;
+               goto err_battery_name;
+       }
 
        ret = power_supply_register(&wdata->hdev->dev, &wdata->battery);
        if (ret) {
@@ -1254,6 +1283,8 @@ err_free:
        return ret;
 
 err_battery:
+       kfree(wdata->battery.name);
+err_battery_name:
        input_unregister_device(wdata->input);
        wdata->input = NULL;
 err_input:
@@ -1283,6 +1314,8 @@ static void wiimote_hid_remove(struct hid_device *hdev)
 static const struct hid_device_id wiimote_hid_devices[] = {
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO,
                                USB_DEVICE_ID_NINTENDO_WIIMOTE) },
+       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO,
+                               USB_DEVICE_ID_NINTENDO_WIIMOTE2) },
        { }
 };
 MODULE_DEVICE_TABLE(hid, wiimote_hid_devices);
index af66452592e963c8a5e91f17921e166e50699800..6ec28a37c146ab58d623ef1ccaafc38b3dcd9477 100644 (file)
 #include <linux/hid.h>
 #include <linux/input.h>
 #include <linux/slab.h>
-#include <linux/usb.h>
 #include <linux/module.h>
 
 #include "hid-ids.h"
 
 #ifdef CONFIG_ZEROPLUS_FF
-#include "usbhid/usbhid.h"
 
 struct zpff_device {
        struct hid_report *report;
@@ -59,7 +57,7 @@ static int zpff_play(struct input_dev *dev, void *data,
        zpff->report->field[2]->value[0] = left;
        zpff->report->field[3]->value[0] = right;
        dbg_hid("running with 0x%02x 0x%02x\n", left, right);
-       usbhid_submit_report(hid, zpff->report, USB_DIR_OUT);
+       hid_hw_request(hid, zpff->report, HID_REQ_SET_REPORT);
 
        return 0;
 }
@@ -104,7 +102,7 @@ static int zpff_init(struct hid_device *hid)
        zpff->report->field[1]->value[0] = 0x02;
        zpff->report->field[2]->value[0] = 0x00;
        zpff->report->field[3]->value[0] = 0x00;
-       usbhid_submit_report(hid, zpff->report, USB_DIR_OUT);
+       hid_hw_request(hid, zpff->report, HID_REQ_SET_REPORT);
 
        hid_info(hid, "force feedback for Zeroplus based devices by Anssi Hannula <anssi.hannula@gmail.com>\n");
 
index ec7930217a6dff1fceb15b1a445ec0462cb47b82..2b1799a3b212d73e1bc9100be6092923a4bc8cb2 100644 (file)
@@ -563,6 +563,36 @@ static int i2c_hid_output_raw_report(struct hid_device *hid, __u8 *buf,
        return ret;
 }
 
+static void i2c_hid_request(struct hid_device *hid, struct hid_report *rep,
+               int reqtype)
+{
+       struct i2c_client *client = hid->driver_data;
+       char *buf;
+       int ret;
+       int len = i2c_hid_get_report_length(rep) - 2;
+
+       buf = kzalloc(len, GFP_KERNEL);
+       if (!buf)
+               return;
+
+       switch (reqtype) {
+       case HID_REQ_GET_REPORT:
+               ret = i2c_hid_get_raw_report(hid, rep->id, buf, len, rep->type);
+               if (ret < 0)
+                       dev_err(&client->dev, "%s: unable to get report: %d\n",
+                               __func__, ret);
+               else
+                       hid_input_report(hid, rep->type, buf, ret, 0);
+               break;
+       case HID_REQ_SET_REPORT:
+               hid_output_report(rep, buf);
+               i2c_hid_output_raw_report(hid, buf, len, rep->type);
+               break;
+       }
+
+       kfree(buf);
+}
+
 static int i2c_hid_parse(struct hid_device *hid)
 {
        struct i2c_client *client = hid->driver_data;
@@ -742,6 +772,7 @@ static struct hid_ll_driver i2c_hid_ll_driver = {
        .open = i2c_hid_open,
        .close = i2c_hid_close,
        .power = i2c_hid_power,
+       .request = i2c_hid_request,
        .hidinput_input_event = i2c_hid_hidinput_input_event,
 };
 
index 1f9e56bfeaa0499ee9522aa0813e5da43f36164a..99418285222cf118cbc09e4d9029c80ba3493fcf 100644 (file)
@@ -639,7 +639,7 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re
        }
 }
 
-void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir)
+static void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir)
 {
        struct usbhid_device *usbhid = hid->driver_data;
        unsigned long flags;
@@ -648,7 +648,6 @@ void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, uns
        __usbhid_submit_report(hid, report, dir);
        spin_unlock_irqrestore(&usbhid->lock, flags);
 }
-EXPORT_SYMBOL_GPL(usbhid_submit_report);
 
 /* Workqueue routine to send requests to change LEDs */
 static void hid_led(struct work_struct *work)
@@ -706,7 +705,7 @@ static int usb_hidinput_input_event(struct input_dev *dev, unsigned int type, un
        return 0;
 }
 
-int usbhid_wait_io(struct hid_device *hid)
+static int usbhid_wait_io(struct hid_device *hid)
 {
        struct usbhid_device *usbhid = hid->driver_data;
 
@@ -720,7 +719,6 @@ int usbhid_wait_io(struct hid_device *hid)
 
        return 0;
 }
-EXPORT_SYMBOL_GPL(usbhid_wait_io);
 
 static int hid_set_idle(struct usb_device *dev, int ifnum, int report, int idle)
 {
@@ -1243,6 +1241,32 @@ static int usbhid_power(struct hid_device *hid, int lvl)
        return r;
 }
 
+static void usbhid_request(struct hid_device *hid, struct hid_report *rep, int reqtype)
+{
+       switch (reqtype) {
+       case HID_REQ_GET_REPORT:
+               usbhid_submit_report(hid, rep, USB_DIR_IN);
+               break;
+       case HID_REQ_SET_REPORT:
+               usbhid_submit_report(hid, rep, USB_DIR_OUT);
+               break;
+       }
+}
+
+static int usbhid_idle(struct hid_device *hid, int report, int idle,
+               int reqtype)
+{
+       struct usb_device *dev = hid_to_usb_dev(hid);
+       struct usb_interface *intf = to_usb_interface(hid->dev.parent);
+       struct usb_host_interface *interface = intf->cur_altsetting;
+       int ifnum = interface->desc.bInterfaceNumber;
+
+       if (reqtype != HID_REQ_SET_IDLE)
+               return -EINVAL;
+
+       return hid_set_idle(dev, ifnum, report, idle);
+}
+
 static struct hid_ll_driver usb_hid_driver = {
        .parse = usbhid_parse,
        .start = usbhid_start,
@@ -1251,6 +1275,9 @@ static struct hid_ll_driver usb_hid_driver = {
        .close = usbhid_close,
        .power = usbhid_power,
        .hidinput_input_event = usb_hidinput_input_event,
+       .request = usbhid_request,
+       .wait = usbhid_wait_io,
+       .idle = usbhid_idle,
 };
 
 static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id *id)
index f91c136821f7097e05cd761ed9f554a56fabcfed..10b6167027802abbc289466c00a74b6281e2b5f3 100644 (file)
@@ -263,8 +263,8 @@ static void pidff_set_envelope_report(struct pidff_device *pidff,
                envelope->attack_level,
                pidff->set_envelope[PID_ATTACK_LEVEL].value[0]);
 
-       usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_ENVELOPE],
-                         USB_DIR_OUT);
+       hid_hw_request(pidff->hid, pidff->reports[PID_SET_ENVELOPE],
+                       HID_REQ_SET_REPORT);
 }
 
 /*
@@ -290,8 +290,8 @@ static void pidff_set_constant_force_report(struct pidff_device *pidff,
        pidff_set_signed(&pidff->set_constant[PID_MAGNITUDE],
                         effect->u.constant.level);
 
-       usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_CONSTANT],
-                         USB_DIR_OUT);
+       hid_hw_request(pidff->hid, pidff->reports[PID_SET_CONSTANT],
+                       HID_REQ_SET_REPORT);
 }
 
 /*
@@ -325,8 +325,8 @@ static void pidff_set_effect_report(struct pidff_device *pidff,
                                pidff->effect_direction);
        pidff->set_effect[PID_START_DELAY].value[0] = effect->replay.delay;
 
-       usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT],
-                         USB_DIR_OUT);
+       hid_hw_request(pidff->hid, pidff->reports[PID_SET_EFFECT],
+                       HID_REQ_SET_REPORT);
 }
 
 /*
@@ -357,8 +357,8 @@ static void pidff_set_periodic_report(struct pidff_device *pidff,
        pidff_set(&pidff->set_periodic[PID_PHASE], effect->u.periodic.phase);
        pidff->set_periodic[PID_PERIOD].value[0] = effect->u.periodic.period;
 
-       usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_PERIODIC],
-                         USB_DIR_OUT);
+       hid_hw_request(pidff->hid, pidff->reports[PID_SET_PERIODIC],
+                       HID_REQ_SET_REPORT);
 
 }
 
@@ -399,8 +399,8 @@ static void pidff_set_condition_report(struct pidff_device *pidff,
                          effect->u.condition[i].left_saturation);
                pidff_set(&pidff->set_condition[PID_DEAD_BAND],
                          effect->u.condition[i].deadband);
-               usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_CONDITION],
-                                 USB_DIR_OUT);
+               hid_hw_request(pidff->hid, pidff->reports[PID_SET_CONDITION],
+                               HID_REQ_SET_REPORT);
        }
 }
 
@@ -440,8 +440,8 @@ static void pidff_set_ramp_force_report(struct pidff_device *pidff,
                         effect->u.ramp.start_level);
        pidff_set_signed(&pidff->set_ramp[PID_RAMP_END],
                         effect->u.ramp.end_level);
-       usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_RAMP],
-                         USB_DIR_OUT);
+       hid_hw_request(pidff->hid, pidff->reports[PID_SET_RAMP],
+                       HID_REQ_SET_REPORT);
 }
 
 /*
@@ -465,19 +465,19 @@ static int pidff_request_effect_upload(struct pidff_device *pidff, int efnum)
        int j;
 
        pidff->create_new_effect_type->value[0] = efnum;
-       usbhid_submit_report(pidff->hid, pidff->reports[PID_CREATE_NEW_EFFECT],
-                         USB_DIR_OUT);
+       hid_hw_request(pidff->hid, pidff->reports[PID_CREATE_NEW_EFFECT],
+                       HID_REQ_SET_REPORT);
        hid_dbg(pidff->hid, "create_new_effect sent, type: %d\n", efnum);
 
        pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0] = 0;
        pidff->block_load_status->value[0] = 0;
-       usbhid_wait_io(pidff->hid);
+       hid_hw_wait(pidff->hid);
 
        for (j = 0; j < 60; j++) {
                hid_dbg(pidff->hid, "pid_block_load requested\n");
-               usbhid_submit_report(pidff->hid, pidff->reports[PID_BLOCK_LOAD],
-                                 USB_DIR_IN);
-               usbhid_wait_io(pidff->hid);
+               hid_hw_request(pidff->hid, pidff->reports[PID_BLOCK_LOAD],
+                               HID_REQ_GET_REPORT);
+               hid_hw_wait(pidff->hid);
                if (pidff->block_load_status->value[0] ==
                    pidff->status_id[PID_BLOCK_LOAD_SUCCESS]) {
                        hid_dbg(pidff->hid, "device reported free memory: %d bytes\n",
@@ -513,8 +513,8 @@ static void pidff_playback_pid(struct pidff_device *pidff, int pid_id, int n)
                pidff->effect_operation[PID_LOOP_COUNT].value[0] = n;
        }
 
-       usbhid_submit_report(pidff->hid, pidff->reports[PID_EFFECT_OPERATION],
-                         USB_DIR_OUT);
+       hid_hw_request(pidff->hid, pidff->reports[PID_EFFECT_OPERATION],
+                       HID_REQ_SET_REPORT);
 }
 
 /**
@@ -535,8 +535,8 @@ static int pidff_playback(struct input_dev *dev, int effect_id, int value)
 static void pidff_erase_pid(struct pidff_device *pidff, int pid_id)
 {
        pidff->block_free[PID_EFFECT_BLOCK_INDEX].value[0] = pid_id;
-       usbhid_submit_report(pidff->hid, pidff->reports[PID_BLOCK_FREE],
-                         USB_DIR_OUT);
+       hid_hw_request(pidff->hid, pidff->reports[PID_BLOCK_FREE],
+                       HID_REQ_SET_REPORT);
 }
 
 /*
@@ -551,7 +551,7 @@ static int pidff_erase_effect(struct input_dev *dev, int effect_id)
                effect_id, pidff->pid_id[effect_id]);
        /* Wait for the queue to clear. We do not want a full fifo to
           prevent the effect removal. */
-       usbhid_wait_io(pidff->hid);
+       hid_hw_wait(pidff->hid);
        pidff_playback_pid(pidff, pid_id, 0);
        pidff_erase_pid(pidff, pid_id);
 
@@ -718,8 +718,8 @@ static void pidff_set_gain(struct input_dev *dev, u16 gain)
        struct pidff_device *pidff = dev->ff->private;
 
        pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], gain);
-       usbhid_submit_report(pidff->hid, pidff->reports[PID_DEVICE_GAIN],
-                         USB_DIR_OUT);
+       hid_hw_request(pidff->hid, pidff->reports[PID_DEVICE_GAIN],
+                       HID_REQ_SET_REPORT);
 }
 
 static void pidff_autocenter(struct pidff_device *pidff, u16 magnitude)
@@ -744,8 +744,8 @@ static void pidff_autocenter(struct pidff_device *pidff, u16 magnitude)
        pidff->set_effect[PID_DIRECTION_ENABLE].value[0] = 1;
        pidff->set_effect[PID_START_DELAY].value[0] = 0;
 
-       usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT],
-                         USB_DIR_OUT);
+       hid_hw_request(pidff->hid, pidff->reports[PID_SET_EFFECT],
+                       HID_REQ_SET_REPORT);
 }
 
 /*
@@ -1158,19 +1158,19 @@ static void pidff_reset(struct pidff_device *pidff)
 
        pidff->device_control->value[0] = pidff->control_id[PID_RESET];
        /* We reset twice as sometimes hid_wait_io isn't waiting long enough */
-       usbhid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT);
-       usbhid_wait_io(hid);
-       usbhid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT);
-       usbhid_wait_io(hid);
+       hid_hw_request(hid, pidff->reports[PID_DEVICE_CONTROL], HID_REQ_SET_REPORT);
+       hid_hw_wait(hid);
+       hid_hw_request(hid, pidff->reports[PID_DEVICE_CONTROL], HID_REQ_SET_REPORT);
+       hid_hw_wait(hid);
 
        pidff->device_control->value[0] =
                pidff->control_id[PID_ENABLE_ACTUATORS];
-       usbhid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT);
-       usbhid_wait_io(hid);
+       hid_hw_request(hid, pidff->reports[PID_DEVICE_CONTROL], HID_REQ_SET_REPORT);
+       hid_hw_wait(hid);
 
        /* pool report is sometimes messed up, refetch it */
-       usbhid_submit_report(hid, pidff->reports[PID_POOL], USB_DIR_IN);
-       usbhid_wait_io(hid);
+       hid_hw_request(hid, pidff->reports[PID_POOL], HID_REQ_GET_REPORT);
+       hid_hw_wait(hid);
 
        if (pidff->pool[PID_SIMULTANEOUS_MAX].value) {
                while (pidff->pool[PID_SIMULTANEOUS_MAX].value[0] < 2) {
@@ -1181,9 +1181,9 @@ static void pidff_reset(struct pidff_device *pidff)
                                break;
                        }
                        hid_dbg(pidff->hid, "pid_pool requested again\n");
-                       usbhid_submit_report(hid, pidff->reports[PID_POOL],
-                                         USB_DIR_IN);
-                       usbhid_wait_io(hid);
+                       hid_hw_request(hid, pidff->reports[PID_POOL],
+                                         HID_REQ_GET_REPORT);
+                       hid_hw_wait(hid);
                }
        }
 }
@@ -1269,8 +1269,8 @@ int hid_pidff_init(struct hid_device *hid)
 
        if (test_bit(FF_GAIN, dev->ffbit)) {
                pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], 0xffff);
-               usbhid_submit_report(hid, pidff->reports[PID_DEVICE_GAIN],
-                                    USB_DIR_OUT);
+               hid_hw_request(hid, pidff->reports[PID_DEVICE_GAIN],
+                                    HID_REQ_SET_REPORT);
        }
 
        error = pidff_check_autocenter(pidff, dev);
index 87bd64959a91b4bed5e3745751e237f78ac4470a..2f1ddca6f2e0a3a4712bce434d5b29e1556e216c 100644 (file)
@@ -705,8 +705,8 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                if (report == NULL)
                        break;
 
-               usbhid_submit_report(hid, report, USB_DIR_IN);
-               usbhid_wait_io(hid);
+               hid_hw_request(hid, report, HID_REQ_GET_REPORT);
+               hid_hw_wait(hid);
 
                r = 0;
                break;
@@ -724,8 +724,8 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                if (report == NULL)
                        break;
 
-               usbhid_submit_report(hid, report, USB_DIR_OUT);
-               usbhid_wait_io(hid);
+               hid_hw_request(hid, report, HID_REQ_SET_REPORT);
+               hid_hw_wait(hid);
 
                r = 0;
                break;
index bd87a61e53037dd63c63aff48a277ff172cd964c..dbb6af6991350d4e09b2c7ca484411065afdc75c 100644 (file)
 #include <linux/input.h>
 
 /*  API provided by hid-core.c for USB HID drivers */
-int usbhid_wait_io(struct hid_device* hid);
 void usbhid_close(struct hid_device *hid);
 int usbhid_open(struct hid_device *hid);
 void usbhid_init_reports(struct hid_device *hid);
-void usbhid_submit_report
-(struct hid_device *hid, struct hid_report *report, unsigned char dir);
 int usbhid_get_power(struct hid_device *hid);
 void usbhid_put_power(struct hid_device *hid);
 struct usb_interface *usbhid_find_interface(int minor);
index 53744fa1c8b7af4aac65c057a09518a5fec70f05..8663f216c563e9023df067c83ec9b6e5fbcbe02b 100644 (file)
  *
  */
 
-#define HID_DEBUG_BUFSIZE 512
-
 #ifdef CONFIG_DEBUG_FS
 
+#define HID_DEBUG_BUFSIZE 512
+
 void hid_dump_input(struct hid_device *, struct hid_usage *, __s32);
+void hid_dump_report(struct hid_device *, int , u8 *, int);
 void hid_dump_device(struct hid_device *, struct seq_file *);
 void hid_dump_field(struct hid_field *, int, struct seq_file *);
 char *hid_resolv_usage(unsigned, struct seq_file *);
@@ -50,6 +51,7 @@ struct hid_debug_list {
 #else
 
 #define hid_dump_input(a,b,c)          do { } while (0)
+#define hid_dump_report(a,b,c,d)       do { } while (0)
 #define hid_dump_device(a,b)           do { } while (0)
 #define hid_dump_field(a,b,c)          do { } while (0)
 #define hid_resolv_usage(a,b)          do { } while (0)
index e14b465b11463d353553027e602d79499d8be01d..af1b86d46f6e714e4feb5aeab303fb76f47a1234 100644 (file)
@@ -282,6 +282,7 @@ struct hid_item {
 #define HID_QUIRK_BADPAD                       0x00000020
 #define HID_QUIRK_MULTI_INPUT                  0x00000040
 #define HID_QUIRK_HIDINPUT_FORCE               0x00000080
+#define HID_QUIRK_NO_EMPTY_INPUT               0x00000100
 #define HID_QUIRK_SKIP_OUTPUT_REPORTS          0x00010000
 #define HID_QUIRK_FULLSPEED_INTERVAL           0x10000000
 #define HID_QUIRK_NO_INIT_REPORTS              0x20000000
@@ -456,7 +457,8 @@ struct hid_device {                                                 /* device report descriptor */
        unsigned country;                                               /* HID country */
        struct hid_report_enum report_enum[HID_REPORT_TYPES];
 
-       struct semaphore driver_lock;                                   /* protects the current driver */
+       struct semaphore driver_lock;                                   /* protects the current driver, except during input */
+       struct semaphore driver_input_lock;                             /* protects the current driver */
        struct device dev;                                              /* device */
        struct hid_driver *driver;
        struct hid_ll_driver *ll_driver;
@@ -477,6 +479,7 @@ struct hid_device {                                                 /* device report descriptor */
        unsigned int status;                                            /* see STAT flags above */
        unsigned claimed;                                               /* Claimed by hidinput, hiddev? */
        unsigned quirks;                                                /* Various quirks the device can pull on us */
+       bool io_started;                                                /* Protected by driver_lock. If IO has started */
 
        struct list_head inputs;                                        /* The list of inputs */
        void *hiddev;                                                   /* The hiddev structure */
@@ -512,6 +515,7 @@ struct hid_device {                                                 /* device report descriptor */
        struct dentry *debug_rdesc;
        struct dentry *debug_events;
        struct list_head debug_list;
+       struct mutex debug_list_lock;
        wait_queue_head_t debug_wait;
 };
 
@@ -599,6 +603,10 @@ struct hid_usage_id {
  * @resume: invoked on resume if device was not reset (NULL means nop)
  * @reset_resume: invoked on resume if device was reset (NULL means nop)
  *
+ * probe should return -errno on error, or 0 on success. During probe,
+ * input will not be passed to raw_event unless hid_device_io_start is
+ * called.
+ *
  * raw_event and event should return 0 on no action performed, 1 when no
  * further processing should be done and negative on error
  *
@@ -662,6 +670,9 @@ struct hid_driver {
  * @hidinput_input_event: event input event (e.g. ff or leds)
  * @parse: this method is called only once to parse the device data,
  *        shouldn't allocate anything to not leak memory
+ * @request: send report request to device (e.g. feature report)
+ * @wait: wait for buffered io to complete (send/recv reports)
+ * @idle: send idle request to device
  */
 struct hid_ll_driver {
        int (*start)(struct hid_device *hdev);
@@ -676,6 +687,13 @@ struct hid_ll_driver {
                        unsigned int code, int value);
 
        int (*parse)(struct hid_device *hdev);
+
+       void (*request)(struct hid_device *hdev,
+                       struct hid_report *report, int reqtype);
+
+       int (*wait)(struct hid_device *hdev);
+       int (*idle)(struct hid_device *hdev, int report, int idle, int reqtype);
+
 };
 
 #define        PM_HINT_FULLON  1<<5
@@ -737,6 +755,44 @@ const struct hid_device_id *hid_match_id(struct hid_device *hdev,
                                         const struct hid_device_id *id);
 s32 hid_snto32(__u32 value, unsigned n);
 
+/**
+ * hid_device_io_start - enable HID input during probe, remove
+ *
+ * @hid - the device
+ *
+ * This should only be called during probe or remove and only be
+ * called by the thread calling probe or remove. It will allow
+ * incoming packets to be delivered to the driver.
+ */
+static inline void hid_device_io_start(struct hid_device *hid) {
+       if (hid->io_started) {
+               dev_warn(&hid->dev, "io already started");
+               return;
+       }
+       hid->io_started = true;
+       up(&hid->driver_input_lock);
+}
+
+/**
+ * hid_device_io_stop - disable HID input during probe, remove
+ *
+ * @hid - the device
+ *
+ * Should only be called after hid_device_io_start. It will prevent
+ * incoming packets from going to the driver for the duration of
+ * probe, remove. If called during probe, packets will still go to the
+ * driver after probe is complete. This function should only be called
+ * by the thread calling probe or remove.
+ */
+static inline void hid_device_io_stop(struct hid_device *hid) {
+       if (!hid->io_started) {
+               dev_warn(&hid->dev, "io already stopped");
+               return;
+       }
+       hid->io_started = false;
+       down(&hid->driver_input_lock);
+}
+
 /**
  * hid_map_usage - map usage input bits
  *
@@ -883,6 +939,49 @@ static inline int hid_hw_power(struct hid_device *hdev, int level)
        return hdev->ll_driver->power ? hdev->ll_driver->power(hdev, level) : 0;
 }
 
+
+/**
+ * hid_hw_request - send report request to device
+ *
+ * @hdev: hid device
+ * @report: report to send
+ * @reqtype: hid request type
+ */
+static inline void hid_hw_request(struct hid_device *hdev,
+                                 struct hid_report *report, int reqtype)
+{
+       if (hdev->ll_driver->request)
+               hdev->ll_driver->request(hdev, report, reqtype);
+}
+
+/**
+ * hid_hw_idle - send idle request to device
+ *
+ * @hdev: hid device
+ * @report: report to control
+ * @idle: idle state
+ * @reqtype: hid request type
+ */
+static inline int hid_hw_idle(struct hid_device *hdev, int report, int idle,
+               int reqtype)
+{
+       if (hdev->ll_driver->idle)
+               return hdev->ll_driver->idle(hdev, report, idle, reqtype);
+
+       return 0;
+}
+
+/**
+ * hid_hw_wait - wait for buffered io to complete
+ *
+ * @hdev: hid device
+ */
+static inline void hid_hw_wait(struct hid_device *hdev)
+{
+       if (hdev->ll_driver->wait)
+               hdev->ll_driver->wait(hdev);
+}
+
 int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
                int interrupt);
 
index 816e2dcda7ca9d244a5e4321aa477267bb07a46f..512a7e50bcae19dd3d7dc40edb3741198f0512ac 100644 (file)
 /*
  * Ugly hack to work around failing compilation on systems that don't
  * yet populate new version of hidraw.h to userspace.
- *
- * If you need this, please have your distro update the kernel headers.
  */
 #ifndef HIDIOCSFEATURE
+#warning Please have your distro update the userspace kernel headers
 #define HIDIOCSFEATURE(len)    _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x06, len)
 #define HIDIOCGFEATURE(len)    _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x07, len)
 #endif