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 ...
Unified · Split
| @@ -101,7 +101,8 @@ Date: June 2011 · 100 unmodified lines | ||
| 101 | 101 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> |
| 102 | 102 | Description: When written, this file lets one set the backlight intensity for |
| 103 | 103 | a specific profile. Profile number is included in written data. |
| 104 | − The data has to be 10 bytes long. | |
| 104 | + The data has to be 10 bytes long for Isku, IskuFX needs 16 bytes | |
| 105 | + of data. | |
| 105 | 106 | Before reading this file, control has to be written to select |
| 106 | 107 | which profile to read. |
| 107 | 108 | Users: http://roccat.sourceforge.net |
| @@ -141,3 +142,12 @@ Description: When written, this file lets one trigger easyshift functionality · 33 unmodified lines | ||
| 141 | 142 | The data has to be 16 bytes long. |
| 142 | 143 | This file is writeonly. |
| 143 | 144 | Users: http://roccat.sourceforge.net |
| 145 | + | |
| 146 | +What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/isku/roccatisku<minor>/talkfx | |
| 147 | +Date: February 2013 | |
| 148 | +Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | |
| 149 | +Description: When written, this file lets one trigger temporary color schemes | |
| 150 | + from the host. | |
| 151 | + The data has to be 16 bytes long. | |
| 152 | + This file is writeonly. | |
| 153 | +Users: http://roccat.sourceforge.net | |
| @@ -0,0 +1,105 @@ | ||
| 1 | +What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/konepure/roccatkonepure<minor>/actual_profile | |
| 2 | +Date: December 2012 | |
| 3 | +Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | |
| 4 | +Description: The mouse can store 5 profiles which can be switched by the | |
| 5 | + press of a button. actual_profile holds number of actual profile. | |
| 6 | + This value is persistent, so its value determines the profile | |
| 7 | + that's active when the mouse is powered on next time. | |
| 8 | + When written, the mouse activates the set profile immediately. | |
| 9 | + The data has to be 3 bytes long. | |
| 10 | + The mouse will reject invalid data. | |
| 11 | +Users: http://roccat.sourceforge.net | |
| 12 | + | |
| 13 | +What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/konepure/roccatkonepure<minor>/control | |
| 14 | +Date: December 2012 | |
| 15 | +Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | |
| 16 | +Description: When written, this file lets one select which data from which | |
| 17 | + profile will be read next. The data has to be 3 bytes long. | |
| 18 | + This file is writeonly. | |
| 19 | +Users: http://roccat.sourceforge.net | |
| 20 | + | |
| 21 | +What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/konepure/roccatkonepure<minor>/info | |
| 22 | +Date: December 2012 | |
| 23 | +Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | |
| 24 | +Description: When read, this file returns general data like firmware version. | |
| 25 | + When written, the device can be reset. | |
| 26 | + The data is 6 bytes long. | |
| 27 | +Users: http://roccat.sourceforge.net | |
| 28 | + | |
| 29 | +What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/konepure/roccatkonepure<minor>/macro | |
| 30 | +Date: December 2012 | |
| 31 | +Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | |
| 32 | +Description: The mouse can store a macro with max 500 key/button strokes | |
| 33 | + internally. | |
| 34 | + When written, this file lets one set the sequence for a specific | |
| 35 | + button for a specific profile. Button and profile numbers are | |
| 36 | + included in written data. The data has to be 2082 bytes long. | |
| 37 | + This file is writeonly. | |
| 38 | +Users: http://roccat.sourceforge.net | |
| 39 | + | |
| 40 | +What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/konepure/roccatkonepure<minor>/profile_buttons | |
| 41 | +Date: December 2012 | |
| 42 | +Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | |
| 43 | +Description: The mouse can store 5 profiles which can be switched by the | |
| 44 | + press of a button. A profile is split in settings and buttons. | |
| 45 | + profile_buttons holds information about button layout. | |
| 46 | + When written, this file lets one write the respective profile | |
| 47 | + buttons back to the mouse. The data has to be 59 bytes long. | |
| 48 | + The mouse will reject invalid data. | |
| 49 | + Which profile to write is determined by the profile number | |
| 50 | + contained in the data. | |
| 51 | + Before reading this file, control has to be written to select | |
| 52 | + which profile to read. | |
| 53 | +Users: http://roccat.sourceforge.net | |
| 54 | + | |
| 55 | +What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/konepure/roccatkonepure<minor>/profile_settings | |
| 56 | +Date: December 2012 | |
| 57 | +Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | |
| 58 | +Description: The mouse can store 5 profiles which can be switched by the | |
| 59 | + press of a button. A profile is split in settings and buttons. | |
| 60 | + profile_settings holds information like resolution, sensitivity | |
| 61 | + and light effects. | |
| 62 | + When written, this file lets one write the respective profile | |
| 63 | + settings back to the mouse. The data has to be 31 bytes long. | |
| 64 | + The mouse will reject invalid data. | |
| 65 | + Which profile to write is determined by the profile number | |
| 66 | + contained in the data. | |
| 67 | + Before reading this file, control has to be written to select | |
| 68 | + which profile to read. | |
| 69 | +Users: http://roccat.sourceforge.net | |
| 70 | + | |
| 71 | +What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/konepure/roccatkonepure<minor>/sensor | |
| 72 | +Date: December 2012 | |
| 73 | +Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | |
| 74 | +Description: The mouse has a tracking- and a distance-control-unit. These | |
| 75 | + can be activated/deactivated and the lift-off distance can be | |
| 76 | + set. The data has to be 6 bytes long. | |
| 77 | + This file is writeonly. | |
| 78 | +Users: http://roccat.sourceforge.net | |
| 79 | + | |
| 80 | +What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/konepure/roccatkonepure<minor>/talk | |
| 81 | +Date: December 2012 | |
| 82 | +Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | |
| 83 | +Description: Used to active some easy* functions of the mouse from outside. | |
| 84 | + The data has to be 16 bytes long. | |
| 85 | + This file is writeonly. | |
| 86 | +Users: http://roccat.sourceforge.net | |
| 87 | + | |
| 88 | +What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/konepure/roccatkonepure<minor>/tcu | |
| 89 | +Date: December 2012 | |
| 90 | +Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | |
| 91 | +Description: When written a calibration process for the tracking control unit | |
| 92 | + can be initiated/cancelled. Also lets one read/write sensor | |
| 93 | + registers. | |
| 94 | + The data has to be 4 bytes long. | |
| 95 | +Users: http://roccat.sourceforge.net | |
| 96 | + | |
| 97 | +What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/konepure/roccatkonepure<minor>/tcu_image | |
| 98 | +Date: December 2012 | |
| 99 | +Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | |
| 100 | +Description: When read the mouse returns a 30x30 pixel image of the | |
| 101 | + sampled underground. This works only in the course of a | |
| 102 | + calibration process initiated with tcu. | |
| 103 | + The returned data is 1028 bytes in size. | |
| 104 | + This file is readonly. | |
| 105 | +Users: http://roccat.sourceforge.net | |
| @@ -92,14 +92,14 @@ menu "Special HID drivers" · 91 unmodified lines | ||
| 92 | 92 | |
| 93 | 93 | config HID_A4TECH |
| 94 | 94 | tristate "A4 tech mice" if EXPERT |
| 95 | − depends on USB_HID | |
| 95 | + depends on HID | |
| 96 | 96 | default !EXPERT |
| 97 | 97 | ---help--- |
| 98 | 98 | Support for A4 tech X5 and WOP-35 / Trust 450L mice. |
| 99 | 99 | |
| 100 | 100 | config HID_ACRUX |
| 101 | 101 | tristate "ACRUX game controller support" |
| 102 | − depends on USB_HID | |
| 102 | + depends on HID | |
| 103 | 103 | ---help--- |
| 104 | 104 | Say Y here if you want to enable support for ACRUX game controllers. |
| 105 | 105 | |
| @@ -113,7 +113,7 @@ config HID_ACRUX_FF · 7 unmodified lines | ||
| 113 | 113 | |
| 114 | 114 | config HID_APPLE |
| 115 | 115 | tristate "Apple {i,Power,Mac}Books" if EXPERT |
| 116 | − depends on (USB_HID || BT_HIDP) | |
| 116 | + depends on HID | |
| 117 | 117 | default !EXPERT |
| 118 | 118 | ---help--- |
| 119 | 119 | Support for some Apple devices which less or more break |
| @@ -122,36 +122,47 @@ config HID_APPLE · 2 unmodified lines | ||
| 122 | 122 | Say Y here if you want support for keyboards of Apple iBooks, PowerBooks, |
| 123 | 123 | MacBooks, MacBook Pros and Apple Aluminum. |
| 124 | 124 | |
| 125 | +config HID_APPLEIR | |
| 126 | + tristate "Apple infrared receiver" | |
| 127 | + depends on (USB_HID) | |
| 128 | + ---help--- | |
| 129 | + Support for Apple infrared remote control. All the Apple computers from | |
| 130 | + 2005 onwards include such a port, except the unibody Macbook (2009), | |
| 131 | + and Mac Pros. This receiver is also used in the Apple TV set-top box | |
| 132 | + prior to the 2010 model. | |
| 133 | + | |
| 134 | + Say Y here if you want support for Apple infrared remote control. | |
| 135 | + | |
| 125 | 136 | config HID_AUREAL |
| 126 | 137 | tristate "Aureal" |
| 127 | − depends on USB_HID | |
| 138 | + depends on HID | |
| 128 | 139 | ---help--- |
| 129 | 140 | Support for Aureal Cy se W-01RN Remote Controller and other Aureal derived remotes. |
| 130 | 141 | |
| 131 | 142 | config HID_BELKIN |
| 132 | 143 | tristate "Belkin Flip KVM and Wireless keyboard" if EXPERT |
| 133 | − depends on USB_HID | |
| 144 | + depends on HID | |
| 134 | 145 | default !EXPERT |
| 135 | 146 | ---help--- |
| 136 | 147 | Support for Belkin Flip KVM and Wireless keyboard. |
| 137 | 148 | |
| 138 | 149 | config HID_CHERRY |
| 139 | 150 | tristate "Cherry Cymotion keyboard" if EXPERT |
| 140 | − depends on USB_HID | |
| 151 | + depends on HID | |
| 141 | 152 | default !EXPERT |
| 142 | 153 | ---help--- |
| 143 | 154 | Support for Cherry Cymotion keyboard. |
| 144 | 155 | |
| 145 | 156 | config HID_CHICONY |
| 146 | 157 | tristate "Chicony Tactical pad" if EXPERT |
| 147 | − depends on USB_HID | |
| 158 | + depends on HID | |
| 148 | 159 | default !EXPERT |
| 149 | 160 | ---help--- |
| 150 | 161 | Support for Chicony Tactical pad. |
| 151 | 162 | |
| 152 | 163 | config HID_PRODIKEYS |
| 153 | 164 | tristate "Prodikeys PC-MIDI Keyboard support" |
| 154 | − depends on USB_HID && SND | |
| 165 | + depends on HID && SND | |
| 155 | 166 | select SND_RAWMIDI |
| 156 | 167 | ---help--- |
| 157 | 168 | Support for Prodikeys PC-MIDI Keyboard device support. |
| @@ -166,14 +177,14 @@ config HID_PRODIKEYS · 8 unmodified lines | ||
| 166 | 177 | |
| 167 | 178 | config HID_CYPRESS |
| 168 | 179 | tristate "Cypress mouse and barcode readers" if EXPERT |
| 169 | − depends on USB_HID | |
| 180 | + depends on HID | |
| 170 | 181 | default !EXPERT |
| 171 | 182 | ---help--- |
| 172 | 183 | Support for cypress mouse and barcode readers. |
| 173 | 184 | |
| 174 | 185 | config HID_DRAGONRISE |
| 175 | 186 | tristate "DragonRise Inc. game controller" |
| 176 | − depends on USB_HID | |
| 187 | + depends on HID | |
| 177 | 188 | ---help--- |
| 178 | 189 | Say Y here if you have DragonRise Inc. game controllers. |
| 179 | 190 | These might be branded as: |
| @@ -192,7 +203,7 @@ config DRAGONRISE_FF · 12 unmodified lines | ||
| 192 | 203 | |
| 193 | 204 | config HID_EMS_FF |
| 194 | 205 | tristate "EMS Production Inc. force feedback support" |
| 195 | − depends on USB_HID | |
| 206 | + depends on HID | |
| 196 | 207 | select INPUT_FF_MEMLESS |
| 197 | 208 | ---help--- |
| 198 | 209 | Say Y here if you want to enable force feedback support for devices by |
| @@ -202,13 +213,13 @@ config HID_EMS_FF · 3 unmodified lines | ||
| 202 | 213 | |
| 203 | 214 | config HID_ELECOM |
| 204 | 215 | tristate "ELECOM BM084 bluetooth mouse" |
| 205 | − depends on BT_HIDP | |
| 216 | + depends on HID | |
| 206 | 217 | ---help--- |
| 207 | 218 | Support for the ELECOM BM084 (bluetooth mouse). |
| 208 | 219 | |
| 209 | 220 | config HID_EZKEY |
| 210 | 221 | tristate "Ezkey BTC 8193 keyboard" if EXPERT |
| 211 | − depends on USB_HID | |
| 222 | + depends on HID | |
| 212 | 223 | default !EXPERT |
| 213 | 224 | ---help--- |
| 214 | 225 | Support for Ezkey BTC 8193 keyboard. |
| @@ -231,7 +242,7 @@ config HOLTEK_FF · 16 unmodified lines | ||
| 231 | 242 | |
| 232 | 243 | config HID_KEYTOUCH |
| 233 | 244 | tristate "Keytouch HID devices" |
| 234 | − depends on USB_HID | |
| 245 | + depends on HID | |
| 235 | 246 | ---help--- |
| 236 | 247 | Support for Keytouch HID devices not fully compliant with |
| 237 | 248 | the specification. Currently supported: |
| @@ -239,7 +250,7 @@ config HID_KEYTOUCH · 1 unmodified line | ||
| 239 | 250 | |
| 240 | 251 | config HID_KYE |
| 241 | 252 | tristate "KYE/Genius devices" |
| 242 | − depends on USB_HID | |
| 253 | + depends on HID | |
| 243 | 254 | ---help--- |
| 244 | 255 | Support for KYE/Genius devices not fully compliant with HID standard: |
| 245 | 256 | - Ergo Mouse |
| @@ -249,25 +260,25 @@ config HID_KYE · 3 unmodified lines | ||
| 249 | 260 | |
| 250 | 261 | config HID_UCLOGIC |
| 251 | 262 | tristate "UC-Logic" |
| 252 | − depends on USB_HID | |
| 263 | + depends on HID | |
| 253 | 264 | ---help--- |
| 254 | 265 | Support for UC-Logic tablets. |
| 255 | 266 | |
| 256 | 267 | config HID_WALTOP |
| 257 | 268 | tristate "Waltop" |
| 258 | − depends on USB_HID | |
| 269 | + depends on HID | |
| 259 | 270 | ---help--- |
| 260 | 271 | Support for Waltop tablets. |
| 261 | 272 | |
| 262 | 273 | config HID_GYRATION |
| 263 | 274 | tristate "Gyration remote control" |
| 264 | − depends on USB_HID | |
| 275 | + depends on HID | |
| 265 | 276 | ---help--- |
| 266 | 277 | Support for Gyration remote control. |
| 267 | 278 | |
| 268 | 279 | config HID_ICADE |
| 269 | 280 | tristate "ION iCade arcade controller" |
| 270 | − depends on BT_HIDP | |
| 281 | + depends on HID | |
| 271 | 282 | ---help--- |
| 272 | 283 | Support for the ION iCade arcade controller to work as a joystick. |
| 273 | 284 | |
| @@ -276,20 +287,20 @@ config HID_ICADE · 2 unmodified lines | ||
| 276 | 287 | |
| 277 | 288 | config HID_TWINHAN |
| 278 | 289 | tristate "Twinhan IR remote control" |
| 279 | − depends on USB_HID | |
| 290 | + depends on HID | |
| 280 | 291 | ---help--- |
| 281 | 292 | Support for Twinhan IR remote control. |
| 282 | 293 | |
| 283 | 294 | config HID_KENSINGTON |
| 284 | 295 | tristate "Kensington Slimblade Trackball" if EXPERT |
| 285 | − depends on USB_HID | |
| 296 | + depends on HID | |
| 286 | 297 | default !EXPERT |
| 287 | 298 | ---help--- |
| 288 | 299 | Support for Kensington Slimblade Trackball. |
| 289 | 300 | |
| 290 | 301 | config HID_LCPOWER |
| 291 | 302 | tristate "LC-Power" |
| 292 | − depends on USB_HID | |
| 303 | + depends on HID | |
| 293 | 304 | ---help--- |
| 294 | 305 | Support for LC-Power RC1000MCE RF remote control. |
| 295 | 306 | |
| @@ -308,7 +319,7 @@ config HID_LENOVO_TPKBD · 12 unmodified lines | ||
| 308 | 319 | |
| 309 | 320 | config HID_LOGITECH |
| 310 | 321 | tristate "Logitech devices" if EXPERT |
| 311 | − depends on USB_HID | |
| 322 | + depends on HID | |
| 312 | 323 | default !EXPERT |
| 313 | 324 | ---help--- |
| 314 | 325 | Support for Logitech devices that are not fully compliant with HID standard. |
| @@ -373,31 +384,31 @@ config LOGIWHEELS_FF · 58 unmodified lines | ||
| 373 | 384 | - Logitech Formula Force EX |
| 374 | 385 | |
| 375 | 386 | config HID_MAGICMOUSE |
| 376 | − tristate "Apple MagicMouse multi-touch support" | |
| 377 | − depends on BT_HIDP | |
| 387 | + tristate "Apple Magic Mouse/Trackpad multi-touch support" | |
| 388 | + depends on HID | |
| 378 | 389 | ---help--- |
| 379 | − Support for the Apple Magic Mouse multi-touch. | |
| 390 | + Support for the Apple Magic Mouse/Trackpad multi-touch. | |
| 380 | 391 | |
| 381 | 392 | Say Y here if you want support for the multi-touch features of the |
| 382 | − Apple Wireless "Magic" Mouse. | |
| 393 | + Apple Wireless "Magic" Mouse and the Apple Wireless "Magic" Trackpad. | |
| 383 | 394 | |
| 384 | 395 | config HID_MICROSOFT |
| 385 | 396 | tristate "Microsoft non-fully HID-compliant devices" if EXPERT |
| 386 | − depends on USB_HID | |
| 397 | + depends on HID | |
| 387 | 398 | default !EXPERT |
| 388 | 399 | ---help--- |
| 389 | 400 | Support for Microsoft devices that are not fully compliant with HID standard. |
| 390 | 401 | |
| 391 | 402 | config HID_MONTEREY |
| 392 | 403 | tristate "Monterey Genius KB29E keyboard" if EXPERT |
| 393 | − depends on USB_HID | |
| 404 | + depends on HID | |
| 394 | 405 | default !EXPERT |
| 395 | 406 | ---help--- |
| 396 | 407 | Support for Monterey Genius KB29E. |
| 397 | 408 | |
| 398 | 409 | config HID_MULTITOUCH |
| 399 | 410 | tristate "HID Multitouch panels" |
| 400 | − depends on USB_HID | |
| 411 | + depends on HID | |
| 401 | 412 | ---help--- |
| 402 | 413 | Generic support for HID multitouch panels. |
| 403 | 414 | |
| @@ -445,7 +456,7 @@ config HID_NTRIG · 41 unmodified lines | ||
| 445 | 456 | |
| 446 | 457 | config HID_ORTEK |
| 447 | 458 | tristate "Ortek PKB-1700/WKB-2000/Skycable wireless keyboard and mouse trackpad" |
| 448 | − depends on USB_HID | |
| 459 | + depends on HID | |
| 449 | 460 | ---help--- |
| 450 | 461 | There are certain devices which have LogicalMaximum wrong in the keyboard |
| 451 | 462 | usage page of their report descriptor. The most prevailing ones so far |
| @@ -458,7 +469,7 @@ config HID_ORTEK · 6 unmodified lines | ||
| 458 | 469 | |
| 459 | 470 | config HID_PANTHERLORD |
| 460 | 471 | tristate "Pantherlord/GreenAsia game controller" |
| 461 | − depends on USB_HID | |
| 472 | + depends on HID | |
| 462 | 473 | ---help--- |
| 463 | 474 | Say Y here if you have a PantherLord/GreenAsia based game controller |
| 464 | 475 | or adapter. |
| @@ -473,13 +484,13 @@ config PANTHERLORD_FF · 8 unmodified lines | ||
| 473 | 484 | |
| 474 | 485 | config HID_PETALYNX |
| 475 | 486 | tristate "Petalynx Maxter remote control" |
| 476 | − depends on USB_HID | |
| 487 | + depends on HID | |
| 477 | 488 | ---help--- |
| 478 | 489 | Support for Petalynx Maxter remote control. |
| 479 | 490 | |
| 480 | 491 | config HID_PICOLCD |
| 481 | 492 | tristate "PicoLCD (graphic version)" |
| 482 | − depends on USB_HID | |
| 493 | + depends on HID | |
| 483 | 494 | ---help--- |
| 484 | 495 | This provides support for Minibox PicoLCD devices, currently |
| 485 | 496 | only the graphical ones are supported. |
| @@ -545,14 +556,14 @@ config HID_PICOLCD_CIR · 59 unmodified lines | ||
| 545 | 556 | |
| 546 | 557 | config HID_PRIMAX |
| 547 | 558 | tristate "Primax non-fully HID-compliant devices" |
| 548 | − depends on USB_HID | |
| 559 | + depends on HID | |
| 549 | 560 | ---help--- |
| 550 | 561 | Support for Primax devices that are not fully compliant with the |
| 551 | 562 | HID standard. |
| 552 | 563 | |
| 553 | 564 | config HID_PS3REMOTE |
| 554 | 565 | tristate "Sony PS3 BD Remote Control" |
| 555 | − depends on BT_HIDP | |
| 566 | + depends on HID | |
| 556 | 567 | ---help--- |
| 557 | 568 | Support for the Sony PS3 Blue-ray Disk Remote Control and Logitech |
| 558 | 569 | Harmony Adapter for PS3, which connect over Bluetooth. |
| @@ -569,7 +580,7 @@ config HID_ROCCAT · 10 unmodified lines | ||
| 569 | 580 | |
| 570 | 581 | config HID_SAITEK |
| 571 | 582 | tristate "Saitek non-fully HID-compliant devices" |
| 572 | − depends on USB_HID | |
| 583 | + depends on HID | |
| 573 | 584 | ---help--- |
| 574 | 585 | Support for Saitek devices that are not fully compliant with the |
| 575 | 586 | HID standard. |
| @@ -578,7 +589,7 @@ config HID_SAITEK · 2 unmodified lines | ||
| 578 | 589 | |
| 579 | 590 | config HID_SAMSUNG |
| 580 | 591 | tristate "Samsung InfraRed remote control or keyboards" |
| 581 | − depends on USB_HID | |
| 592 | + depends on HID | |
| 582 | 593 | ---help--- |
| 583 | 594 | Support for Samsung InfraRed remote control or keyboards. |
| 584 | 595 | |
| @@ -592,25 +603,25 @@ config HID_SONY · 7 unmodified lines | ||
| 592 | 603 | |
| 593 | 604 | config HID_SPEEDLINK |
| 594 | 605 | tristate "Speedlink VAD Cezanne mouse support" |
| 595 | − depends on USB_HID | |
| 606 | + depends on HID | |
| 596 | 607 | ---help--- |
| 597 | 608 | Support for Speedlink Vicious and Divine Cezanne mouse. |
| 598 | 609 | |
| 599 | 610 | config HID_STEELSERIES |
| 600 | 611 | tristate "Steelseries SRW-S1 steering wheel support" |
| 601 | − depends on USB_HID | |
| 612 | + depends on HID | |
| 602 | 613 | ---help--- |
| 603 | 614 | Support for Steelseries SRW-S1 steering wheel |
| 604 | 615 | |
| 605 | 616 | config HID_SUNPLUS |
| 606 | 617 | tristate "Sunplus wireless desktop" |
| 607 | − depends on USB_HID | |
| 618 | + depends on HID | |
| 608 | 619 | ---help--- |
| 609 | 620 | Support for Sunplus wireless desktop. |
| 610 | 621 | |
| 611 | 622 | config HID_GREENASIA |
| 612 | 623 | tristate "GreenAsia (Product ID 0x12) game controller support" |
| 613 | − depends on USB_HID | |
| 624 | + depends on HID | |
| 614 | 625 | ---help--- |
| 615 | 626 | Say Y here if you have a GreenAsia (Product ID 0x12) based game |
| 616 | 627 | controller or adapter. |
| @@ -632,7 +643,7 @@ config HID_HYPERV_MOUSE · 15 unmodified lines | ||
| 632 | 643 | |
| 633 | 644 | config HID_SMARTJOYPLUS |
| 634 | 645 | tristate "SmartJoy PLUS PS2/USB adapter support" |
| 635 | − depends on USB_HID | |
| 646 | + depends on HID | |
| 636 | 647 | ---help--- |
| 637 | 648 | Support for SmartJoy PLUS PS2/USB adapter, Super Dual Box, |
| 638 | 649 | Super Joy Box 3 Pro, Super Dual Box Pro, and Super Joy Box 5 Pro. |
| @@ -650,20 +661,20 @@ config SMARTJOYPLUS_FF · 11 unmodified lines | ||
| 650 | 661 | |
| 651 | 662 | config HID_TIVO |
| 652 | 663 | tristate "TiVo Slide Bluetooth remote control support" |
| 653 | − depends on (USB_HID || BT_HIDP) | |
| 664 | + depends on HID | |
| 654 | 665 | ---help--- |
| 655 | 666 | Say Y if you have a TiVo Slide Bluetooth remote control. |
| 656 | 667 | |
| 657 | 668 | config HID_TOPSEED |
| 658 | 669 | tristate "TopSeed Cyberlink, BTC Emprex, Conceptronic remote control support" |
| 659 | − depends on USB_HID | |
| 670 | + depends on HID | |
| 660 | 671 | ---help--- |
| 661 | 672 | Say Y if you have a TopSeed Cyberlink or BTC Emprex or Conceptronic |
| 662 | 673 | CLLRCMCE remote control. |
| 663 | 674 | |
| 664 | 675 | config HID_THINGM |
| 665 | 676 | tristate "ThingM blink(1) USB RGB LED" |
| 666 | − depends on USB_HID | |
| 677 | + depends on HID | |
| 667 | 678 | depends on LEDS_CLASS |
| 668 | 679 | ---help--- |
| 669 | 680 | Support for the ThingM blink(1) USB RGB LED. This driver registers a |
| @@ -673,7 +684,7 @@ config HID_THINGM · 3 unmodified lines | ||
| 673 | 684 | |
| 674 | 685 | config HID_THRUSTMASTER |
| 675 | 686 | tristate "ThrustMaster devices support" |
| 676 | − depends on USB_HID | |
| 687 | + depends on HID | |
| 677 | 688 | ---help--- |
| 678 | 689 | Say Y here if you have a THRUSTMASTER FireStore Dual Power 2 or |
| 679 | 690 | a THRUSTMASTER Ferrari GT Rumble Wheel. |
| @@ -689,7 +700,7 @@ config THRUSTMASTER_FF · 9 unmodified lines | ||
| 689 | 700 | |
| 690 | 701 | config HID_WACOM |
| 691 | 702 | tristate "Wacom Bluetooth devices support" |
| 692 | − depends on BT_HIDP | |
| 703 | + depends on HID | |
| 693 | 704 | depends on LEDS_CLASS |
| 694 | 705 | select POWER_SUPPLY |
| 695 | 706 | ---help--- |
| @@ -697,7 +708,7 @@ config HID_WACOM · 1 unmodified line | ||
| 697 | 708 | |
| 698 | 709 | config HID_WIIMOTE |
| 699 | 710 | tristate "Nintendo Wii Remote support" |
| 700 | − depends on BT_HIDP | |
| 711 | + depends on HID | |
| 701 | 712 | depends on LEDS_CLASS |
| 702 | 713 | select POWER_SUPPLY |
| 703 | 714 | select INPUT_FF_MEMLESS |
| @@ -715,7 +726,7 @@ config HID_WIIMOTE_EXT · 11 unmodified lines | ||
| 715 | 726 | |
| 716 | 727 | config HID_ZEROPLUS |
| 717 | 728 | tristate "Zeroplus based game controller support" |
| 718 | − depends on USB_HID | |
| 729 | + depends on HID | |
| 719 | 730 | ---help--- |
| 720 | 731 | Say Y here if you have a Zeroplus based game controller. |
| 721 | 732 | |
| @@ -729,16 +740,16 @@ config ZEROPLUS_FF · 7 unmodified lines | ||
| 729 | 740 | |
| 730 | 741 | config HID_ZYDACRON |
| 731 | 742 | tristate "Zydacron remote control support" |
| 732 | − depends on USB_HID | |
| 743 | + depends on HID | |
| 733 | 744 | ---help--- |
| 734 | 745 | Support for Zydacron remote control. |
| 735 | 746 | |
| 736 | 747 | config HID_SENSOR_HUB |
| 737 | 748 | tristate "HID Sensors framework support" |
| 738 | − depends on USB_HID && GENERIC_HARDIRQS | |
| 749 | + depends on HID && GENERIC_HARDIRQS | |
| 739 | 750 | select MFD_CORE |
| 740 | 751 | default n |
| 741 | − -- help--- | |
| 752 | + ---help--- | |
| 742 | 753 | Support for HID Sensor framework. This creates a MFD instance |
| 743 | 754 | for a sensor hub and identifies all the sensors connected to it. |
| 744 | 755 | Each sensor is registered as a MFD cell, so that sensor specific |
| @@ -39,6 +39,7 @@ endif · 38 unmodified lines | ||
| 39 | 39 | obj-$(CONFIG_HID_A4TECH) += hid-a4tech.o |
| 40 | 40 | obj-$(CONFIG_HID_ACRUX) += hid-axff.o |
| 41 | 41 | obj-$(CONFIG_HID_APPLE) += hid-apple.o |
| 42 | +obj-$(CONFIG_HID_APPLEIR) += hid-appleir.o | |
| 42 | 43 | obj-$(CONFIG_HID_AUREAL) += hid-aureal.o |
| 43 | 44 | obj-$(CONFIG_HID_BELKIN) += hid-belkin.o |
| 44 | 45 | obj-$(CONFIG_HID_CHERRY) += hid-cherry.o |
| @@ -94,8 +95,8 @@ obj-$(CONFIG_HID_PRIMAX) += hid-primax.o · 49 unmodified lines | ||
| 94 | 95 | obj-$(CONFIG_HID_PS3REMOTE) += hid-ps3remote.o |
| 95 | 96 | obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o hid-roccat-common.o \ |
| 96 | 97 | hid-roccat-arvo.o hid-roccat-isku.o hid-roccat-kone.o \ |
| 97 | − hid-roccat-koneplus.o hid-roccat-kovaplus.o hid-roccat-lua.o \ | |
| 98 | − hid-roccat-pyra.o hid-roccat-savu.o | |
| 98 | + hid-roccat-koneplus.o hid-roccat-konepure.o hid-roccat-kovaplus.o \ | |
| 99 | + hid-roccat-lua.o hid-roccat-pyra.o hid-roccat-savu.o | |
| 99 | 100 | obj-$(CONFIG_HID_SAITEK) += hid-saitek.o |
| 100 | 101 | obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o |
| 101 | 102 | obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o |
| @@ -21,7 +21,6 @@ · 20 unmodified lines | ||
| 21 | 21 | #include <linux/hid.h> |
| 22 | 22 | #include <linux/module.h> |
| 23 | 23 | #include <linux/slab.h> |
| 24 | −#include <linux/usb.h> | |
| 25 | 24 | |
| 26 | 25 | #include "hid-ids.h" |
| 27 | 26 | |
| @@ -390,10 +389,6 @@ static void apple_remove(struct hid_device *hdev) · 362 unmodified lines | ||
| 390 | 389 | } |
| 391 | 390 | |
| 392 | 391 | static const struct hid_device_id apple_devices[] = { |
| 393 | − { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ATV_IRCONTROL), | |
| 394 | − .driver_data = APPLE_HIDDEV | APPLE_IGNORE_HIDINPUT }, | |
| 395 | − { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4), | |
| 396 | − .driver_data = APPLE_HIDDEV | APPLE_IGNORE_HIDINPUT }, | |
| 397 | 392 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE), |
| 398 | 393 | .driver_data = APPLE_MIGHTYMOUSE | APPLE_INVERT_HWHEEL }, |
| 399 | 394 | |
| @@ -0,0 +1,352 @@ | ||
| 1 | +/* | |
| 2 | + * HID driver for the apple ir device | |
| 3 | + * | |
| 4 | + * Original driver written by James McKenzie | |
| 5 | + * Ported to recent 2.6 kernel versions by Greg Kroah-Hartman <gregkh@suse.de> | |
| 6 | + * Updated to support newer remotes by Bastien Nocera <hadess@hadess.net> | |
| 7 | + * Ported to HID subsystem by Benjamin Tissoires <benjamin.tissoires@gmail.com> | |
| 8 | + * | |
| 9 | + * Copyright (C) 2006 James McKenzie | |
| 10 | + * Copyright (C) 2008 Greg Kroah-Hartman <greg@kroah.com> | |
| 11 | + * Copyright (C) 2008 Novell Inc. | |
| 12 | + * Copyright (C) 2010, 2012 Bastien Nocera <hadess@hadess.net> | |
| 13 | + * Copyright (C) 2013 Benjamin Tissoires <benjamin.tissoires@gmail.com> | |
| 14 | + * Copyright (C) 2013 Red Hat Inc. All Rights Reserved | |
| 15 | + * | |
| 16 | + * This software is licensed under the terms of the GNU General Public | |
| 17 | + * License version 2, as published by the Free Software Foundation, and | |
| 18 | + * may be copied, distributed, and modified under those terms. | |
| 19 | + * | |
| 20 | + * This program is distributed in the hope that it will be useful, | |
| 21 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 22 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 23 | + * GNU General Public License for more details. | |
| 24 | + */ | |
| 25 | + | |
| 26 | +#include <linux/device.h> | |
| 27 | +#include <linux/hid.h> | |
| 28 | +#include <linux/module.h> | |
| 29 | +#include "hid-ids.h" | |
| 30 | + | |
| 31 | +MODULE_AUTHOR("James McKenzie"); | |
| 32 | +MODULE_AUTHOR("Benjamin Tissoires <benjamin.tissoires@redhat.com>"); | |
| 33 | +MODULE_DESCRIPTION("HID Apple IR remote controls"); | |
| 34 | +MODULE_LICENSE("GPL"); | |
| 35 | + | |
| 36 | +#define KEY_MASK 0x0F | |
| 37 | +#define TWO_PACKETS_MASK 0x40 | |
| 38 | + | |
| 39 | +/* | |
| 40 | + * James McKenzie has two devices both of which report the following | |
| 41 | + * 25 87 ee 83 0a + | |
| 42 | + * 25 87 ee 83 0c - | |
| 43 | + * 25 87 ee 83 09 << | |
| 44 | + * 25 87 ee 83 06 >> | |
| 45 | + * 25 87 ee 83 05 >" | |
| 46 | + * 25 87 ee 83 03 menu | |
| 47 | + * 26 00 00 00 00 for key repeat | |
| 48 | + */ | |
| 49 | + | |
| 50 | +/* | |
| 51 | + * Thomas Glanzmann reports the following responses | |
| 52 | + * 25 87 ee ca 0b + | |
| 53 | + * 25 87 ee ca 0d - | |
| 54 | + * 25 87 ee ca 08 << | |
| 55 | + * 25 87 ee ca 07 >> | |
| 56 | + * 25 87 ee ca 04 >" | |
| 57 | + * 25 87 ee ca 02 menu | |
| 58 | + * 26 00 00 00 00 for key repeat | |
| 59 | + * | |
| 60 | + * He also observes the following event sometimes | |
| 61 | + * sent after a key is release, which I interpret | |
| 62 | + * as a flat battery message | |
| 63 | + * 25 87 e0 ca 06 flat battery | |
| 64 | + */ | |
| 65 | + | |
| 66 | +/* | |
| 67 | + * Alexandre Karpenko reports the following responses for Device ID 0x8242 | |
| 68 | + * 25 87 ee 47 0b + | |
| 69 | + * 25 87 ee 47 0d - | |
| 70 | + * 25 87 ee 47 08 << | |
| 71 | + * 25 87 ee 47 07 >> | |
| 72 | + * 25 87 ee 47 04 >" | |
| 73 | + * 25 87 ee 47 02 menu | |
| 74 | + * 26 87 ee 47 ** for key repeat (** is the code of the key being held) | |
| 75 | + */ | |
| 76 | + | |
| 77 | +/* | |
| 78 | + * Bastien Nocera's remote | |
| 79 | + * 25 87 ee 91 5f followed by | |
| 80 | + * 25 87 ee 91 05 gives you >" | |
| 81 | + * | |
| 82 | + * 25 87 ee 91 5c followed by | |
| 83 | + * 25 87 ee 91 05 gives you the middle button | |
| 84 | + */ | |
| 85 | + | |
| 86 | +/* | |
| 87 | + * Fabien Andre's remote | |
| 88 | + * 25 87 ee a3 5e followed by | |
| 89 | + * 25 87 ee a3 04 gives you >" | |
| 90 | + * | |
| 91 | + * 25 87 ee a3 5d followed by | |
| 92 | + * 25 87 ee a3 04 gives you the middle button | |
| 93 | + */ | |
| 94 | + | |
| 95 | +static const unsigned short appleir_key_table[] = { | |
| 96 | + KEY_RESERVED, | |
| 97 | + KEY_MENU, | |
| 98 | + KEY_PLAYPAUSE, | |
| 99 | + KEY_FORWARD, | |
| 100 | + KEY_BACK, | |
| 101 | + KEY_VOLUMEUP, | |
| 102 | + KEY_VOLUMEDOWN, | |
| 103 | + KEY_RESERVED, | |
| 104 | + KEY_RESERVED, | |
| 105 | + KEY_RESERVED, | |
| 106 | + KEY_RESERVED, | |
| 107 | + KEY_RESERVED, | |
| 108 | + KEY_RESERVED, | |
| 109 | + KEY_RESERVED, | |
| 110 | + KEY_ENTER, | |
| 111 | + KEY_PLAYPAUSE, | |
| 112 | + KEY_RESERVED, | |
| 113 | +}; | |
| 114 | + | |
| 115 | +struct appleir { | |
| 116 | + struct input_dev *input_dev; | |
| 117 | + struct hid_device *hid; | |
| 118 | + unsigned short keymap[ARRAY_SIZE(appleir_key_table)]; | |
| 119 | + struct timer_list key_up_timer; /* timer for key up */ | |
| 120 | + spinlock_t lock; /* protects .current_key */ | |
| 121 | + int current_key; /* the currently pressed key */ | |
| 122 | + int prev_key_idx; /* key index in a 2 packets message */ | |
| 123 | +}; | |
| 124 | + | |
| 125 | +static int get_key(int data) | |
| 126 | +{ | |
| 127 | + /* | |
| 128 | + * The key is coded accross bits 2..9: | |
| 129 | + * | |
| 130 | + * 0x00 or 0x01 ( ) key: 0 -> KEY_RESERVED | |
| 131 | + * 0x02 or 0x03 ( menu ) key: 1 -> KEY_MENU | |
| 132 | + * 0x04 or 0x05 ( >" ) key: 2 -> KEY_PLAYPAUSE | |
| 133 | + * 0x06 or 0x07 ( >> ) key: 3 -> KEY_FORWARD | |
| 134 | + * 0x08 or 0x09 ( << ) key: 4 -> KEY_BACK | |
| 135 | + * 0x0a or 0x0b ( + ) key: 5 -> KEY_VOLUMEUP | |
| 136 | + * 0x0c or 0x0d ( - ) key: 6 -> KEY_VOLUMEDOWN | |
| 137 | + * 0x0e or 0x0f ( ) key: 7 -> KEY_RESERVED | |
| 138 | + * 0x50 or 0x51 ( ) key: 8 -> KEY_RESERVED | |
| 139 | + * 0x52 or 0x53 ( ) key: 9 -> KEY_RESERVED | |
| 140 | + * 0x54 or 0x55 ( ) key: 10 -> KEY_RESERVED | |
| 141 | + * 0x56 or 0x57 ( ) key: 11 -> KEY_RESERVED | |
| 142 | + * 0x58 or 0x59 ( ) key: 12 -> KEY_RESERVED | |
| 143 | + * 0x5a or 0x5b ( ) key: 13 -> KEY_RESERVED | |
| 144 | + * 0x5c or 0x5d ( middle ) key: 14 -> KEY_ENTER | |
| 145 | + * 0x5e or 0x5f ( >" ) key: 15 -> KEY_PLAYPAUSE | |
| 146 | + * | |
| 147 | + * Packets starting with 0x5 are part of a two-packets message, | |
| 148 | + * we notify the caller by sending a negative value. | |
| 149 | + */ | |
| 150 | + int key = (data >> 1) & KEY_MASK; | |
| 151 | + | |
| 152 | + if ((data & TWO_PACKETS_MASK)) | |
| 153 | + /* Part of a 2 packets-command */ | |
| 154 | + key = -key; | |
| 155 | + | |
| 156 | + return key; | |
| 157 | +} | |
| 158 | + | |
| 159 | +static void key_up(struct hid_device *hid, struct appleir *appleir, int key) | |
| 160 | +{ | |
| 161 | + input_report_key(appleir->input_dev, key, 0); | |
| 162 | + input_sync(appleir->input_dev); | |
| 163 | +} | |
| 164 | + | |
| 165 | +static void key_down(struct hid_device *hid, struct appleir *appleir, int key) | |
| 166 | +{ | |
| 167 | + input_report_key(appleir->input_dev, key, 1); | |
| 168 | + input_sync(appleir->input_dev); | |
| 169 | +} | |
| 170 | + | |
| 171 | +static void battery_flat(struct appleir *appleir) | |
| 172 | +{ | |
| 173 | + dev_err(&appleir->input_dev->dev, "possible flat battery?\n"); | |
| 174 | +} | |
| 175 | + | |
| 176 | +static void key_up_tick(unsigned long data) | |
| 177 | +{ | |
| 178 | + struct appleir *appleir = (struct appleir *)data; | |
| 179 | + struct hid_device *hid = appleir->hid; | |
| 180 | + unsigned long flags; | |
| 181 | + | |
| 182 | + spin_lock_irqsave(&appleir->lock, flags); | |
| 183 | + if (appleir->current_key) { | |
| 184 | + key_up(hid, appleir, appleir->current_key); | |
| 185 | + appleir->current_key = 0; | |
| 186 | + } | |
| 187 | + spin_unlock_irqrestore(&appleir->lock, flags); | |
| 188 | +} | |
| 189 | + | |
| 190 | +static int appleir_raw_event(struct hid_device *hid, struct hid_report *report, | |
| 191 | + u8 *data, int len) | |
| 192 | +{ | |
| 193 | + struct appleir *appleir = hid_get_drvdata(hid); | |
| 194 | + static const u8 keydown[] = { 0x25, 0x87, 0xee }; | |
| 195 | + static const u8 keyrepeat[] = { 0x26, }; | |
| 196 | + static const u8 flatbattery[] = { 0x25, 0x87, 0xe0 }; | |
| 197 | + unsigned long flags; | |
| 198 | + | |
| 199 | + if (len != 5) | |
| 200 | + goto out; | |
| 201 | + | |
| 202 | + if (!memcmp(data, keydown, sizeof(keydown))) { | |
| 203 | + int index; | |
| 204 | + | |
| 205 | + spin_lock_irqsave(&appleir->lock, flags); | |
| 206 | + /* | |
| 207 | + * If we already have a key down, take it up before marking | |
| 208 | + * this one down | |
| 209 | + */ | |
| 210 | + if (appleir->current_key) | |
| 211 | + key_up(hid, appleir, appleir->current_key); | |
| 212 | + | |
| 213 | + /* Handle dual packet commands */ | |
| 214 | + if (appleir->prev_key_idx > 0) | |
| 215 | + index = appleir->prev_key_idx; | |
| 216 | + else | |
| 217 | + index = get_key(data[4]); | |
| 218 | + | |
| 219 | + if (index >= 0) { | |
| 220 | + appleir->current_key = appleir->keymap[index]; | |
| 221 | + | |
| 222 | + key_down(hid, appleir, appleir->current_key); | |
| 223 | + /* | |
| 224 | + * Remote doesn't do key up, either pull them up, in | |
| 225 | + * the test above, or here set a timer which pulls | |
| 226 | + * them up after 1/8 s | |
| 227 | + */ | |
| 228 | + mod_timer(&appleir->key_up_timer, jiffies + HZ / 8); | |
| 229 | + appleir->prev_key_idx = 0; | |
| 230 | + } else | |
| 231 | + /* Remember key for next packet */ | |
| 232 | + appleir->prev_key_idx = -index; | |
| 233 | + spin_unlock_irqrestore(&appleir->lock, flags); | |
| 234 | + goto out; | |
| 235 | + } | |
| 236 | + | |
| 237 | + appleir->prev_key_idx = 0; | |
| 238 | + | |
| 239 | + if (!memcmp(data, keyrepeat, sizeof(keyrepeat))) { | |
| 240 | + key_down(hid, appleir, appleir->current_key); | |
| 241 | + /* | |
| 242 | + * Remote doesn't do key up, either pull them up, in the test | |
| 243 | + * above, or here set a timer which pulls them up after 1/8 s | |
| 244 | + */ | |
| 245 | + mod_timer(&appleir->key_up_timer, jiffies + HZ / 8); | |
| 246 | + goto out; | |
| 247 | + } | |
| 248 | + | |
| 249 | + if (!memcmp(data, flatbattery, sizeof(flatbattery))) { | |
| 250 | + battery_flat(appleir); | |
| 251 | + /* Fall through */ | |
| 252 | + } | |
| 253 | + | |
| 254 | +out: | |
| 255 | + /* let hidraw and hiddev handle the report */ | |
| 256 | + return 0; | |
| 257 | +} | |
| 258 | + | |
| 259 | +static void appleir_input_configured(struct hid_device *hid, | |
| 260 | + struct hid_input *hidinput) | |
| 261 | +{ | |
| 262 | + struct input_dev *input_dev = hidinput->input; | |
| 263 | + struct appleir *appleir = hid_get_drvdata(hid); | |
| 264 | + int i; | |
| 265 | + | |
| 266 | + appleir->input_dev = input_dev; | |
| 267 | + | |
| 268 | + input_dev->keycode = appleir->keymap; | |
| 269 | + input_dev->keycodesize = sizeof(unsigned short); | |
| 270 | + input_dev->keycodemax = ARRAY_SIZE(appleir->keymap); | |
| 271 | + | |
| 272 | + input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); | |
| 273 | + | |
| 274 | + memcpy(appleir->keymap, appleir_key_table, sizeof(appleir->keymap)); | |
| 275 | + for (i = 0; i < ARRAY_SIZE(appleir_key_table); i++) | |
| 276 | + set_bit(appleir->keymap[i], input_dev->keybit); | |
| 277 | + clear_bit(KEY_RESERVED, input_dev->keybit); | |
| 278 | +} | |
| 279 | + | |
| 280 | +static int appleir_input_mapping(struct hid_device *hid, | |
| 281 | + struct hid_input *hi, struct hid_field *field, | |
| 282 | + struct hid_usage *usage, unsigned long **bit, int *max) | |
| 283 | +{ | |
| 284 | + return -1; | |
| 285 | +} | |
| 286 | + | |
| 287 | +static int appleir_probe(struct hid_device *hid, const struct hid_device_id *id) | |
| 288 | +{ | |
| 289 | + int ret; | |
| 290 | + struct appleir *appleir; | |
| 291 | + | |
| 292 | + appleir = kzalloc(sizeof(struct appleir), GFP_KERNEL); | |
| 293 | + if (!appleir) { | |
| 294 | + ret = -ENOMEM; | |
| 295 | + goto allocfail; | |
| 296 | + } | |
| 297 | + | |
| 298 | + appleir->hid = hid; | |
| 299 | + | |
| 300 | + spin_lock_init(&appleir->lock); | |
| 301 | + setup_timer(&appleir->key_up_timer, | |
| 302 | + key_up_tick, (unsigned long) appleir); | |
| 303 | + | |
| 304 | + hid_set_drvdata(hid, appleir); | |
| 305 | + | |
| 306 | + ret = hid_parse(hid); | |
| 307 | + if (ret) { | |
| 308 | + hid_err(hid, "parse failed\n"); | |
| 309 | + goto fail; | |
| 310 | + } | |
| 311 | + | |
| 312 | + ret = hid_hw_start(hid, HID_CONNECT_DEFAULT | HID_CONNECT_HIDDEV_FORCE); | |
| 313 | + if (ret) { | |
| 314 | + hid_err(hid, "hw start failed\n"); | |
| 315 | + goto fail; | |
| 316 | + } | |
| 317 | + | |
| 318 | + return 0; | |
| 319 | +fail: | |
| 320 | + kfree(appleir); | |
| 321 | +allocfail: | |
| 322 | + return ret; | |
| 323 | +} | |
| 324 | + | |
| 325 | +static void appleir_remove(struct hid_device *hid) | |
| 326 | +{ | |
| 327 | + struct appleir *appleir = hid_get_drvdata(hid); | |
| 328 | + hid_hw_stop(hid); | |
| 329 | + del_timer_sync(&appleir->key_up_timer); | |
| 330 | + kfree(appleir); | |
| 331 | +} | |
| 332 | + | |
| 333 | +static const struct hid_device_id appleir_devices[] = { | |
| 334 | + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL) }, | |
| 335 | + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL2) }, | |
| 336 | + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL3) }, | |
| 337 | + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4) }, | |
| 338 | + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL5) }, | |
| 339 | + { } | |
| 340 | +}; | |
| 341 | +MODULE_DEVICE_TABLE(hid, appleir_devices); | |
| 342 | + | |
| 343 | +static struct hid_driver appleir_driver = { | |
| 344 | + .name = "appleir", | |
| 345 | + .id_table = appleir_devices, | |
| 346 | + .raw_event = appleir_raw_event, | |
| 347 | + .input_configured = appleir_input_configured, | |
| 348 | + .probe = appleir_probe, | |
| 349 | + .remove = appleir_remove, | |
| 350 | + .input_mapping = appleir_input_mapping, | |
| 351 | +}; | |
| 352 | +module_hid_driver(appleir_driver); | |
| @@ -29,14 +29,12 @@ · 28 unmodified lines | ||
| 29 | 29 | |
| 30 | 30 | #include <linux/input.h> |
| 31 | 31 | #include <linux/slab.h> |
| 32 | −#include <linux/usb.h> | |
| 33 | 32 | #include <linux/hid.h> |
| 34 | 33 | #include <linux/module.h> |
| 35 | 34 | |
| 36 | 35 | #include "hid-ids.h" |
| 37 | 36 | |
| 38 | 37 | #ifdef CONFIG_HID_ACRUX_FF |
| 39 | −#include "usbhid/usbhid.h" | |
| 40 | 38 | |
| 41 | 39 | struct axff_device { |
| 42 | 40 | struct hid_report *report; |
| @@ -68,7 +66,7 @@ static int axff_play(struct input_dev *dev, void *data, struct ff_effect *effect · 25 unmodified lines | ||
| 68 | 66 | } |
| 69 | 67 | |
| 70 | 68 | dbg_hid("running with 0x%02x 0x%02x", left, right); |
| 71 | − usbhid_submit_report(hid, axff->report, USB_DIR_OUT); | |
| 69 | + hid_hw_request(hid, axff->report, HID_REQ_SET_REPORT); | |
| 72 | 70 | |
| 73 | 71 | return 0; |
| 74 | 72 | } |
| @@ -114,7 +112,7 @@ static int axff_init(struct hid_device *hid) · 39 unmodified lines | ||
| 114 | 112 | goto err_free_mem; |
| 115 | 113 | |
| 116 | 114 | axff->report = report; |
| 117 | − usbhid_submit_report(hid, axff->report, USB_DIR_OUT); | |
| 115 | + hid_hw_request(hid, axff->report, HID_REQ_SET_REPORT); | |
| 118 | 116 | |
| 119 | 117 | hid_info(hid, "Force Feedback for ACRUX game controllers by Sergei Kolzun <x0r@dv-life.ru>\n"); |
| 120 | 118 | |
| @@ -728,8 +728,7 @@ static int hid_scan_report(struct hid_device *hid) · 727 unmodified lines | ||
| 728 | 728 | } else if (page == HID_UP_SENSOR && |
| 729 | 729 | item.type == HID_ITEM_TYPE_MAIN && |
| 730 | 730 | item.tag == HID_MAIN_ITEM_TAG_BEGIN_COLLECTION && |
| 731 | − (item_udata(&item) & 0xff) == HID_COLLECTION_PHYSICAL && | |
| 732 | − (hid->bus == BUS_USB || hid->bus == BUS_I2C)) | |
| 731 | + (item_udata(&item) & 0xff) == HID_COLLECTION_PHYSICAL) | |
| 733 | 732 | hid->group = HID_GROUP_SENSOR_HUB; |
| 734 | 733 | } |
| 735 | 734 | |
| @@ -1260,14 +1259,12 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i · 524 unmodified lines | ||
| 1260 | 1259 | struct hid_report_enum *report_enum; |
| 1261 | 1260 | struct hid_driver *hdrv; |
| 1262 | 1261 | struct hid_report *report; |
| 1263 | − char *buf; | |
| 1264 | − unsigned int i; | |
| 1265 | 1262 | int ret = 0; |
| 1266 | 1263 | |
| 1267 | 1264 | if (!hid) |
| 1268 | 1265 | return -ENODEV; |
| 1269 | 1266 | |
| 1270 | − if (down_trylock(&hid->driver_lock)) | |
| 1267 | + if (down_trylock(&hid->driver_input_lock)) | |
| 1271 | 1268 | return -EBUSY; |
| 1272 | 1269 | |
| 1273 | 1270 | if (!hid->driver) { |
| @@ -1284,28 +1281,9 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i · 10 unmodified lines | ||
| 1284 | 1281 | } |
| 1285 | 1282 | |
| 1286 | 1283 | /* Avoid unnecessary overhead if debugfs is disabled */ |
| 1287 | − if (list_empty(&hid->debug_list)) | |
| 1288 | − goto nomem; | |
| 1289 | − | |
| 1290 | − buf = kmalloc(sizeof(char) * HID_DEBUG_BUFSIZE, GFP_ATOMIC); | |
| 1291 | − | |
| 1292 | − if (!buf) | |
| 1293 | − goto nomem; | |
| 1294 | − | |
| 1295 | − /* dump the report */ | |
| 1296 | − snprintf(buf, HID_DEBUG_BUFSIZE - 1, | |
| 1297 | − "\nreport (size %u) (%snumbered) = ", size, report_enum->numbered ? "" : "un"); | |
| 1298 | − hid_debug_event(hid, buf); | |
| 1299 | − | |
| 1300 | − for (i = 0; i < size; i++) { | |
| 1301 | − snprintf(buf, HID_DEBUG_BUFSIZE - 1, | |
| 1302 | − " %02x", data[i]); | |
| 1303 | − hid_debug_event(hid, buf); | |
| 1304 | − } | |
| 1305 | − hid_debug_event(hid, "\n"); | |
| 1306 | − kfree(buf); | |
| 1284 | + if (!list_empty(&hid->debug_list)) | |
| 1285 | + hid_dump_report(hid, type, data, size); | |
| 1307 | 1286 | |
| 1308 | −nomem: | |
| 1309 | 1287 | report = hid_get_report(report_enum, data); |
| 1310 | 1288 | |
| 1311 | 1289 | if (!report) { |
| @@ -1324,7 +1302,7 @@ nomem: · 12 unmodified lines | ||
| 1324 | 1302 | ret = hid_report_raw_event(hid, type, data, size, interrupt); |
| 1325 | 1303 | |
| 1326 | 1304 | unlock: |
| 1327 | − up(&hid->driver_lock); | |
| 1305 | + up(&hid->driver_input_lock); | |
| 1328 | 1306 | return ret; |
| 1329 | 1307 | } |
| 1330 | 1308 | EXPORT_SYMBOL_GPL(hid_input_report); |
| @@ -1502,8 +1480,6 @@ static const struct hid_device_id hid_have_special_driver[] = { · 171 unmodified lines | ||
| 1502 | 1480 | { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D) }, |
| 1503 | 1481 | { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_RP_649) }, |
| 1504 | 1482 | { HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0x0802) }, |
| 1505 | − { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ATV_IRCONTROL) }, | |
| 1506 | − { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4) }, | |
| 1507 | 1483 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE) }, |
| 1508 | 1484 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICMOUSE) }, |
| 1509 | 1485 | { 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[] = { · 17 unmodified lines | ||
| 1527 | 1503 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI) }, |
| 1528 | 1504 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO) }, |
| 1529 | 1505 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS) }, |
| 1506 | + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL) }, | |
| 1507 | + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL2) }, | |
| 1508 | + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL3) }, | |
| 1509 | + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4) }, | |
| 1510 | + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL5) }, | |
| 1530 | 1511 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI) }, |
| 1531 | 1512 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO) }, |
| 1532 | 1513 | { 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[] = { · 121 unmodified lines | ||
| 1654 | 1635 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500) }, |
| 1655 | 1636 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV) }, |
| 1656 | 1637 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K) }, |
| 1638 | + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K_JP) }, | |
| 1657 | 1639 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_LK6K) }, |
| 1658 | 1640 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB) }, |
| 1659 | 1641 | { 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[] = { · 27 unmodified lines | ||
| 1687 | 1669 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ARVO) }, |
| 1688 | 1670 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKU) }, |
| 1689 | 1671 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) }, |
| 1672 | + { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPURE) }, | |
| 1690 | 1673 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KOVAPLUS) }, |
| 1691 | 1674 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_LUA) }, |
| 1692 | 1675 | { 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[] = { · 54 unmodified lines | ||
| 1747 | 1730 | |
| 1748 | 1731 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT) }, |
| 1749 | 1732 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO, USB_DEVICE_ID_NINTENDO_WIIMOTE) }, |
| 1733 | + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO, USB_DEVICE_ID_NINTENDO_WIIMOTE2) }, | |
| 1750 | 1734 | { } |
| 1751 | 1735 | }; |
| 1752 | 1736 | |
| @@ -1845,6 +1829,11 @@ static int hid_device_probe(struct device *dev) · 92 unmodified lines | ||
| 1845 | 1829 | |
| 1846 | 1830 | if (down_interruptible(&hdev->driver_lock)) |
| 1847 | 1831 | return -EINTR; |
| 1832 | + if (down_interruptible(&hdev->driver_input_lock)) { | |
| 1833 | + ret = -EINTR; | |
| 1834 | + goto unlock_driver_lock; | |
| 1835 | + } | |
| 1836 | + hdev->io_started = false; | |
| 1848 | 1837 | |
| 1849 | 1838 | if (!hdev->driver) { |
| 1850 | 1839 | id = hid_match_device(hdev, hdrv); |
| @@ -1867,6 +1856,9 @@ static int hid_device_probe(struct device *dev) · 16 unmodified lines | ||
| 1867 | 1856 | } |
| 1868 | 1857 | } |
| 1869 | 1858 | unlock: |
| 1859 | + if (!hdev->io_started) | |
| 1860 | + up(&hdev->driver_input_lock); | |
| 1861 | +unlock_driver_lock: | |
| 1870 | 1862 | up(&hdev->driver_lock); |
| 1871 | 1863 | return ret; |
| 1872 | 1864 | } |
| @@ -1875,9 +1867,15 @@ static int hid_device_remove(struct device *dev) · 2 unmodified lines | ||
| 1875 | 1867 | { |
| 1876 | 1868 | struct hid_device *hdev = container_of(dev, struct hid_device, dev); |
| 1877 | 1869 | struct hid_driver *hdrv; |
| 1870 | + int ret = 0; | |
| 1878 | 1871 | |
| 1879 | 1872 | if (down_interruptible(&hdev->driver_lock)) |
| 1880 | 1873 | return -EINTR; |
| 1874 | + if (down_interruptible(&hdev->driver_input_lock)) { | |
| 1875 | + ret = -EINTR; | |
| 1876 | + goto unlock_driver_lock; | |
| 1877 | + } | |
| 1878 | + hdev->io_started = false; | |
| 1881 | 1879 | |
| 1882 | 1880 | hdrv = hdev->driver; |
| 1883 | 1881 | if (hdrv) { |
| @@ -1889,8 +1887,11 @@ static int hid_device_remove(struct device *dev) · 5 unmodified lines | ||
| 1889 | 1887 | hdev->driver = NULL; |
| 1890 | 1888 | } |
| 1891 | 1889 | |
| 1890 | + if (!hdev->io_started) | |
| 1891 | + up(&hdev->driver_input_lock); | |
| 1892 | +unlock_driver_lock: | |
| 1892 | 1893 | up(&hdev->driver_lock); |
| 1893 | − return 0; | |
| 1894 | + return ret; | |
| 1894 | 1895 | } |
| 1895 | 1896 | |
| 1896 | 1897 | static ssize_t modalias_show(struct device *dev, struct device_attribute *a, |
| @@ -2340,7 +2341,9 @@ struct hid_device *hid_allocate_device(void) · 443 unmodified lines | ||
| 2340 | 2341 | |
| 2341 | 2342 | init_waitqueue_head(&hdev->debug_wait); |
| 2342 | 2343 | INIT_LIST_HEAD(&hdev->debug_list); |
| 2344 | + mutex_init(&hdev->debug_list_lock); | |
| 2343 | 2345 | sema_init(&hdev->driver_lock, 1); |
| 2346 | + sema_init(&hdev->driver_input_lock, 1); | |
| 2344 | 2347 | |
| 2345 | 2348 | return hdev; |
| 2346 | 2349 | } |
| @@ -580,17 +580,49 @@ void hid_debug_event(struct hid_device *hdev, char *buf) · 579 unmodified lines | ||
| 580 | 580 | int i; |
| 581 | 581 | struct hid_debug_list *list; |
| 582 | 582 | |
| 583 | + mutex_lock(&hdev->debug_list_lock); | |
| 583 | 584 | list_for_each_entry(list, &hdev->debug_list, node) { |
| 584 | 585 | for (i = 0; i < strlen(buf); i++) |
| 585 | 586 | list->hid_debug_buf[(list->tail + i) % HID_DEBUG_BUFSIZE] = |
| 586 | 587 | buf[i]; |
| 587 | 588 | list->tail = (list->tail + i) % HID_DEBUG_BUFSIZE; |
| 588 | 589 | } |
| 590 | + mutex_unlock(&hdev->debug_list_lock); | |
| 589 | 591 | |
| 590 | 592 | wake_up_interruptible(&hdev->debug_wait); |
| 591 | 593 | } |
| 592 | 594 | EXPORT_SYMBOL_GPL(hid_debug_event); |
| 593 | 595 | |
| 596 | +void hid_dump_report(struct hid_device *hid, int type, u8 *data, | |
| 597 | + int size) | |
| 598 | +{ | |
| 599 | + struct hid_report_enum *report_enum; | |
| 600 | + char *buf; | |
| 601 | + unsigned int i; | |
| 602 | + | |
| 603 | + buf = kmalloc(sizeof(char) * HID_DEBUG_BUFSIZE, GFP_ATOMIC); | |
| 604 | + | |
| 605 | + if (!buf) | |
| 606 | + return; | |
| 607 | + | |
| 608 | + report_enum = hid->report_enum + type; | |
| 609 | + | |
| 610 | + /* dump the report */ | |
| 611 | + snprintf(buf, HID_DEBUG_BUFSIZE - 1, | |
| 612 | + "\nreport (size %u) (%snumbered) = ", size, | |
| 613 | + report_enum->numbered ? "" : "un"); | |
| 614 | + hid_debug_event(hid, buf); | |
| 615 | + | |
| 616 | + for (i = 0; i < size; i++) { | |
| 617 | + snprintf(buf, HID_DEBUG_BUFSIZE - 1, | |
| 618 | + " %02x", data[i]); | |
| 619 | + hid_debug_event(hid, buf); | |
| 620 | + } | |
| 621 | + hid_debug_event(hid, "\n"); | |
| 622 | + kfree(buf); | |
| 623 | +} | |
| 624 | +EXPORT_SYMBOL_GPL(hid_dump_report); | |
| 625 | + | |
| 594 | 626 | void hid_dump_input(struct hid_device *hdev, struct hid_usage *usage, __s32 value) |
| 595 | 627 | { |
| 596 | 628 | char *buf; |
| @@ -960,7 +992,9 @@ static int hid_debug_events_open(struct inode *inode, struct file *file) · 363 unmodified lines | ||
| 960 | 992 | file->private_data = list; |
| 961 | 993 | mutex_init(&list->read_mutex); |
| 962 | 994 | |
| 995 | + mutex_lock(&list->hdev->debug_list_lock); | |
| 963 | 996 | list_add_tail(&list->node, &list->hdev->debug_list); |
| 997 | + mutex_unlock(&list->hdev->debug_list_lock); | |
| 964 | 998 | |
| 965 | 999 | out: |
| 966 | 1000 | return err; |
| @@ -1055,7 +1089,9 @@ static int hid_debug_events_release(struct inode *inode, struct file *file) · 88 unmodified lines | ||
| 1055 | 1089 | { |
| 1056 | 1090 | struct hid_debug_list *list = file->private_data; |
| 1057 | 1091 | |
| 1092 | + mutex_lock(&list->hdev->debug_list_lock); | |
| 1058 | 1093 | list_del(&list->node); |
| 1094 | + mutex_unlock(&list->hdev->debug_list_lock); | |
| 1059 | 1095 | kfree(list->hid_debug_buf); |
| 1060 | 1096 | kfree(list); |
| 1061 | 1097 | |
| @@ -29,14 +29,12 @@ · 28 unmodified lines | ||
| 29 | 29 | |
| 30 | 30 | #include <linux/input.h> |
| 31 | 31 | #include <linux/slab.h> |
| 32 | −#include <linux/usb.h> | |
| 33 | 32 | #include <linux/hid.h> |
| 34 | 33 | #include <linux/module.h> |
| 35 | 34 | |
| 36 | 35 | #include "hid-ids.h" |
| 37 | 36 | |
| 38 | 37 | #ifdef CONFIG_DRAGONRISE_FF |
| 39 | −#include "usbhid/usbhid.h" | |
| 40 | 38 | |
| 41 | 39 | struct drff_device { |
| 42 | 40 | struct hid_report *report; |
| @@ -68,7 +66,7 @@ static int drff_play(struct input_dev *dev, void *data, · 25 unmodified lines | ||
| 68 | 66 | drff->report->field[0]->value[1] = 0x00; |
| 69 | 67 | drff->report->field[0]->value[2] = weak; |
| 70 | 68 | drff->report->field[0]->value[4] = strong; |
| 71 | − usbhid_submit_report(hid, drff->report, USB_DIR_OUT); | |
| 69 | + hid_hw_request(hid, drff->report, HID_REQ_SET_REPORT); | |
| 72 | 70 | |
| 73 | 71 | drff->report->field[0]->value[0] = 0xfa; |
| 74 | 72 | drff->report->field[0]->value[1] = 0xfe; |
| @@ -80,7 +78,7 @@ static int drff_play(struct input_dev *dev, void *data, · 5 unmodified lines | ||
| 80 | 78 | drff->report->field[0]->value[2] = 0x00; |
| 81 | 79 | drff->report->field[0]->value[4] = 0x00; |
| 82 | 80 | dbg_hid("running with 0x%02x 0x%02x", strong, weak); |
| 83 | − usbhid_submit_report(hid, drff->report, USB_DIR_OUT); | |
| 81 | + hid_hw_request(hid, drff->report, HID_REQ_SET_REPORT); | |
| 84 | 82 | |
| 85 | 83 | return 0; |
| 86 | 84 | } |
| @@ -132,7 +130,7 @@ static int drff_init(struct hid_device *hid) · 45 unmodified lines | ||
| 132 | 130 | drff->report->field[0]->value[4] = 0x00; |
| 133 | 131 | drff->report->field[0]->value[5] = 0x00; |
| 134 | 132 | drff->report->field[0]->value[6] = 0x00; |
| 135 | − usbhid_submit_report(hid, drff->report, USB_DIR_OUT); | |
| 133 | + hid_hw_request(hid, drff->report, HID_REQ_SET_REPORT); | |
| 136 | 134 | |
| 137 | 135 | hid_info(hid, "Force Feedback for DragonRise Inc. " |
| 138 | 136 | "game controllers by Richard Walmsley <richwalm@gmail.com>\n"); |
| @@ -23,11 +23,9 @@ · 22 unmodified lines | ||
| 23 | 23 | |
| 24 | 24 | #include <linux/hid.h> |
| 25 | 25 | #include <linux/input.h> |
| 26 | −#include <linux/usb.h> | |
| 27 | 26 | #include <linux/module.h> |
| 28 | 27 | |
| 29 | 28 | #include "hid-ids.h" |
| 30 | −#include "usbhid/usbhid.h" | |
| 31 | 29 | |
| 32 | 30 | struct emsff_device { |
| 33 | 31 | struct hid_report *report; |
| @@ -52,7 +50,7 @@ static int emsff_play(struct input_dev *dev, void *data, · 18 unmodified lines | ||
| 52 | 50 | emsff->report->field[0]->value[2] = strong; |
| 53 | 51 | |
| 54 | 52 | dbg_hid("running with 0x%02x 0x%02x\n", strong, weak); |
| 55 | − usbhid_submit_report(hid, emsff->report, USB_DIR_OUT); | |
| 53 | + hid_hw_request(hid, emsff->report, HID_REQ_SET_REPORT); | |
| 56 | 54 | |
| 57 | 55 | return 0; |
| 58 | 56 | } |
| @@ -104,7 +102,7 @@ static int emsff_init(struct hid_device *hid) · 45 unmodified lines | ||
| 104 | 102 | emsff->report->field[0]->value[4] = 0x00; |
| 105 | 103 | emsff->report->field[0]->value[5] = 0x00; |
| 106 | 104 | emsff->report->field[0]->value[6] = 0x00; |
| 107 | − usbhid_submit_report(hid, emsff->report, USB_DIR_OUT); | |
| 105 | + hid_hw_request(hid, emsff->report, HID_REQ_SET_REPORT); | |
| 108 | 106 | |
| 109 | 107 | hid_info(hid, "force feedback for EMS based devices by Ignaz Forster <ignaz.forster@gmx.de>\n"); |
| 110 | 108 | |
| @@ -29,13 +29,11 @@ · 28 unmodified lines | ||
| 29 | 29 | |
| 30 | 30 | #include <linux/input.h> |
| 31 | 31 | #include <linux/slab.h> |
| 32 | −#include <linux/usb.h> | |
| 33 | 32 | #include <linux/hid.h> |
| 34 | 33 | #include <linux/module.h> |
| 35 | 34 | #include "hid-ids.h" |
| 36 | 35 | |
| 37 | 36 | #ifdef CONFIG_GREENASIA_FF |
| 38 | −#include "usbhid/usbhid.h" | |
| 39 | 37 | |
| 40 | 38 | struct gaff_device { |
| 41 | 39 | struct hid_report *report; |
| @@ -63,14 +61,14 @@ static int hid_gaff_play(struct input_dev *dev, void *data, · 21 unmodified lines | ||
| 63 | 61 | gaff->report->field[0]->value[4] = left; |
| 64 | 62 | gaff->report->field[0]->value[5] = 0; |
| 65 | 63 | dbg_hid("running with 0x%02x 0x%02x", left, right); |
| 66 | − usbhid_submit_report(hid, gaff->report, USB_DIR_OUT); | |
| 64 | + hid_hw_request(hid, gaff->report, HID_REQ_SET_REPORT); | |
| 67 | 65 | |
| 68 | 66 | gaff->report->field[0]->value[0] = 0xfa; |
| 69 | 67 | gaff->report->field[0]->value[1] = 0xfe; |
| 70 | 68 | gaff->report->field[0]->value[2] = 0x0; |
| 71 | 69 | gaff->report->field[0]->value[4] = 0x0; |
| 72 | 70 | |
| 73 | − usbhid_submit_report(hid, gaff->report, USB_DIR_OUT); | |
| 71 | + hid_hw_request(hid, gaff->report, HID_REQ_SET_REPORT); | |
| 74 | 72 | |
| 75 | 73 | return 0; |
| 76 | 74 | } |
| @@ -122,12 +120,12 @@ static int gaff_init(struct hid_device *hid) · 45 unmodified lines | ||
| 122 | 120 | gaff->report->field[0]->value[1] = 0x00; |
| 123 | 121 | gaff->report->field[0]->value[2] = 0x00; |
| 124 | 122 | gaff->report->field[0]->value[3] = 0x00; |
| 125 | − usbhid_submit_report(hid, gaff->report, USB_DIR_OUT); | |
| 123 | + hid_hw_request(hid, gaff->report, HID_REQ_SET_REPORT); | |
| 126 | 124 | |
| 127 | 125 | gaff->report->field[0]->value[0] = 0xfa; |
| 128 | 126 | gaff->report->field[0]->value[1] = 0xfe; |
| 129 | 127 | |
| 130 | − usbhid_submit_report(hid, gaff->report, USB_DIR_OUT); | |
| 128 | + hid_hw_request(hid, gaff->report, HID_REQ_SET_REPORT); | |
| 131 | 129 | |
| 132 | 130 | hid_info(hid, "Force Feedback for GreenAsia 0x12 devices by Lukasz Lubojanski <lukasz@lubojanski.info>\n"); |
| 133 | 131 | |
| @@ -27,12 +27,10 @@ · 26 unmodified lines | ||
| 27 | 27 | #include <linux/input.h> |
| 28 | 28 | #include <linux/module.h> |
| 29 | 29 | #include <linux/slab.h> |
| 30 | −#include <linux/usb.h> | |
| 31 | 30 | |
| 32 | 31 | #include "hid-ids.h" |
| 33 | 32 | |
| 34 | 33 | #ifdef CONFIG_HOLTEK_FF |
| 35 | −#include "usbhid/usbhid.h" | |
| 36 | 34 | |
| 37 | 35 | MODULE_LICENSE("GPL"); |
| 38 | 36 | MODULE_AUTHOR("Anssi Hannula <anssi.hannula@iki.fi>"); |
| @@ -102,7 +100,7 @@ static void holtekff_send(struct holtekff_device *holtekff, · 63 unmodified lines | ||
| 102 | 100 | |
| 103 | 101 | dbg_hid("sending %*ph\n", 7, data); |
| 104 | 102 | |
| 105 | − usbhid_submit_report(hid, holtekff->field->report, USB_DIR_OUT); | |
| 103 | + hid_hw_request(hid, holtekff->field->report, HID_REQ_SET_REPORT); | |
| 106 | 104 | } |
| 107 | 105 | |
| 108 | 106 | static int holtekff_play(struct input_dev *dev, void *data, |
| @@ -159,7 +159,7 @@ static const struct icade_key icade_usage_table[30] = { · 158 unmodified lines | ||
| 159 | 159 | |
| 160 | 160 | static const struct icade_key *icade_find_translation(u16 from) |
| 161 | 161 | { |
| 162 | − if (from < 0 || from > ICADE_MAX_USAGE) | |
| 162 | + if (from > ICADE_MAX_USAGE) | |
| 163 | 163 | return NULL; |
| 164 | 164 | return &icade_usage_table[from]; |
| 165 | 165 | } |
| @@ -137,8 +137,11 @@ · 136 unmodified lines | ||
| 137 | 137 | #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO 0x0256 |
| 138 | 138 | #define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a |
| 139 | 139 | #define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b |
| 140 | −#define USB_DEVICE_ID_APPLE_ATV_IRCONTROL 0x8241 | |
| 140 | +#define USB_DEVICE_ID_APPLE_IRCONTROL 0x8240 | |
| 141 | +#define USB_DEVICE_ID_APPLE_IRCONTROL2 0x1440 | |
| 142 | +#define USB_DEVICE_ID_APPLE_IRCONTROL3 0x8241 | |
| 141 | 143 | #define USB_DEVICE_ID_APPLE_IRCONTROL4 0x8242 |
| 144 | +#define USB_DEVICE_ID_APPLE_IRCONTROL5 0x8243 | |
| 142 | 145 | |
| 143 | 146 | #define USB_VENDOR_ID_ASUS 0x0486 |
| 144 | 147 | #define USB_DEVICE_ID_ASUS_T91MT 0x0185 |
| @@ -577,6 +580,7 @@ · 432 unmodified lines | ||
| 577 | 580 | #define USB_DEVICE_ID_SIDEWINDER_GV 0x003b |
| 578 | 581 | #define USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0 0x009d |
| 579 | 582 | #define USB_DEVICE_ID_MS_NE4K 0x00db |
| 583 | +#define USB_DEVICE_ID_MS_NE4K_JP 0x00dc | |
| 580 | 584 | #define USB_DEVICE_ID_MS_LK6K 0x00f9 |
| 581 | 585 | #define USB_DEVICE_ID_MS_PRESENTER_8K_BT 0x0701 |
| 582 | 586 | #define USB_DEVICE_ID_MS_PRESENTER_8K_USB 0x0713 |
| @@ -613,6 +617,7 @@ · 30 unmodified lines | ||
| 613 | 617 | |
| 614 | 618 | #define USB_VENDOR_ID_NINTENDO 0x057e |
| 615 | 619 | #define USB_DEVICE_ID_NINTENDO_WIIMOTE 0x0306 |
| 620 | +#define USB_DEVICE_ID_NINTENDO_WIIMOTE2 0x0330 | |
| 616 | 621 | |
| 617 | 622 | #define USB_VENDOR_ID_NOVATEK 0x0603 |
| 618 | 623 | #define USB_DEVICE_ID_NOVATEK_PCT 0x0600 |
| @@ -692,8 +697,10 @@ · 73 unmodified lines | ||
| 692 | 697 | #define USB_VENDOR_ID_ROCCAT 0x1e7d |
| 693 | 698 | #define USB_DEVICE_ID_ROCCAT_ARVO 0x30d4 |
| 694 | 699 | #define USB_DEVICE_ID_ROCCAT_ISKU 0x319c |
| 700 | +#define USB_DEVICE_ID_ROCCAT_ISKUFX 0x3264 | |
| 695 | 701 | #define USB_DEVICE_ID_ROCCAT_KONE 0x2ced |
| 696 | 702 | #define USB_DEVICE_ID_ROCCAT_KONEPLUS 0x2d51 |
| 703 | +#define USB_DEVICE_ID_ROCCAT_KONEPURE 0x2dbe | |
| 697 | 704 | #define USB_DEVICE_ID_ROCCAT_KONEXTD 0x2e22 |
| 698 | 705 | #define USB_DEVICE_ID_ROCCAT_KOVAPLUS 0x2d50 |
| 699 | 706 | #define USB_DEVICE_ID_ROCCAT_LUA 0x2c2e |
| @@ -1198,6 +1198,67 @@ static struct hid_input *hidinput_allocate(struct hid_device *hid) · 1197 unmodified lines | ||
| 1198 | 1198 | return hidinput; |
| 1199 | 1199 | } |
| 1200 | 1200 | |
| 1201 | +static bool hidinput_has_been_populated(struct hid_input *hidinput) | |
| 1202 | +{ | |
| 1203 | + int i; | |
| 1204 | + unsigned long r = 0; | |
| 1205 | + | |
| 1206 | + for (i = 0; i < BITS_TO_LONGS(EV_CNT); i++) | |
| 1207 | + r |= hidinput->input->evbit[i]; | |
| 1208 | + | |
| 1209 | + for (i = 0; i < BITS_TO_LONGS(KEY_CNT); i++) | |
| 1210 | + r |= hidinput->input->keybit[i]; | |
| 1211 | + | |
| 1212 | + for (i = 0; i < BITS_TO_LONGS(REL_CNT); i++) | |
| 1213 | + r |= hidinput->input->relbit[i]; | |
| 1214 | + | |
| 1215 | + for (i = 0; i < BITS_TO_LONGS(ABS_CNT); i++) | |
| 1216 | + r |= hidinput->input->absbit[i]; | |
| 1217 | + | |
| 1218 | + for (i = 0; i < BITS_TO_LONGS(MSC_CNT); i++) | |
| 1219 | + r |= hidinput->input->mscbit[i]; | |
| 1220 | + | |
| 1221 | + for (i = 0; i < BITS_TO_LONGS(LED_CNT); i++) | |
| 1222 | + r |= hidinput->input->ledbit[i]; | |
| 1223 | + | |
| 1224 | + for (i = 0; i < BITS_TO_LONGS(SND_CNT); i++) | |
| 1225 | + r |= hidinput->input->sndbit[i]; | |
| 1226 | + | |
| 1227 | + for (i = 0; i < BITS_TO_LONGS(FF_CNT); i++) | |
| 1228 | + r |= hidinput->input->ffbit[i]; | |
| 1229 | + | |
| 1230 | + for (i = 0; i < BITS_TO_LONGS(SW_CNT); i++) | |
| 1231 | + r |= hidinput->input->swbit[i]; | |
| 1232 | + | |
| 1233 | + return !!r; | |
| 1234 | +} | |
| 1235 | + | |
| 1236 | +static void hidinput_cleanup_hidinput(struct hid_device *hid, | |
| 1237 | + struct hid_input *hidinput) | |
| 1238 | +{ | |
| 1239 | + struct hid_report *report; | |
| 1240 | + int i, k; | |
| 1241 | + | |
| 1242 | + list_del(&hidinput->list); | |
| 1243 | + input_free_device(hidinput->input); | |
| 1244 | + | |
| 1245 | + for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) { | |
| 1246 | + if (k == HID_OUTPUT_REPORT && | |
| 1247 | + hid->quirks & HID_QUIRK_SKIP_OUTPUT_REPORTS) | |
| 1248 | + continue; | |
| 1249 | + | |
| 1250 | + list_for_each_entry(report, &hid->report_enum[k].report_list, | |
| 1251 | + list) { | |
| 1252 | + | |
| 1253 | + for (i = 0; i < report->maxfield; i++) | |
| 1254 | + if (report->field[i]->hidinput == hidinput) | |
| 1255 | + report->field[i]->hidinput = NULL; | |
| 1256 | + } | |
| 1257 | + } | |
| 1258 | + | |
| 1259 | + kfree(hidinput); | |
| 1260 | +} | |
| 1261 | + | |
| 1201 | 1262 | /* |
| 1202 | 1263 | * Register the input device; print a message. |
| 1203 | 1264 | * Configure the input layer interface |
| @@ -1249,6 +1310,10 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) · 45 unmodified lines | ||
| 1249 | 1310 | hidinput_configure_usage(hidinput, report->field[i], |
| 1250 | 1311 | report->field[i]->usage + j); |
| 1251 | 1312 | |
| 1313 | + if ((hid->quirks & HID_QUIRK_NO_EMPTY_INPUT) && | |
| 1314 | + !hidinput_has_been_populated(hidinput)) | |
| 1315 | + continue; | |
| 1316 | + | |
| 1252 | 1317 | if (hid->quirks & HID_QUIRK_MULTI_INPUT) { |
| 1253 | 1318 | /* This will leave hidinput NULL, so that it |
| 1254 | 1319 | * allocates another one if we have more inputs on |
| @@ -1265,6 +1330,18 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) · 10 unmodified lines | ||
| 1265 | 1330 | } |
| 1266 | 1331 | } |
| 1267 | 1332 | |
| 1333 | + if (hidinput && (hid->quirks & HID_QUIRK_NO_EMPTY_INPUT) && | |
| 1334 | + !hidinput_has_been_populated(hidinput)) { | |
| 1335 | + /* no need to register an input device not populated */ | |
| 1336 | + hidinput_cleanup_hidinput(hid, hidinput); | |
| 1337 | + hidinput = NULL; | |
| 1338 | + } | |
| 1339 | + | |
| 1340 | + if (list_empty(&hid->inputs)) { | |
| 1341 | + hid_err(hid, "No inputs registered, leaving\n"); | |
| 1342 | + goto out_unwind; | |
| 1343 | + } | |
| 1344 | + | |
| 1268 | 1345 | if (hidinput) { |
| 1269 | 1346 | if (drv->input_configured) |
| 1270 | 1347 | drv->input_configured(hid, hidinput); |
| @@ -16,8 +16,6 @@ · 15 unmodified lines | ||
| 16 | 16 | #include <linux/device.h> |
| 17 | 17 | #include <linux/hid.h> |
| 18 | 18 | #include <linux/module.h> |
| 19 | −#include <linux/usb.h> | |
| 20 | −#include "usbhid/usbhid.h" | |
| 21 | 19 | |
| 22 | 20 | #include "hid-ids.h" |
| 23 | 21 | |
| @@ -361,7 +359,7 @@ static int kye_tablet_enable(struct hid_device *hdev) · 337 unmodified lines | ||
| 361 | 359 | value[4] = 0x00; |
| 362 | 360 | value[5] = 0x00; |
| 363 | 361 | value[6] = 0x00; |
| 364 | − usbhid_submit_report(hdev, report, USB_DIR_OUT); | |
| 362 | + hid_hw_request(hdev, report, HID_REQ_SET_REPORT); | |
| 365 | 363 | |
| 366 | 364 | return 0; |
| 367 | 365 | } |
| @@ -68,7 +68,7 @@ static int tpkbd_features_set(struct hid_device *hdev) · 67 unmodified lines | ||
| 68 | 68 | report->field[2]->value[0] = data_pointer->sensitivity; |
| 69 | 69 | report->field[3]->value[0] = data_pointer->press_speed; |
| 70 | 70 | |
| 71 | − usbhid_submit_report(hdev, report, USB_DIR_OUT); | |
| 71 | + hid_hw_request(hdev, report, HID_REQ_SET_REPORT); | |
| 72 | 72 | return 0; |
| 73 | 73 | } |
| 74 | 74 | |
| @@ -228,8 +228,6 @@ static ssize_t pointer_press_speed_show(struct device *dev, · 153 unmodified lines | ||
| 228 | 228 | struct hid_device *hdev = container_of(dev, struct hid_device, dev); |
| 229 | 229 | struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev); |
| 230 | 230 | |
| 231 | − data_pointer = hid_get_drvdata(hdev); | |
| 232 | − | |
| 233 | 231 | return snprintf(buf, PAGE_SIZE, "%u\n", |
| 234 | 232 | data_pointer->press_speed); |
| 235 | 233 | } |
| @@ -332,7 +330,7 @@ static void tpkbd_led_brightness_set(struct led_classdev *led_cdev, · 96 unmodified lines | ||
| 332 | 330 | report = hdev->report_enum[HID_OUTPUT_REPORT].report_id_hash[3]; |
| 333 | 331 | report->field[0]->value[0] = (data_pointer->led_state >> 0) & 1; |
| 334 | 332 | report->field[0]->value[1] = (data_pointer->led_state >> 1) & 1; |
| 335 | − usbhid_submit_report(hdev, report, USB_DIR_OUT); | |
| 333 | + hid_hw_request(hdev, report, HID_REQ_SET_REPORT); | |
| 336 | 334 | } |
| 337 | 335 | |
| 338 | 336 | static int tpkbd_probe_tp(struct hid_device *hdev) |
| @@ -23,10 +23,8 @@ · 22 unmodified lines | ||
| 23 | 23 | |
| 24 | 24 | #include <linux/input.h> |
| 25 | 25 | #include <linux/slab.h> |
| 26 | −#include <linux/usb.h> | |
| 27 | 26 | #include <linux/hid.h> |
| 28 | 27 | |
| 29 | −#include "usbhid/usbhid.h" | |
| 30 | 28 | #include "hid-lg.h" |
| 31 | 29 | |
| 32 | 30 | struct lg2ff_device { |
| @@ -56,7 +54,7 @@ static int play_effect(struct input_dev *dev, void *data, · 23 unmodified lines | ||
| 56 | 54 | lg2ff->report->field[0]->value[4] = 0x00; |
| 57 | 55 | } |
| 58 | 56 | |
| 59 | − usbhid_submit_report(hid, lg2ff->report, USB_DIR_OUT); | |
| 57 | + hid_hw_request(hid, lg2ff->report, HID_REQ_SET_REPORT); | |
| 60 | 58 | return 0; |
| 61 | 59 | } |
| 62 | 60 | |
| @@ -108,7 +106,7 @@ int lg2ff_init(struct hid_device *hid) · 45 unmodified lines | ||
| 108 | 106 | report->field[0]->value[5] = 0x00; |
| 109 | 107 | report->field[0]->value[6] = 0x00; |
| 110 | 108 | |
| 111 | − usbhid_submit_report(hid, report, USB_DIR_OUT); | |
| 109 | + hid_hw_request(hid, report, HID_REQ_SET_REPORT); | |
| 112 | 110 | |
| 113 | 111 | hid_info(hid, "Force feedback for Logitech RumblePad/Rumblepad 2 by Anssi Hannula <anssi.hannula@gmail.com>\n"); |
| 114 | 112 | |
| @@ -22,10 +22,8 @@ · 21 unmodified lines | ||
| 22 | 22 | |
| 23 | 23 | |
| 24 | 24 | #include <linux/input.h> |
| 25 | −#include <linux/usb.h> | |
| 26 | 25 | #include <linux/hid.h> |
| 27 | 26 | |
| 28 | −#include "usbhid/usbhid.h" | |
| 29 | 27 | #include "hid-lg.h" |
| 30 | 28 | |
| 31 | 29 | /* |
| @@ -92,7 +90,7 @@ static int hid_lg3ff_play(struct input_dev *dev, void *data, · 60 unmodified lines | ||
| 92 | 90 | report->field[0]->value[1] = (unsigned char)(-x); |
| 93 | 91 | report->field[0]->value[31] = (unsigned char)(-y); |
| 94 | 92 | |
| 95 | − usbhid_submit_report(hid, report, USB_DIR_OUT); | |
| 93 | + hid_hw_request(hid, report, HID_REQ_SET_REPORT); | |
| 96 | 94 | break; |
| 97 | 95 | } |
| 98 | 96 | return 0; |
| @@ -118,7 +116,7 @@ static void hid_lg3ff_set_autocenter(struct input_dev *dev, u16 magnitude) · 19 unmodified lines | ||
| 118 | 116 | report->field[0]->value[33] = 0x7F; |
| 119 | 117 | report->field[0]->value[34] = 0x7F; |
| 120 | 118 | |
| 121 | − usbhid_submit_report(hid, report, USB_DIR_OUT); | |
| 119 | + hid_hw_request(hid, report, HID_REQ_SET_REPORT); | |
| 122 | 120 | } |
| 123 | 121 | |
| 124 | 122 | |
| @@ -34,6 +34,7 @@ · 33 unmodified lines | ||
| 34 | 34 | |
| 35 | 35 | #define DFGT_REV_MAJ 0x13 |
| 36 | 36 | #define DFGT_REV_MIN 0x22 |
| 37 | +#define DFGT2_REV_MIN 0x26 | |
| 37 | 38 | #define DFP_REV_MAJ 0x11 |
| 38 | 39 | #define DFP_REV_MIN 0x06 |
| 39 | 40 | #define FFEX_REV_MAJ 0x21 |
| @@ -125,6 +126,7 @@ static const struct lg4ff_native_cmd native_g27 = { · 85 unmodified lines | ||
| 125 | 126 | |
| 126 | 127 | static const struct lg4ff_usb_revision lg4ff_revs[] = { |
| 127 | 128 | {DFGT_REV_MAJ, DFGT_REV_MIN, &native_dfgt}, /* Driving Force GT */ |
| 129 | + {DFGT_REV_MAJ, DFGT2_REV_MIN, &native_dfgt}, /* Driving Force GT v2 */ | |
| 128 | 130 | {DFP_REV_MAJ, DFP_REV_MIN, &native_dfp}, /* Driving Force Pro */ |
| 129 | 131 | {G25_REV_MAJ, G25_REV_MIN, &native_g25}, /* G25 */ |
| 130 | 132 | {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 · 71 unmodified lines | ||
| 202 | 204 | value[5] = 0x00; |
| 203 | 205 | value[6] = 0x00; |
| 204 | 206 | |
| 205 | − usbhid_submit_report(hid, report, USB_DIR_OUT); | |
| 207 | + hid_hw_request(hid, report, HID_REQ_SET_REPORT); | |
| 206 | 208 | break; |
| 207 | 209 | } |
| 208 | 210 | return 0; |
| @@ -225,7 +227,7 @@ static void hid_lg4ff_set_autocenter_default(struct input_dev *dev, u16 magnitud · 16 unmodified lines | ||
| 225 | 227 | value[5] = 0x00; |
| 226 | 228 | value[6] = 0x00; |
| 227 | 229 | |
| 228 | − usbhid_submit_report(hid, report, USB_DIR_OUT); | |
| 230 | + hid_hw_request(hid, report, HID_REQ_SET_REPORT); | |
| 229 | 231 | } |
| 230 | 232 | |
| 231 | 233 | /* 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) · 13 unmodified lines | ||
| 245 | 247 | value[5] = 0x00; |
| 246 | 248 | value[6] = 0x00; |
| 247 | 249 | |
| 248 | − usbhid_submit_report(hid, report, USB_DIR_OUT); | |
| 250 | + hid_hw_request(hid, report, HID_REQ_SET_REPORT); | |
| 249 | 251 | } |
| 250 | 252 | |
| 251 | 253 | /* 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) · 13 unmodified lines | ||
| 265 | 267 | value[5] = 0x00; |
| 266 | 268 | value[6] = 0x00; |
| 267 | 269 | |
| 268 | − usbhid_submit_report(hid, report, USB_DIR_OUT); | |
| 270 | + hid_hw_request(hid, report, HID_REQ_SET_REPORT); | |
| 269 | 271 | } |
| 270 | 272 | |
| 271 | 273 | /* 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) · 22 unmodified lines | ||
| 294 | 296 | report->field[0]->value[1] = 0x02; |
| 295 | 297 | full_range = 200; |
| 296 | 298 | } |
| 297 | − usbhid_submit_report(hid, report, USB_DIR_OUT); | |
| 299 | + hid_hw_request(hid, report, HID_REQ_SET_REPORT); | |
| 298 | 300 | |
| 299 | 301 | /* Prepare "fine" limit command */ |
| 300 | 302 | value[0] = 0x81; |
| @@ -306,7 +308,7 @@ static void hid_lg4ff_set_range_dfp(struct hid_device *hid, __u16 range) · 5 unmodified lines | ||
| 306 | 308 | value[6] = 0x00; |
| 307 | 309 | |
| 308 | 310 | if (range == 200 || range == 900) { /* Do not apply any fine limit */ |
| 309 | − usbhid_submit_report(hid, report, USB_DIR_OUT); | |
| 311 | + hid_hw_request(hid, report, HID_REQ_SET_REPORT); | |
| 310 | 312 | return; |
| 311 | 313 | } |
| 312 | 314 | |
| @@ -320,7 +322,7 @@ static void hid_lg4ff_set_range_dfp(struct hid_device *hid, __u16 range) · 7 unmodified lines | ||
| 320 | 322 | value[5] = (start_right & 0xe) << 4 | (start_left & 0xe); |
| 321 | 323 | value[6] = 0xff; |
| 322 | 324 | |
| 323 | − usbhid_submit_report(hid, report, USB_DIR_OUT); | |
| 325 | + hid_hw_request(hid, report, HID_REQ_SET_REPORT); | |
| 324 | 326 | } |
| 325 | 327 | |
| 326 | 328 | 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 · 7 unmodified lines | ||
| 334 | 336 | for (i = 0; i < 7; i++) |
| 335 | 337 | report->field[0]->value[i] = cmd->cmd[j++]; |
| 336 | 338 | |
| 337 | − usbhid_submit_report(hid, report, USB_DIR_OUT); | |
| 339 | + hid_hw_request(hid, report, HID_REQ_SET_REPORT); | |
| 338 | 340 | } |
| 339 | 341 | } |
| 340 | 342 | |
| @@ -410,7 +412,7 @@ static void lg4ff_set_leds(struct hid_device *hid, __u8 leds) · 69 unmodified lines | ||
| 410 | 412 | value[4] = 0x00; |
| 411 | 413 | value[5] = 0x00; |
| 412 | 414 | value[6] = 0x00; |
| 413 | − usbhid_submit_report(hid, report, USB_DIR_OUT); | |
| 415 | + hid_hw_request(hid, report, HID_REQ_SET_REPORT); | |
| 414 | 416 | } |
| 415 | 417 | |
| 416 | 418 | static void lg4ff_led_set_brightness(struct led_classdev *led_cdev, |
| @@ -30,10 +30,8 @@ · 29 unmodified lines | ||
| 30 | 30 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
| 31 | 31 | |
| 32 | 32 | #include <linux/input.h> |
| 33 | −#include <linux/usb.h> | |
| 34 | 33 | #include <linux/hid.h> |
| 35 | 34 | |
| 36 | −#include "usbhid/usbhid.h" | |
| 37 | 35 | #include "hid-lg.h" |
| 38 | 36 | |
| 39 | 37 | struct dev_type { |
| @@ -89,7 +87,7 @@ static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *ef · 49 unmodified lines | ||
| 89 | 87 | report->field[0]->value[2] = x; |
| 90 | 88 | report->field[0]->value[3] = y; |
| 91 | 89 | dbg_hid("(x, y)=(%04x, %04x)\n", x, y); |
| 92 | − usbhid_submit_report(hid, report, USB_DIR_OUT); | |
| 90 | + hid_hw_request(hid, report, HID_REQ_SET_REPORT); | |
| 93 | 91 | break; |
| 94 | 92 | |
| 95 | 93 | case FF_RUMBLE: |
| @@ -104,7 +102,7 @@ static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *ef · 8 unmodified lines | ||
| 104 | 102 | report->field[0]->value[2] = left; |
| 105 | 103 | report->field[0]->value[3] = right; |
| 106 | 104 | dbg_hid("(left, right)=(%04x, %04x)\n", left, right); |
| 107 | − usbhid_submit_report(hid, report, USB_DIR_OUT); | |
| 105 | + hid_hw_request(hid, report, HID_REQ_SET_REPORT); | |
| 108 | 106 | break; |
| 109 | 107 | } |
| 110 | 108 | return 0; |
| @@ -124,7 +122,7 @@ static void hid_lgff_set_autocenter(struct input_dev *dev, u16 magnitude) · 13 unmodified lines | ||
| 124 | 122 | *value++ = 0x80; |
| 125 | 123 | *value++ = 0x00; |
| 126 | 124 | *value = 0x00; |
| 127 | − usbhid_submit_report(hid, report, USB_DIR_OUT); | |
| 125 | + hid_hw_request(hid, report, HID_REQ_SET_REPORT); | |
| 128 | 126 | } |
| 129 | 127 | |
| 130 | 128 | int lgff_init(struct hid_device* hid) |
| @@ -27,7 +27,6 @@ · 26 unmodified lines | ||
| 27 | 27 | #include <linux/module.h> |
| 28 | 28 | #include <linux/usb.h> |
| 29 | 29 | #include <asm/unaligned.h> |
| 30 | −#include "usbhid/usbhid.h" | |
| 31 | 30 | #include "hid-ids.h" |
| 32 | 31 | #include "hid-logitech-dj.h" |
| 33 | 32 | |
| @@ -193,7 +192,6 @@ static struct hid_ll_driver logi_dj_ll_driver; · 159 unmodified lines | ||
| 193 | 192 | static int logi_dj_output_hidraw_report(struct hid_device *hid, u8 * buf, |
| 194 | 193 | size_t count, |
| 195 | 194 | unsigned char report_type); |
| 196 | −static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev); | |
| 197 | 195 | |
| 198 | 196 | static void logi_dj_recv_destroy_djhid_device(struct dj_receiver_dev *djrcv_dev, |
| 199 | 197 | struct dj_report *dj_report) |
| @@ -234,7 +232,6 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev, · 34 unmodified lines | ||
| 234 | 232 | if (dj_report->report_params[DEVICE_PAIRED_PARAM_SPFUNCTION] & |
| 235 | 233 | SPFUNCTION_DEVICE_LIST_EMPTY) { |
| 236 | 234 | dbg_hid("%s: device list is empty\n", __func__); |
| 237 | − djrcv_dev->querying_devices = false; | |
| 238 | 235 | return; |
| 239 | 236 | } |
| 240 | 237 | |
| @@ -245,12 +242,6 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev, · 4 unmodified lines | ||
| 245 | 242 | return; |
| 246 | 243 | } |
| 247 | 244 | |
| 248 | − if (djrcv_dev->paired_dj_devices[dj_report->device_index]) { | |
| 249 | − /* The device is already known. No need to reallocate it. */ | |
| 250 | − dbg_hid("%s: device is already known\n", __func__); | |
| 251 | − return; | |
| 252 | − } | |
| 253 | − | |
| 254 | 245 | dj_hiddev = hid_allocate_device(); |
| 255 | 246 | if (IS_ERR(dj_hiddev)) { |
| 256 | 247 | dev_err(&djrcv_hdev->dev, "%s: hid_allocate_device failed\n", |
| @@ -314,7 +305,6 @@ static void delayedwork_callback(struct work_struct *work) · 57 unmodified lines | ||
| 314 | 305 | struct dj_report dj_report; |
| 315 | 306 | unsigned long flags; |
| 316 | 307 | int count; |
| 317 | − int retval; | |
| 318 | 308 | |
| 319 | 309 | dbg_hid("%s\n", __func__); |
| 320 | 310 | |
| @@ -347,25 +337,6 @@ static void delayedwork_callback(struct work_struct *work) · 26 unmodified lines | ||
| 347 | 337 | logi_dj_recv_destroy_djhid_device(djrcv_dev, &dj_report); |
| 348 | 338 | break; |
| 349 | 339 | default: |
| 350 | − /* A normal report (i. e. not belonging to a pair/unpair notification) | |
| 351 | − * arriving here, means that the report arrived but we did not have a | |
| 352 | − * paired dj_device associated to the report's device_index, this | |
| 353 | − * means that the original "device paired" notification corresponding | |
| 354 | − * to this dj_device never arrived to this driver. The reason is that | |
| 355 | − * hid-core discards all packets coming from a device while probe() is | |
| 356 | − * executing. */ | |
| 357 | − if (!djrcv_dev->paired_dj_devices[dj_report.device_index]) { | |
| 358 | − /* ok, we don't know the device, just re-ask the | |
| 359 | − * receiver for the list of connected devices. */ | |
| 360 | − retval = logi_dj_recv_query_paired_devices(djrcv_dev); | |
| 361 | − if (!retval) { | |
| 362 | − /* everything went fine, so just leave */ | |
| 363 | − break; | |
| 364 | − } | |
| 365 | − dev_err(&djrcv_dev->hdev->dev, | |
| 366 | − "%s:logi_dj_recv_query_paired_devices " | |
| 367 | − "error:%d\n", __func__, retval); | |
| 368 | − } | |
| 369 | 340 | dbg_hid("%s: unexpected report type\n", __func__); |
| 370 | 341 | } |
| 371 | 342 | } |
| @@ -396,12 +367,6 @@ static void logi_dj_recv_forward_null_report(struct dj_receiver_dev *djrcv_dev, · 24 unmodified lines | ||
| 396 | 367 | if (!djdev) { |
| 397 | 368 | dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]" |
| 398 | 369 | " is NULL, index %d\n", dj_report->device_index); |
| 399 | − kfifo_in(&djrcv_dev->notif_fifo, dj_report, sizeof(struct dj_report)); | |
| 400 | − | |
| 401 | − if (schedule_work(&djrcv_dev->work) == 0) { | |
| 402 | − dbg_hid("%s: did not schedule the work item, was already " | |
| 403 | − "queued\n", __func__); | |
| 404 | − } | |
| 405 | 370 | return; |
| 406 | 371 | } |
| 407 | 372 | |
| @@ -432,12 +397,6 @@ static void logi_dj_recv_forward_report(struct dj_receiver_dev *djrcv_dev, · 24 unmodified lines | ||
| 432 | 397 | if (dj_device == NULL) { |
| 433 | 398 | dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]" |
| 434 | 399 | " is NULL, index %d\n", dj_report->device_index); |
| 435 | − kfifo_in(&djrcv_dev->notif_fifo, dj_report, sizeof(struct dj_report)); | |
| 436 | − | |
| 437 | − if (schedule_work(&djrcv_dev->work) == 0) { | |
| 438 | − dbg_hid("%s: did not schedule the work item, was already " | |
| 439 | − "queued\n", __func__); | |
| 440 | − } | |
| 441 | 400 | return; |
| 442 | 401 | } |
| 443 | 402 | |
| @@ -475,7 +434,7 @@ static int logi_dj_recv_send_report(struct dj_receiver_dev *djrcv_dev, · 31 unmodified lines | ||
| 475 | 434 | for (i = 0; i < report->field[0]->report_count; i++) |
| 476 | 435 | report->field[0]->value[i] = data[i]; |
| 477 | 436 | |
| 478 | − usbhid_submit_report(hdev, report, USB_DIR_OUT); | |
| 437 | + hid_hw_request(hdev, report, HID_REQ_SET_REPORT); | |
| 479 | 438 | |
| 480 | 439 | return 0; |
| 481 | 440 | } |
| @@ -485,10 +444,6 @@ static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev) · 3 unmodified lines | ||
| 485 | 444 | struct dj_report *dj_report; |
| 486 | 445 | int retval; |
| 487 | 446 | |
| 488 | − /* no need to protect djrcv_dev->querying_devices */ | |
| 489 | − if (djrcv_dev->querying_devices) | |
| 490 | − return 0; | |
| 491 | − | |
| 492 | 447 | dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL); |
| 493 | 448 | if (!dj_report) |
| 494 | 449 | return -ENOMEM; |
| @@ -500,7 +455,6 @@ static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev) · 5 unmodified lines | ||
| 500 | 455 | return retval; |
| 501 | 456 | } |
| 502 | 457 | |
| 503 | − | |
| 504 | 458 | static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev, |
| 505 | 459 | unsigned timeout) |
| 506 | 460 | { |
| @@ -644,7 +598,7 @@ static int logi_dj_ll_input_event(struct input_dev *dev, unsigned int type, · 137 unmodified lines | ||
| 644 | 598 | hid_set_field(report->field[0], 1, REPORT_TYPE_LEDS); |
| 645 | 599 | hid_set_field(report->field[0], 2, data[1]); |
| 646 | 600 | |
| 647 | − usbhid_submit_report(dj_rcv_hiddev, report, USB_DIR_OUT); | |
| 601 | + hid_hw_request(dj_rcv_hiddev, report, HID_REQ_SET_REPORT); | |
| 648 | 602 | |
| 649 | 603 | return 0; |
| 650 | 604 | |
| @@ -809,6 +763,9 @@ static int logi_dj_probe(struct hid_device *hdev, · 158 unmodified lines | ||
| 809 | 763 | goto llopen_failed; |
| 810 | 764 | } |
| 811 | 765 | |
| 766 | + /* Allow incoming packets to arrive: */ | |
| 767 | + hid_device_io_start(hdev); | |
| 768 | + | |
| 812 | 769 | retval = logi_dj_recv_query_paired_devices(djrcv_dev); |
| 813 | 770 | if (retval < 0) { |
| 814 | 771 | dev_err(&hdev->dev, "%s:logi_dj_recv_query_paired_devices " |
| @@ -101,7 +101,6 @@ struct dj_receiver_dev { · 100 unmodified lines | ||
| 101 | 101 | struct work_struct work; |
| 102 | 102 | struct kfifo notif_fifo; |
| 103 | 103 | spinlock_t lock; |
| 104 | − bool querying_devices; | |
| 105 | 104 | }; |
| 106 | 105 | |
| 107 | 106 | struct dj_device { |
| @@ -19,7 +19,6 @@ · 18 unmodified lines | ||
| 19 | 19 | #include <linux/input/mt.h> |
| 20 | 20 | #include <linux/module.h> |
| 21 | 21 | #include <linux/slab.h> |
| 22 | −#include <linux/usb.h> | |
| 23 | 22 | |
| 24 | 23 | #include "hid-ids.h" |
| 25 | 24 | |
| @@ -195,6 +195,8 @@ static const struct hid_device_id ms_devices[] = { · 194 unmodified lines | ||
| 195 | 195 | .driver_data = MS_HIDINPUT }, |
| 196 | 196 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K), |
| 197 | 197 | .driver_data = MS_ERGONOMY }, |
| 198 | + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K_JP), | |
| 199 | + .driver_data = MS_ERGONOMY }, | |
| 198 | 200 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_LK6K), |
| 199 | 201 | .driver_data = MS_ERGONOMY | MS_RDESC }, |
| 200 | 202 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB), |
| @@ -2,8 +2,9 @@ · 1 unmodified line | ||
| 2 | 2 | * HID driver for multitouch panels |
| 3 | 3 | * |
| 4 | 4 | * Copyright (c) 2010-2012 Stephane Chatty <chatty@enac.fr> |
| 5 | − * Copyright (c) 2010-2012 Benjamin Tissoires <benjamin.tissoires@gmail.com> | |
| 5 | + * Copyright (c) 2010-2013 Benjamin Tissoires <benjamin.tissoires@gmail.com> | |
| 6 | 6 | * Copyright (c) 2010-2012 Ecole Nationale de l'Aviation Civile, France |
| 7 | + * Copyright (c) 2012-2013 Red Hat, Inc | |
| 7 | 8 | * |
| 8 | 9 | * This code is partly based on hid-egalax.c: |
| 9 | 10 | * |
| @@ -26,13 +27,24 @@ · 16 unmodified lines | ||
| 26 | 27 | * any later version. |
| 27 | 28 | */ |
| 28 | 29 | |
| 30 | +/* | |
| 31 | + * This driver is regularly tested thanks to the tool hid-test[1]. | |
| 32 | + * This tool relies on hid-replay[2] and a database of hid devices[3]. | |
| 33 | + * Please run these regression tests before patching this module so that | |
| 34 | + * your patch won't break existing known devices. | |
| 35 | + * | |
| 36 | + * [1] https://github.com/bentiss/hid-test | |
| 37 | + * [2] https://github.com/bentiss/hid-replay | |
| 38 | + * [3] https://github.com/bentiss/hid-devices | |
| 39 | + */ | |
| 40 | + | |
| 29 | 41 | #include <linux/device.h> |
| 30 | 42 | #include <linux/hid.h> |
| 31 | 43 | #include <linux/module.h> |
| 32 | 44 | #include <linux/slab.h> |
| 33 | 45 | #include <linux/usb.h> |
| 34 | 46 | #include <linux/input/mt.h> |
| 35 | −#include "usbhid/usbhid.h" | |
| 47 | +#include <linux/string.h> | |
| 36 | 48 | |
| 37 | 49 | |
| 38 | 50 | MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>"); |
| @@ -86,9 +98,9 @@ struct mt_device { · 47 unmodified lines | ||
| 86 | 98 | multitouch fields */ |
| 87 | 99 | int cc_index; /* contact count field index in the report */ |
| 88 | 100 | int cc_value_index; /* contact count value index in the field */ |
| 89 | − unsigned last_field_index; /* last field index of the report */ | |
| 90 | 101 | unsigned last_slot_field; /* the last field of a slot */ |
| 91 | 102 | unsigned mt_report_id; /* the report ID of the multitouch device */ |
| 103 | + unsigned pen_report_id; /* the report ID of the pen device */ | |
| 92 | 104 | __s8 inputmode; /* InputMode HID feature, -1 if non-existent */ |
| 93 | 105 | __s8 inputmode_index; /* InputMode HID feature index in the report */ |
| 94 | 106 | __s8 maxcontact_report_id; /* Maximum Contact Number HID feature, |
| @@ -104,6 +116,9 @@ struct mt_device { · 9 unmodified lines | ||
| 104 | 116 | unsigned mt_flags; /* flags to pass to input-mt */ |
| 105 | 117 | }; |
| 106 | 118 | |
| 119 | +static void mt_post_parse_default_settings(struct mt_device *td); | |
| 120 | +static void mt_post_parse(struct mt_device *td); | |
| 121 | + | |
| 107 | 122 | /* classes of device behavior */ |
| 108 | 123 | #define MT_CLS_DEFAULT 0x0001 |
| 109 | 124 | |
| @@ -246,6 +261,14 @@ static struct mt_class mt_classes[] = { · 136 unmodified lines | ||
| 246 | 261 | { } |
| 247 | 262 | }; |
| 248 | 263 | |
| 264 | +static void mt_free_input_name(struct hid_input *hi) | |
| 265 | +{ | |
| 266 | + struct hid_device *hdev = hi->report->device; | |
| 267 | + | |
| 268 | + if (hi->input->name != hdev->name) | |
| 269 | + kfree(hi->input->name); | |
| 270 | +} | |
| 271 | + | |
| 249 | 272 | static ssize_t mt_show_quirks(struct device *dev, |
| 250 | 273 | struct device_attribute *attr, |
| 251 | 274 | char *buf) |
| @@ -354,7 +377,53 @@ static void mt_store_field(struct hid_usage *usage, struct mt_device *td, · 102 unmodified lines | ||
| 354 | 377 | f->usages[f->length++] = usage->hid; |
| 355 | 378 | } |
| 356 | 379 | |
| 357 | −static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |
| 380 | +static int mt_pen_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |
| 381 | + struct hid_field *field, struct hid_usage *usage, | |
| 382 | + unsigned long **bit, int *max) | |
| 383 | +{ | |
| 384 | + struct mt_device *td = hid_get_drvdata(hdev); | |
| 385 | + | |
| 386 | + td->pen_report_id = field->report->id; | |
| 387 | + | |
| 388 | + return 0; | |
| 389 | +} | |
| 390 | + | |
| 391 | +static int mt_pen_input_mapped(struct hid_device *hdev, struct hid_input *hi, | |
| 392 | + struct hid_field *field, struct hid_usage *usage, | |
| 393 | + unsigned long **bit, int *max) | |
| 394 | +{ | |
| 395 | + return 0; | |
| 396 | +} | |
| 397 | + | |
| 398 | +static int mt_pen_event(struct hid_device *hid, struct hid_field *field, | |
| 399 | + struct hid_usage *usage, __s32 value) | |
| 400 | +{ | |
| 401 | + /* let hid-input handle it */ | |
| 402 | + return 0; | |
| 403 | +} | |
| 404 | + | |
| 405 | +static void mt_pen_report(struct hid_device *hid, struct hid_report *report) | |
| 406 | +{ | |
| 407 | + struct hid_field *field = report->field[0]; | |
| 408 | + | |
| 409 | + input_sync(field->hidinput->input); | |
| 410 | +} | |
| 411 | + | |
| 412 | +static void mt_pen_input_configured(struct hid_device *hdev, | |
| 413 | + struct hid_input *hi) | |
| 414 | +{ | |
| 415 | + char *name = kzalloc(strlen(hi->input->name) + 5, GFP_KERNEL); | |
| 416 | + if (name) { | |
| 417 | + sprintf(name, "%s Pen", hi->input->name); | |
| 418 | + mt_free_input_name(hi); | |
| 419 | + hi->input->name = name; | |
| 420 | + } | |
| 421 | + | |
| 422 | + /* force BTN_STYLUS to allow tablet matching in udev */ | |
| 423 | + __set_bit(BTN_STYLUS, hi->input->keybit); | |
| 424 | +} | |
| 425 | + | |
| 426 | +static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |
| 358 | 427 | struct hid_field *field, struct hid_usage *usage, |
| 359 | 428 | unsigned long **bit, int *max) |
| 360 | 429 | { |
| @@ -363,13 +432,8 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, · 2 unmodified lines | ||
| 363 | 432 | int code; |
| 364 | 433 | struct hid_usage *prev_usage = NULL; |
| 365 | 434 | |
| 366 | − /* Only map fields from TouchScreen or TouchPad collections. | |
| 367 | − * We need to ignore fields that belong to other collections | |
| 368 | − * such as Mouse that might have the same GenericDesktop usages. */ | |
| 369 | 435 | if (field->application == HID_DG_TOUCHSCREEN) |
| 370 | 436 | td->mt_flags |= INPUT_MT_DIRECT; |
| 371 | − else if (field->application != HID_DG_TOUCHPAD) | |
| 372 | − return 0; | |
| 373 | 437 | |
| 374 | 438 | /* |
| 375 | 439 | * Model touchscreens providing buttons as touchpads. |
| @@ -378,12 +442,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, · 2 unmodified lines | ||
| 378 | 442 | (usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON) |
| 379 | 443 | td->mt_flags |= INPUT_MT_POINTER; |
| 380 | 444 | |
| 381 | − /* eGalax devices provide a Digitizer.Stylus input which overrides | |
| 382 | − * the correct Digitizers.Finger X/Y ranges. | |
| 383 | − * Let's just ignore this input. */ | |
| 384 | − if (field->physical == HID_DG_STYLUS) | |
| 385 | − return -1; | |
| 386 | − | |
| 387 | 445 | if (usage->usage_index) |
| 388 | 446 | prev_usage = &field->usage[usage->usage_index - 1]; |
| 389 | 447 | |
| @@ -405,7 +463,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, · 15 unmodified lines | ||
| 405 | 463 | } |
| 406 | 464 | |
| 407 | 465 | mt_store_field(usage, td, hi); |
| 408 | − td->last_field_index = field->index; | |
| 409 | 466 | return 1; |
| 410 | 467 | case HID_GD_Y: |
| 411 | 468 | 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, · 9 unmodified lines | ||
| 421 | 478 | } |
| 422 | 479 | |
| 423 | 480 | mt_store_field(usage, td, hi); |
| 424 | − td->last_field_index = field->index; | |
| 425 | 481 | return 1; |
| 426 | 482 | } |
| 427 | 483 | return 0; |
| @@ -436,21 +492,17 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, · 8 unmodified lines | ||
| 436 | 492 | ABS_MT_DISTANCE, 0, 1, 0, 0); |
| 437 | 493 | } |
| 438 | 494 | mt_store_field(usage, td, hi); |
| 439 | − td->last_field_index = field->index; | |
| 440 | 495 | return 1; |
| 441 | 496 | case HID_DG_CONFIDENCE: |
| 442 | 497 | mt_store_field(usage, td, hi); |
| 443 | − td->last_field_index = field->index; | |
| 444 | 498 | return 1; |
| 445 | 499 | case HID_DG_TIPSWITCH: |
| 446 | 500 | hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); |
| 447 | 501 | input_set_capability(hi->input, EV_KEY, BTN_TOUCH); |
| 448 | 502 | mt_store_field(usage, td, hi); |
| 449 | − td->last_field_index = field->index; | |
| 450 | 503 | return 1; |
| 451 | 504 | case HID_DG_CONTACTID: |
| 452 | 505 | mt_store_field(usage, td, hi); |
| 453 | − td->last_field_index = field->index; | |
| 454 | 506 | td->touches_by_report++; |
| 455 | 507 | td->mt_report_id = field->report->id; |
| 456 | 508 | return 1; |
| @@ -461,7 +513,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, · 4 unmodified lines | ||
| 461 | 513 | set_abs(hi->input, ABS_MT_TOUCH_MAJOR, field, |
| 462 | 514 | cls->sn_width); |
| 463 | 515 | mt_store_field(usage, td, hi); |
| 464 | − td->last_field_index = field->index; | |
| 465 | 516 | return 1; |
| 466 | 517 | case HID_DG_HEIGHT: |
| 467 | 518 | hid_map_usage(hi, usage, bit, max, |
| @@ -473,7 +524,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, · 5 unmodified lines | ||
| 473 | 524 | ABS_MT_ORIENTATION, 0, 1, 0, 0); |
| 474 | 525 | } |
| 475 | 526 | mt_store_field(usage, td, hi); |
| 476 | − td->last_field_index = field->index; | |
| 477 | 527 | return 1; |
| 478 | 528 | case HID_DG_TIPPRESSURE: |
| 479 | 529 | hid_map_usage(hi, usage, bit, max, |
| @@ -481,17 +531,14 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, · 1 unmodified line | ||
| 481 | 531 | set_abs(hi->input, ABS_MT_PRESSURE, field, |
| 482 | 532 | cls->sn_pressure); |
| 483 | 533 | mt_store_field(usage, td, hi); |
| 484 | − td->last_field_index = field->index; | |
| 485 | 534 | return 1; |
| 486 | 535 | case HID_DG_CONTACTCOUNT: |
| 487 | 536 | td->cc_index = field->index; |
| 488 | 537 | td->cc_value_index = usage->usage_index; |
| 489 | − td->last_field_index = field->index; | |
| 490 | 538 | return 1; |
| 491 | 539 | case HID_DG_CONTACTMAX: |
| 492 | 540 | /* we don't set td->last_slot_field as contactcount and |
| 493 | 541 | * contact max are global to the report */ |
| 494 | − td->last_field_index = field->index; | |
| 495 | 542 | return -1; |
| 496 | 543 | case HID_DG_TOUCH: |
| 497 | 544 | /* Legacy devices use TIPSWITCH and not TOUCH. |
| @@ -515,7 +562,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, · 17 unmodified lines | ||
| 515 | 562 | return 0; |
| 516 | 563 | } |
| 517 | 564 | |
| 518 | −static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi, | |
| 565 | +static int mt_touch_input_mapped(struct hid_device *hdev, struct hid_input *hi, | |
| 519 | 566 | struct hid_field *field, struct hid_usage *usage, |
| 520 | 567 | unsigned long **bit, int *max) |
| 521 | 568 | { |
| @@ -606,7 +653,7 @@ static void mt_sync_frame(struct mt_device *td, struct input_dev *input) · 84 unmodified lines | ||
| 606 | 653 | td->num_received = 0; |
| 607 | 654 | } |
| 608 | 655 | |
| 609 | −static int mt_event(struct hid_device *hid, struct hid_field *field, | |
| 656 | +static int mt_touch_event(struct hid_device *hid, struct hid_field *field, | |
| 610 | 657 | struct hid_usage *usage, __s32 value) |
| 611 | 658 | { |
| 612 | 659 | /* 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, · 67 unmodified lines | ||
| 680 | 727 | if (usage->usage_index + 1 == field->report_count) { |
| 681 | 728 | /* we only take into account the last report. */ |
| 682 | 729 | if (usage->hid == td->last_slot_field) |
| 683 | − mt_complete_slot(td, input); | |
| 684 | − | |
| 685 | − if (field->index == td->last_field_index | |
| 686 | − && td->num_received >= td->num_expected) | |
| 687 | − mt_sync_frame(td, field->hidinput->input); | |
| 730 | + mt_complete_slot(td, field->hidinput->input); | |
| 688 | 731 | } |
| 689 | 732 | |
| 690 | 733 | } |
| 691 | 734 | } |
| 692 | 735 | |
| 693 | −static void mt_report(struct hid_device *hid, struct hid_report *report) | |
| 736 | +static void mt_touch_report(struct hid_device *hid, struct hid_report *report) | |
| 694 | 737 | { |
| 695 | 738 | struct mt_device *td = hid_get_drvdata(hid); |
| 696 | 739 | struct hid_field *field; |
| 697 | 740 | unsigned count; |
| 698 | 741 | int r, n; |
| 699 | 742 | |
| 700 | − if (report->id != td->mt_report_id) | |
| 701 | − return; | |
| 702 | − | |
| 703 | − if (!(hid->claimed & HID_CLAIMED_INPUT)) | |
| 704 | − return; | |
| 705 | − | |
| 706 | 743 | /* |
| 707 | 744 | * Includes multi-packet support where subsequent |
| 708 | 745 | * packets are sent with zero contactcount. |
| @@ -725,6 +762,91 @@ static void mt_report(struct hid_device *hid, struct hid_report *report) · 16 unmodified lines | ||
| 725 | 762 | mt_process_mt_event(hid, field, &field->usage[n], |
| 726 | 763 | field->value[n]); |
| 727 | 764 | } |
| 765 | + | |
| 766 | + if (td->num_received >= td->num_expected) | |
| 767 | + mt_sync_frame(td, report->field[0]->hidinput->input); | |
| 768 | +} | |
| 769 | + | |
| 770 | +static void mt_touch_input_configured(struct hid_device *hdev, | |
| 771 | + struct hid_input *hi) | |
| 772 | +{ | |
| 773 | + struct mt_device *td = hid_get_drvdata(hdev); | |
| 774 | + struct mt_class *cls = &td->mtclass; | |
| 775 | + struct input_dev *input = hi->input; | |
| 776 | + | |
| 777 | + if (!td->maxcontacts) | |
| 778 | + td->maxcontacts = MT_DEFAULT_MAXCONTACT; | |
| 779 | + | |
| 780 | + mt_post_parse(td); | |
| 781 | + if (td->serial_maybe) | |
| 782 | + mt_post_parse_default_settings(td); | |
| 783 | + | |
| 784 | + if (cls->is_indirect) | |
| 785 | + td->mt_flags |= INPUT_MT_POINTER; | |
| 786 | + | |
| 787 | + if (cls->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP) | |
| 788 | + td->mt_flags |= INPUT_MT_DROP_UNUSED; | |
| 789 | + | |
| 790 | + input_mt_init_slots(input, td->maxcontacts, td->mt_flags); | |
| 791 | + | |
| 792 | + td->mt_flags = 0; | |
| 793 | +} | |
| 794 | + | |
| 795 | +static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |
| 796 | + struct hid_field *field, struct hid_usage *usage, | |
| 797 | + unsigned long **bit, int *max) | |
| 798 | +{ | |
| 799 | + /* Only map fields from TouchScreen or TouchPad collections. | |
| 800 | + * We need to ignore fields that belong to other collections | |
| 801 | + * such as Mouse that might have the same GenericDesktop usages. */ | |
| 802 | + if (field->application != HID_DG_TOUCHSCREEN && | |
| 803 | + field->application != HID_DG_PEN && | |
| 804 | + field->application != HID_DG_TOUCHPAD) | |
| 805 | + return -1; | |
| 806 | + | |
| 807 | + if (field->physical == HID_DG_STYLUS) | |
| 808 | + return mt_pen_input_mapping(hdev, hi, field, usage, bit, max); | |
| 809 | + | |
| 810 | + return mt_touch_input_mapping(hdev, hi, field, usage, bit, max); | |
| 811 | +} | |
| 812 | + | |
| 813 | +static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi, | |
| 814 | + struct hid_field *field, struct hid_usage *usage, | |
| 815 | + unsigned long **bit, int *max) | |
| 816 | +{ | |
| 817 | + if (field->physical == HID_DG_STYLUS) | |
| 818 | + return mt_pen_input_mapped(hdev, hi, field, usage, bit, max); | |
| 819 | + | |
| 820 | + return mt_touch_input_mapped(hdev, hi, field, usage, bit, max); | |
| 821 | +} | |
| 822 | + | |
| 823 | +static int mt_event(struct hid_device *hid, struct hid_field *field, | |
| 824 | + struct hid_usage *usage, __s32 value) | |
| 825 | +{ | |
| 826 | + struct mt_device *td = hid_get_drvdata(hid); | |
| 827 | + | |
| 828 | + if (field->report->id == td->mt_report_id) | |
| 829 | + return mt_touch_event(hid, field, usage, value); | |
| 830 | + | |
| 831 | + if (field->report->id == td->pen_report_id) | |
| 832 | + return mt_pen_event(hid, field, usage, value); | |
| 833 | + | |
| 834 | + /* ignore other reports */ | |
| 835 | + return 1; | |
| 836 | +} | |
| 837 | + | |
| 838 | +static void mt_report(struct hid_device *hid, struct hid_report *report) | |
| 839 | +{ | |
| 840 | + struct mt_device *td = hid_get_drvdata(hid); | |
| 841 | + | |
| 842 | + if (!(hid->claimed & HID_CLAIMED_INPUT)) | |
| 843 | + return; | |
| 844 | + | |
| 845 | + if (report->id == td->mt_report_id) | |
| 846 | + mt_touch_report(hid, report); | |
| 847 | + | |
| 848 | + if (report->id == td->pen_report_id) | |
| 849 | + mt_pen_report(hid, report); | |
| 728 | 850 | } |
| 729 | 851 | |
| 730 | 852 | static void mt_set_input_mode(struct hid_device *hdev) |
| @@ -740,7 +862,7 @@ static void mt_set_input_mode(struct hid_device *hdev) · 9 unmodified lines | ||
| 740 | 862 | r = re->report_id_hash[td->inputmode]; |
| 741 | 863 | if (r) { |
| 742 | 864 | r->field[0]->value[td->inputmode_index] = 0x02; |
| 743 | − usbhid_submit_report(hdev, r, USB_DIR_OUT); | |
| 865 | + hid_hw_request(hdev, r, HID_REQ_SET_REPORT); | |
| 744 | 866 | } |
| 745 | 867 | } |
| 746 | 868 | |
| @@ -765,7 +887,7 @@ static void mt_set_maxcontacts(struct hid_device *hdev) · 18 unmodified lines | ||
| 765 | 887 | max = min(fieldmax, max); |
| 766 | 888 | if (r->field[0]->value[0] != max) { |
| 767 | 889 | r->field[0]->value[0] = max; |
| 768 | − usbhid_submit_report(hdev, r, USB_DIR_OUT); | |
| 890 | + hid_hw_request(hdev, r, HID_REQ_SET_REPORT); | |
| 769 | 891 | } |
| 770 | 892 | } |
| 771 | 893 | } |
| @@ -801,32 +923,18 @@ static void mt_post_parse(struct mt_device *td) · 29 unmodified lines | ||
| 801 | 923 | } |
| 802 | 924 | |
| 803 | 925 | static void mt_input_configured(struct hid_device *hdev, struct hid_input *hi) |
| 804 | − | |
| 805 | 926 | { |
| 806 | 927 | struct mt_device *td = hid_get_drvdata(hdev); |
| 807 | − struct mt_class *cls = &td->mtclass; | |
| 808 | − struct input_dev *input = hi->input; | |
| 928 | + char *name = kstrdup(hdev->name, GFP_KERNEL); | |
| 809 | 929 | |
| 810 | − /* Only initialize slots for MT input devices */ | |
| 811 | − if (!test_bit(ABS_MT_POSITION_X, input->absbit)) | |
| 812 | − return; | |
| 930 | + if (name) | |
| 931 | + hi->input->name = name; | |
| 813 | 932 | |
| 814 | − if (!td->maxcontacts) | |
| 815 | − td->maxcontacts = MT_DEFAULT_MAXCONTACT; | |
| 933 | + if (hi->report->id == td->mt_report_id) | |
| 934 | + mt_touch_input_configured(hdev, hi); | |
| 816 | 935 | |
| 817 | − mt_post_parse(td); | |
| 818 | − if (td->serial_maybe) | |
| 819 | − mt_post_parse_default_settings(td); | |
| 820 | − | |
| 821 | − if (cls->is_indirect) | |
| 822 | − td->mt_flags |= INPUT_MT_POINTER; | |
| 823 | − | |
| 824 | − if (cls->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP) | |
| 825 | − td->mt_flags |= INPUT_MT_DROP_UNUSED; | |
| 826 | − | |
| 827 | − input_mt_init_slots(input, td->maxcontacts, td->mt_flags); | |
| 828 | − | |
| 829 | − td->mt_flags = 0; | |
| 936 | + if (hi->report->id == td->pen_report_id) | |
| 937 | + mt_pen_input_configured(hdev, hi); | |
| 830 | 938 | } |
| 831 | 939 | |
| 832 | 940 | 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) · 1 unmodified line | ||
| 834 | 942 | int ret, i; |
| 835 | 943 | struct mt_device *td; |
| 836 | 944 | struct mt_class *mtclass = mt_classes; /* MT_CLS_DEFAULT */ |
| 945 | + struct hid_input *hi; | |
| 837 | 946 | |
| 838 | 947 | for (i = 0; mt_classes[i].name ; i++) { |
| 839 | 948 | 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) · 7 unmodified lines | ||
| 847 | 956 | */ |
| 848 | 957 | hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC; |
| 849 | 958 | |
| 959 | + /* | |
| 960 | + * This allows the driver to handle different input sensors | |
| 961 | + * that emits events through different reports on the same HID | |
| 962 | + * device. | |
| 963 | + */ | |
| 964 | + hdev->quirks |= HID_QUIRK_MULTI_INPUT; | |
| 965 | + hdev->quirks |= HID_QUIRK_NO_EMPTY_INPUT; | |
| 966 | + | |
| 850 | 967 | td = kzalloc(sizeof(struct mt_device), GFP_KERNEL); |
| 851 | 968 | if (!td) { |
| 852 | 969 | 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) · 3 unmodified lines | ||
| 856 | 973 | td->inputmode = -1; |
| 857 | 974 | td->maxcontact_report_id = -1; |
| 858 | 975 | td->cc_index = -1; |
| 976 | + td->mt_report_id = -1; | |
| 977 | + td->pen_report_id = -1; | |
| 859 | 978 | hid_set_drvdata(hdev, td); |
| 860 | 979 | |
| 861 | 980 | 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) · 12 unmodified lines | ||
| 874 | 993 | |
| 875 | 994 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); |
| 876 | 995 | if (ret) |
| 877 | − goto fail; | |
| 996 | + goto hid_fail; | |
| 878 | 997 | |
| 879 | 998 | ret = sysfs_create_group(&hdev->dev.kobj, &mt_attribute_group); |
| 880 | 999 | |
| @@ -886,6 +1005,9 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) · 5 unmodified lines | ||
| 886 | 1005 | |
| 887 | 1006 | return 0; |
| 888 | 1007 | |
| 1008 | +hid_fail: | |
| 1009 | + list_for_each_entry(hi, &hdev->inputs, list) | |
| 1010 | + mt_free_input_name(hi); | |
| 889 | 1011 | fail: |
| 890 | 1012 | kfree(td->fields); |
| 891 | 1013 | kfree(td); |
| @@ -902,26 +1024,11 @@ static int mt_reset_resume(struct hid_device *hdev) · 10 unmodified lines | ||
| 902 | 1024 | |
| 903 | 1025 | static int mt_resume(struct hid_device *hdev) |
| 904 | 1026 | { |
| 905 | − struct usb_interface *intf; | |
| 906 | − struct usb_host_interface *interface; | |
| 907 | − struct usb_device *dev; | |
| 908 | − | |
| 909 | − if (hdev->bus != BUS_USB) | |
| 910 | − return 0; | |
| 911 | − | |
| 912 | − intf = to_usb_interface(hdev->dev.parent); | |
| 913 | − interface = intf->cur_altsetting; | |
| 914 | − dev = hid_to_usb_dev(hdev); | |
| 915 | − | |
| 916 | 1027 | /* Some Elan legacy devices require SET_IDLE to be set on resume. |
| 917 | 1028 | * It should be safe to send it to other devices too. |
| 918 | 1029 | * Tested on 3M, Stantum, Cypress, Zytronic, eGalax, and Elan panels. */ |
| 919 | 1030 | |
| 920 | − usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | |
| 921 | − HID_REQ_SET_IDLE, | |
| 922 | − USB_TYPE_CLASS | USB_RECIP_INTERFACE, | |
| 923 | − 0, interface->desc.bInterfaceNumber, | |
| 924 | − NULL, 0, USB_CTRL_SET_TIMEOUT); | |
| 1031 | + hid_hw_idle(hdev, 0, 0, HID_REQ_SET_IDLE); | |
| 925 | 1032 | |
| 926 | 1033 | return 0; |
| 927 | 1034 | } |
| @@ -930,8 +1037,14 @@ static int mt_resume(struct hid_device *hdev) · 2 unmodified lines | ||
| 930 | 1037 | static void mt_remove(struct hid_device *hdev) |
| 931 | 1038 | { |
| 932 | 1039 | struct mt_device *td = hid_get_drvdata(hdev); |
| 1040 | + struct hid_input *hi; | |
| 1041 | + | |
| 933 | 1042 | sysfs_remove_group(&hdev->dev.kobj, &mt_attribute_group); |
| 934 | 1043 | hid_hw_stop(hdev); |
| 1044 | + | |
| 1045 | + list_for_each_entry(hi, &hdev->inputs, list) | |
| 1046 | + mt_free_input_name(hi); | |
| 1047 | + | |
| 935 | 1048 | kfree(td); |
| 936 | 1049 | hid_set_drvdata(hdev, NULL); |
| 937 | 1050 | } |
| @@ -118,8 +118,8 @@ static inline int ntrig_get_mode(struct hid_device *hdev) · 117 unmodified lines | ||
| 118 | 118 | if (!report) |
| 119 | 119 | return -EINVAL; |
| 120 | 120 | |
| 121 | − usbhid_submit_report(hdev, report, USB_DIR_IN); | |
| 122 | − usbhid_wait_io(hdev); | |
| 121 | + hid_hw_request(hdev, report, HID_REQ_GET_REPORT); | |
| 122 | + hid_hw_wait(hdev); | |
| 123 | 123 | return (int)report->field[0]->value[0]; |
| 124 | 124 | } |
| 125 | 125 | |
| @@ -137,7 +137,7 @@ static inline void ntrig_set_mode(struct hid_device *hdev, const int mode) · 11 unmodified lines | ||
| 137 | 137 | if (!report) |
| 138 | 138 | return; |
| 139 | 139 | |
| 140 | − usbhid_submit_report(hdev, report, USB_DIR_IN); | |
| 140 | + hid_hw_request(hdev, report, HID_REQ_GET_REPORT); | |
| 141 | 141 | } |
| 142 | 142 | |
| 143 | 143 | 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) · 793 unmodified lines | ||
| 937 | 937 | if (report) { |
| 938 | 938 | /* Let the device settle to ensure the wakeup message gets |
| 939 | 939 | * through */ |
| 940 | − usbhid_wait_io(hdev); | |
| 941 | − usbhid_submit_report(hdev, report, USB_DIR_IN); | |
| 940 | + hid_hw_wait(hdev); | |
| 941 | + hid_hw_request(hdev, report, HID_REQ_GET_REPORT); | |
| 942 | 942 | |
| 943 | 943 | /* |
| 944 | 944 | * Sanity check: if the current mode is invalid reset it to |
| @@ -142,10 +142,10 @@ struct hid_report *picolcd_report(int id, struct hid_device *hdev, int dir); · 141 unmodified lines | ||
| 142 | 142 | #ifdef CONFIG_DEBUG_FS |
| 143 | 143 | void picolcd_debug_out_report(struct picolcd_data *data, |
| 144 | 144 | struct hid_device *hdev, struct hid_report *report); |
| 145 | −#define usbhid_submit_report(a, b, c) \ | |
| 145 | +#define hid_hw_request(a, b, c) \ | |
| 146 | 146 | do { \ |
| 147 | 147 | picolcd_debug_out_report(hid_get_drvdata(a), a, b); \ |
| 148 | − usbhid_submit_report(a, b, c); \ | |
| 148 | + hid_hw_request(a, b, c); \ | |
| 149 | 149 | } while (0) |
| 150 | 150 | |
| 151 | 151 | 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 · 150 unmodified lines | ||
| 302 | 302 | static inline void picolcd_exit_cir(struct picolcd_data *data) |
| 303 | 303 | { |
| 304 | 304 | } |
| 305 | −#endif /* CONFIG_HID_PICOLCD_LIRC */ | |
| 305 | +#endif /* CONFIG_HID_PICOLCD_CIR */ | |
| 306 | 306 | |
| 307 | 307 | int picolcd_reset(struct hid_device *hdev); |
| 308 | 308 | struct picolcd_pending *picolcd_send_and_wait(struct hid_device *hdev, |
| @@ -18,8 +18,6 @@ · 17 unmodified lines | ||
| 18 | 18 | ***************************************************************************/ |
| 19 | 19 | |
| 20 | 20 | #include <linux/hid.h> |
| 21 | −#include "usbhid/usbhid.h" | |
| 22 | −#include <linux/usb.h> | |
| 23 | 21 | |
| 24 | 22 | #include <linux/fb.h> |
| 25 | 23 | #include <linux/backlight.h> |
| @@ -46,7 +44,7 @@ static int picolcd_set_brightness(struct backlight_device *bdev) · 20 unmodified lines | ||
| 46 | 44 | spin_lock_irqsave(&data->lock, flags); |
| 47 | 45 | hid_set_field(report->field[0], 0, data->lcd_power == FB_BLANK_UNBLANK ? data->lcd_brightness : 0); |
| 48 | 46 | if (!(data->status & PICOLCD_FAILED)) |
| 49 | − usbhid_submit_report(data->hdev, report, USB_DIR_OUT); | |
| 47 | + hid_hw_request(data->hdev, report, HID_REQ_SET_REPORT); | |
| 50 | 48 | spin_unlock_irqrestore(&data->lock, flags); |
| 51 | 49 | return 0; |
| 52 | 50 | } |
| @@ -21,8 +21,6 @@ · 20 unmodified lines | ||
| 21 | 21 | #include <linux/hid-debug.h> |
| 22 | 22 | #include <linux/input.h> |
| 23 | 23 | #include "hid-ids.h" |
| 24 | −#include "usbhid/usbhid.h" | |
| 25 | −#include <linux/usb.h> | |
| 26 | 24 | |
| 27 | 25 | #include <linux/fb.h> |
| 28 | 26 | #include <linux/vmalloc.h> |
| @@ -21,8 +21,6 @@ · 20 unmodified lines | ||
| 21 | 21 | #include <linux/hid-debug.h> |
| 22 | 22 | #include <linux/input.h> |
| 23 | 23 | #include "hid-ids.h" |
| 24 | −#include "usbhid/usbhid.h" | |
| 25 | −#include <linux/usb.h> | |
| 26 | 24 | |
| 27 | 25 | #include <linux/fb.h> |
| 28 | 26 | #include <linux/vmalloc.h> |
| @@ -110,7 +108,7 @@ struct picolcd_pending *picolcd_send_and_wait(struct hid_device *hdev, · 81 unmodified lines | ||
| 110 | 108 | work = NULL; |
| 111 | 109 | } else { |
| 112 | 110 | data->pending = work; |
| 113 | − usbhid_submit_report(data->hdev, report, USB_DIR_OUT); | |
| 111 | + hid_hw_request(data->hdev, report, HID_REQ_SET_REPORT); | |
| 114 | 112 | spin_unlock_irqrestore(&data->lock, flags); |
| 115 | 113 | wait_for_completion_interruptible_timeout(&work->ready, HZ*2); |
| 116 | 114 | spin_lock_irqsave(&data->lock, flags); |
| @@ -244,7 +242,7 @@ int picolcd_reset(struct hid_device *hdev) · 127 unmodified lines | ||
| 244 | 242 | spin_unlock_irqrestore(&data->lock, flags); |
| 245 | 243 | return -ENODEV; |
| 246 | 244 | } |
| 247 | − usbhid_submit_report(hdev, report, USB_DIR_OUT); | |
| 245 | + hid_hw_request(hdev, report, HID_REQ_SET_REPORT); | |
| 248 | 246 | spin_unlock_irqrestore(&data->lock, flags); |
| 249 | 247 | |
| 250 | 248 | error = picolcd_check_version(hdev); |
| @@ -303,7 +301,7 @@ static ssize_t picolcd_operation_mode_store(struct device *dev, · 52 unmodified lines | ||
| 303 | 301 | spin_lock_irqsave(&data->lock, flags); |
| 304 | 302 | hid_set_field(report->field[0], 0, timeout & 0xff); |
| 305 | 303 | hid_set_field(report->field[0], 1, (timeout >> 8) & 0xff); |
| 306 | − usbhid_submit_report(data->hdev, report, USB_DIR_OUT); | |
| 304 | + hid_hw_request(data->hdev, report, HID_REQ_SET_REPORT); | |
| 307 | 305 | spin_unlock_irqrestore(&data->lock, flags); |
| 308 | 306 | return count; |
| 309 | 307 | } |
| @@ -19,8 +19,6 @@ · 18 unmodified lines | ||
| 19 | 19 | |
| 20 | 20 | #include <linux/hid.h> |
| 21 | 21 | #include <linux/hid-debug.h> |
| 22 | −#include "usbhid/usbhid.h" | |
| 23 | −#include <linux/usb.h> | |
| 24 | 22 | |
| 25 | 23 | #include <linux/fb.h> |
| 26 | 24 | #include <linux/seq_file.h> |
| @@ -19,8 +19,6 @@ · 18 unmodified lines | ||
| 19 | 19 | |
| 20 | 20 | #include <linux/hid.h> |
| 21 | 21 | #include <linux/vmalloc.h> |
| 22 | −#include "usbhid/usbhid.h" | |
| 23 | −#include <linux/usb.h> | |
| 24 | 22 | |
| 25 | 23 | #include <linux/fb.h> |
| 26 | 24 | #include <linux/module.h> |
| @@ -143,8 +141,8 @@ static int picolcd_fb_send_tile(struct picolcd_data *data, u8 *vbitmap, · 116 unmodified lines | ||
| 143 | 141 | else |
| 144 | 142 | hid_set_field(report2->field[0], 4 + i - 32, tdata[i]); |
| 145 | 143 | |
| 146 | − usbhid_submit_report(data->hdev, report1, USB_DIR_OUT); | |
| 147 | − usbhid_submit_report(data->hdev, report2, USB_DIR_OUT); | |
| 144 | + hid_hw_request(data->hdev, report1, HID_REQ_SET_REPORT); | |
| 145 | + hid_hw_request(data->hdev, report2, HID_REQ_SET_REPORT); | |
| 148 | 146 | spin_unlock_irqrestore(&data->lock, flags); |
| 149 | 147 | return 0; |
| 150 | 148 | } |
| @@ -214,7 +212,7 @@ int picolcd_fb_reset(struct picolcd_data *data, int clear) · 63 unmodified lines | ||
| 214 | 212 | hid_set_field(report->field[0], j, mapcmd[j]); |
| 215 | 213 | else |
| 216 | 214 | hid_set_field(report->field[0], j, 0); |
| 217 | − usbhid_submit_report(data->hdev, report, USB_DIR_OUT); | |
| 215 | + hid_hw_request(data->hdev, report, HID_REQ_SET_REPORT); | |
| 218 | 216 | } |
| 219 | 217 | spin_unlock_irqrestore(&data->lock, flags); |
| 220 | 218 | |
| @@ -270,7 +268,7 @@ static void picolcd_fb_update(struct fb_info *info) · 49 unmodified lines | ||
| 270 | 268 | mutex_unlock(&info->lock); |
| 271 | 269 | if (!data) |
| 272 | 270 | return; |
| 273 | − usbhid_wait_io(data->hdev); | |
| 271 | + hid_hw_wait(data->hdev); | |
| 274 | 272 | mutex_lock(&info->lock); |
| 275 | 273 | n = 0; |
| 276 | 274 | } |
| @@ -288,7 +286,7 @@ static void picolcd_fb_update(struct fb_info *info) · 11 unmodified lines | ||
| 288 | 286 | spin_unlock_irqrestore(&fbdata->lock, flags); |
| 289 | 287 | mutex_unlock(&info->lock); |
| 290 | 288 | if (data) |
| 291 | − usbhid_wait_io(data->hdev); | |
| 289 | + hid_hw_wait(data->hdev); | |
| 292 | 290 | return; |
| 293 | 291 | } |
| 294 | 292 | out: |
| @@ -18,8 +18,6 @@ · 17 unmodified lines | ||
| 18 | 18 | ***************************************************************************/ |
| 19 | 19 | |
| 20 | 20 | #include <linux/hid.h> |
| 21 | −#include "usbhid/usbhid.h" | |
| 22 | −#include <linux/usb.h> | |
| 23 | 21 | |
| 24 | 22 | #include <linux/fb.h> |
| 25 | 23 | #include <linux/lcd.h> |
| @@ -48,7 +46,7 @@ static int picolcd_set_contrast(struct lcd_device *ldev, int contrast) · 22 unmodified lines | ||
| 48 | 46 | spin_lock_irqsave(&data->lock, flags); |
| 49 | 47 | hid_set_field(report->field[0], 0, data->lcd_contrast); |
| 50 | 48 | if (!(data->status & PICOLCD_FAILED)) |
| 51 | − usbhid_submit_report(data->hdev, report, USB_DIR_OUT); | |
| 49 | + hid_hw_request(data->hdev, report, HID_REQ_SET_REPORT); | |
| 52 | 50 | spin_unlock_irqrestore(&data->lock, flags); |
| 53 | 51 | return 0; |
| 54 | 52 | } |
| @@ -21,8 +21,6 @@ · 20 unmodified lines | ||
| 21 | 21 | #include <linux/hid-debug.h> |
| 22 | 22 | #include <linux/input.h> |
| 23 | 23 | #include "hid-ids.h" |
| 24 | −#include "usbhid/usbhid.h" | |
| 25 | −#include <linux/usb.h> | |
| 26 | 24 | |
| 27 | 25 | #include <linux/fb.h> |
| 28 | 26 | #include <linux/vmalloc.h> |
| @@ -55,7 +53,7 @@ void picolcd_leds_set(struct picolcd_data *data) · 26 unmodified lines | ||
| 55 | 53 | spin_lock_irqsave(&data->lock, flags); |
| 56 | 54 | hid_set_field(report->field[0], 0, data->led_state); |
| 57 | 55 | if (!(data->status & PICOLCD_FAILED)) |
| 58 | − usbhid_submit_report(data->hdev, report, USB_DIR_OUT); | |
| 56 | + hid_hw_request(data->hdev, report, HID_REQ_SET_REPORT); | |
| 59 | 57 | spin_unlock_irqrestore(&data->lock, flags); |
| 60 | 58 | } |
| 61 | 59 | |
| @@ -43,13 +43,11 @@ · 42 unmodified lines | ||
| 43 | 43 | #include <linux/input.h> |
| 44 | 44 | #include <linux/slab.h> |
| 45 | 45 | #include <linux/module.h> |
| 46 | −#include <linux/usb.h> | |
| 47 | 46 | #include <linux/hid.h> |
| 48 | 47 | |
| 49 | 48 | #include "hid-ids.h" |
| 50 | 49 | |
| 51 | 50 | #ifdef CONFIG_PANTHERLORD_FF |
| 52 | −#include "usbhid/usbhid.h" | |
| 53 | 51 | |
| 54 | 52 | struct plff_device { |
| 55 | 53 | struct hid_report *report; |
| @@ -75,7 +73,7 @@ static int hid_plff_play(struct input_dev *dev, void *data, · 19 unmodified lines | ||
| 75 | 73 | *plff->strong = left; |
| 76 | 74 | *plff->weak = right; |
| 77 | 75 | debug("running with 0x%02x 0x%02x", left, right); |
| 78 | − usbhid_submit_report(hid, plff->report, USB_DIR_OUT); | |
| 76 | + hid_hw_request(hid, plff->report, HID_REQ_SET_REPORT); | |
| 79 | 77 | |
| 80 | 78 | return 0; |
| 81 | 79 | } |
| @@ -169,7 +167,7 @@ static int plff_init(struct hid_device *hid) · 87 unmodified lines | ||
| 169 | 167 | |
| 170 | 168 | *strong = 0x00; |
| 171 | 169 | *weak = 0x00; |
| 172 | − usbhid_submit_report(hid, plff->report, USB_DIR_OUT); | |
| 170 | + hid_hw_request(hid, plff->report, HID_REQ_SET_REPORT); | |
| 173 | 171 | } |
| 174 | 172 | |
| 175 | 173 | hid_info(hid, "Force feedback for PantherLord/GreenAsia devices by Anssi Hannula <anssi.hannula@gmail.com>\n"); |
| @@ -26,7 +26,6 @@ · 25 unmodified lines | ||
| 26 | 26 | #include <sound/core.h> |
| 27 | 27 | #include <sound/initval.h> |
| 28 | 28 | #include <sound/rawmidi.h> |
| 29 | −#include "usbhid/usbhid.h" | |
| 30 | 29 | #include "hid-ids.h" |
| 31 | 30 | |
| 32 | 31 | |
| @@ -306,7 +305,7 @@ static void pcmidi_submit_output_report(struct pcmidi_snd *pm, int state) · 273 unmodified lines | ||
| 306 | 305 | report->field[0]->value[0] = 0x01; |
| 307 | 306 | report->field[0]->value[1] = state; |
| 308 | 307 | |
| 309 | − usbhid_submit_report(hdev, report, USB_DIR_OUT); | |
| 308 | + hid_hw_request(hdev, report, HID_REQ_SET_REPORT); | |
| 310 | 309 | } |
| 311 | 310 | |
| 312 | 311 | static int pcmidi_handle_report1(struct pcmidi_snd *pm, u8 *data) |
| @@ -130,14 +130,14 @@ static ssize_t isku_sysfs_read(struct file *fp, struct kobject *kobj, · 129 unmodified lines | ||
| 130 | 130 | if (off >= real_size) |
| 131 | 131 | return 0; |
| 132 | 132 | |
| 133 | − if (off != 0 || count != real_size) | |
| 133 | + if (off != 0 || count > real_size) | |
| 134 | 134 | return -EINVAL; |
| 135 | 135 | |
| 136 | 136 | mutex_lock(&isku->isku_lock); |
| 137 | − retval = isku_receive(usb_dev, command, buf, real_size); | |
| 137 | + retval = isku_receive(usb_dev, command, buf, count); | |
| 138 | 138 | mutex_unlock(&isku->isku_lock); |
| 139 | 139 | |
| 140 | − return retval ? retval : real_size; | |
| 140 | + return retval ? retval : count; | |
| 141 | 141 | } |
| 142 | 142 | |
| 143 | 143 | 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, · 6 unmodified lines | ||
| 150 | 150 | struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); |
| 151 | 151 | int retval; |
| 152 | 152 | |
| 153 | − if (off != 0 || count != real_size) | |
| 153 | + if (off != 0 || count > real_size) | |
| 154 | 154 | return -EINVAL; |
| 155 | 155 | |
| 156 | 156 | mutex_lock(&isku->isku_lock); |
| 157 | 157 | retval = roccat_common2_send_with_status(usb_dev, command, |
| 158 | − (void *)buf, real_size); | |
| 158 | + (void *)buf, count); | |
| 159 | 159 | mutex_unlock(&isku->isku_lock); |
| 160 | 160 | |
| 161 | − return retval ? retval : real_size; | |
| 161 | + return retval ? retval : count; | |
| 162 | 162 | } |
| 163 | 163 | |
| 164 | 164 | #define ISKU_SYSFS_W(thingy, THINGY) \ |
| @@ -216,6 +216,7 @@ ISKU_SYSFS_RW(light, LIGHT) · 51 unmodified lines | ||
| 216 | 216 | ISKU_SYSFS_RW(key_mask, KEY_MASK) |
| 217 | 217 | ISKU_SYSFS_RW(last_set, LAST_SET) |
| 218 | 218 | ISKU_SYSFS_W(talk, TALK) |
| 219 | +ISKU_SYSFS_W(talkfx, TALKFX) | |
| 219 | 220 | ISKU_SYSFS_R(info, INFO) |
| 220 | 221 | ISKU_SYSFS_W(control, CONTROL) |
| 221 | 222 | ISKU_SYSFS_W(reset, RESET) |
| @@ -232,6 +233,7 @@ static struct bin_attribute isku_bin_attributes[] = { · 10 unmodified lines | ||
| 232 | 233 | ISKU_BIN_ATTR_RW(key_mask, KEY_MASK), |
| 233 | 234 | ISKU_BIN_ATTR_RW(last_set, LAST_SET), |
| 234 | 235 | ISKU_BIN_ATTR_W(talk, TALK), |
| 236 | + ISKU_BIN_ATTR_W(talkfx, TALKFX), | |
| 235 | 237 | ISKU_BIN_ATTR_R(info, INFO), |
| 236 | 238 | ISKU_BIN_ATTR_W(control, CONTROL), |
| 237 | 239 | ISKU_BIN_ATTR_W(reset, RESET), |
| @@ -405,6 +407,7 @@ static int isku_raw_event(struct hid_device *hdev, · 167 unmodified lines | ||
| 405 | 407 | |
| 406 | 408 | static const struct hid_device_id isku_devices[] = { |
| 407 | 409 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKU) }, |
| 410 | + { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKUFX) }, | |
| 408 | 411 | { } |
| 409 | 412 | }; |
| 410 | 413 | |
| @@ -443,5 +446,5 @@ module_init(isku_init); · 32 unmodified lines | ||
| 443 | 446 | module_exit(isku_exit); |
| 444 | 447 | |
| 445 | 448 | MODULE_AUTHOR("Stefan Achatz"); |
| 446 | −MODULE_DESCRIPTION("USB Roccat Isku driver"); | |
| 449 | +MODULE_DESCRIPTION("USB Roccat Isku/FX driver"); | |
| 447 | 450 | MODULE_LICENSE("GPL v2"); |
| @@ -25,10 +25,11 @@ enum { · 24 unmodified lines | ||
| 25 | 25 | ISKU_SIZE_KEYS_MACRO = 0x23, |
| 26 | 26 | ISKU_SIZE_KEYS_CAPSLOCK = 0x06, |
| 27 | 27 | ISKU_SIZE_LAST_SET = 0x14, |
| 28 | − ISKU_SIZE_LIGHT = 0x0a, | |
| 28 | + ISKU_SIZE_LIGHT = 0x10, | |
| 29 | 29 | ISKU_SIZE_MACRO = 0x823, |
| 30 | 30 | ISKU_SIZE_RESET = 0x03, |
| 31 | 31 | ISKU_SIZE_TALK = 0x10, |
| 32 | + ISKU_SIZE_TALKFX = 0x10, | |
| 32 | 33 | }; |
| 33 | 34 | |
| 34 | 35 | enum { |
| @@ -59,6 +60,7 @@ enum isku_commands { · 24 unmodified lines | ||
| 59 | 60 | ISKU_COMMAND_LAST_SET = 0x14, |
| 60 | 61 | ISKU_COMMAND_15 = 0x15, |
| 61 | 62 | ISKU_COMMAND_TALK = 0x16, |
| 63 | + ISKU_COMMAND_TALKFX = 0x17, | |
| 62 | 64 | ISKU_COMMAND_FIRMWARE_WRITE = 0x1b, |
| 63 | 65 | ISKU_COMMAND_FIRMWARE_WRITE_CONTROL = 0x1c, |
| 64 | 66 | }; |
| @@ -818,8 +818,9 @@ static void kone_report_to_chrdev(struct kone_device const *kone, · 817 unmodified lines | ||
| 818 | 818 | (uint8_t *)&roccat_report); |
| 819 | 819 | break; |
| 820 | 820 | case kone_mouse_event_call_overlong_macro: |
| 821 | + case kone_mouse_event_multimedia: | |
| 821 | 822 | if (event->value == kone_keystroke_action_press) { |
| 822 | − roccat_report.event = kone_mouse_event_call_overlong_macro; | |
| 823 | + roccat_report.event = event->event; | |
| 823 | 824 | roccat_report.value = kone->actual_profile; |
| 824 | 825 | roccat_report.key = event->macro_key; |
| 825 | 826 | roccat_report_event(kone->chrdev_minor, |
| @@ -169,6 +169,7 @@ enum kone_mouse_events { · 168 unmodified lines | ||
| 169 | 169 | /* TODO clarify meaning and occurence of kone_mouse_event_calibration */ |
| 170 | 170 | kone_mouse_event_calibration = 0xc0, |
| 171 | 171 | kone_mouse_event_call_overlong_macro = 0xe0, |
| 172 | + kone_mouse_event_multimedia = 0xe1, | |
| 172 | 173 | /* switch events notify if user changed values with mousebutton click */ |
| 173 | 174 | kone_mouse_event_switch_dpi = 0xf0, |
| 174 | 175 | kone_mouse_event_switch_profile = 0xf1 |
| @@ -0,0 +1,304 @@ | ||
| 1 | +/* | |
| 2 | + * Roccat KonePure driver for Linux | |
| 3 | + * | |
| 4 | + * Copyright (c) 2012 Stefan Achatz <erazor_de@users.sourceforge.net> | |
| 5 | + */ | |
| 6 | + | |
| 7 | +/* | |
| 8 | + * This program is free software; you can redistribute it and/or modify it | |
| 9 | + * under the terms of the GNU General Public License as published by the Free | |
| 10 | + * Software Foundation; either version 2 of the License, or (at your option) | |
| 11 | + * any later version. | |
| 12 | + */ | |
| 13 | + | |
| 14 | +/* | |
| 15 | + * Roccat KonePure is a smaller version of KoneXTD with less buttons and lights. | |
| 16 | + */ | |
| 17 | + | |
| 18 | +#include <linux/device.h> | |
| 19 | +#include <linux/input.h> | |
| 20 | +#include <linux/hid.h> | |
| 21 | +#include <linux/module.h> | |
| 22 | +#include <linux/slab.h> | |
| 23 | +#include <linux/hid-roccat.h> | |
| 24 | +#include "hid-ids.h" | |
| 25 | +#include "hid-roccat-common.h" | |
| 26 | +#include "hid-roccat-konepure.h" | |
| 27 | + | |
| 28 | +static struct class *konepure_class; | |
| 29 | + | |
| 30 | +static ssize_t konepure_sysfs_read(struct file *fp, struct kobject *kobj, | |
| 31 | + char *buf, loff_t off, size_t count, | |
| 32 | + size_t real_size, uint command) | |
| 33 | +{ | |
| 34 | + struct device *dev = | |
| 35 | + container_of(kobj, struct device, kobj)->parent->parent; | |
| 36 | + struct konepure_device *konepure = hid_get_drvdata(dev_get_drvdata(dev)); | |
| 37 | + struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); | |
| 38 | + int retval; | |
| 39 | + | |
| 40 | + if (off >= real_size) | |
| 41 | + return 0; | |
| 42 | + | |
| 43 | + if (off != 0 || count != real_size) | |
| 44 | + return -EINVAL; | |
| 45 | + | |
| 46 | + mutex_lock(&konepure->konepure_lock); | |
| 47 | + retval = roccat_common2_receive(usb_dev, command, buf, real_size); | |
| 48 | + mutex_unlock(&konepure->konepure_lock); | |
| 49 | + | |
| 50 | + return retval ? retval : real_size; | |
| 51 | +} | |
| 52 | + | |
| 53 | +static ssize_t konepure_sysfs_write(struct file *fp, struct kobject *kobj, | |
| 54 | + void const *buf, loff_t off, size_t count, | |
| 55 | + size_t real_size, uint command) | |
| 56 | +{ | |
| 57 | + struct device *dev = | |
| 58 | + container_of(kobj, struct device, kobj)->parent->parent; | |
| 59 | + struct konepure_device *konepure = hid_get_drvdata(dev_get_drvdata(dev)); | |
| 60 | + struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); | |
| 61 | + int retval; | |
| 62 | + | |
| 63 | + if (off != 0 || count != real_size) | |
| 64 | + return -EINVAL; | |
| 65 | + | |
| 66 | + mutex_lock(&konepure->konepure_lock); | |
| 67 | + retval = roccat_common2_send_with_status(usb_dev, command, | |
| 68 | + (void *)buf, real_size); | |
| 69 | + mutex_unlock(&konepure->konepure_lock); | |
| 70 | + | |
| 71 | + return retval ? retval : real_size; | |
| 72 | +} | |
| 73 | + | |
| 74 | +#define KONEPURE_SYSFS_W(thingy, THINGY) \ | |
| 75 | +static ssize_t konepure_sysfs_write_ ## thingy(struct file *fp, \ | |
| 76 | + struct kobject *kobj, struct bin_attribute *attr, char *buf, \ | |
| 77 | + loff_t off, size_t count) \ | |
| 78 | +{ \ | |
| 79 | + return konepure_sysfs_write(fp, kobj, buf, off, count, \ | |
| 80 | + KONEPURE_SIZE_ ## THINGY, KONEPURE_COMMAND_ ## THINGY); \ | |
| 81 | +} | |
| 82 | + | |
| 83 | +#define KONEPURE_SYSFS_R(thingy, THINGY) \ | |
| 84 | +static ssize_t konepure_sysfs_read_ ## thingy(struct file *fp, \ | |
| 85 | + struct kobject *kobj, struct bin_attribute *attr, char *buf, \ | |
| 86 | + loff_t off, size_t count) \ | |
| 87 | +{ \ | |
| 88 | + return konepure_sysfs_read(fp, kobj, buf, off, count, \ | |
| 89 | + KONEPURE_SIZE_ ## THINGY, KONEPURE_COMMAND_ ## THINGY); \ | |
| 90 | +} | |
| 91 | + | |
| 92 | +#define KONEPURE_SYSFS_RW(thingy, THINGY) \ | |
| 93 | +KONEPURE_SYSFS_W(thingy, THINGY) \ | |
| 94 | +KONEPURE_SYSFS_R(thingy, THINGY) | |
| 95 | + | |
| 96 | +#define KONEPURE_BIN_ATTRIBUTE_RW(thingy, THINGY) \ | |
| 97 | +{ \ | |
| 98 | + .attr = { .name = #thingy, .mode = 0660 }, \ | |
| 99 | + .size = KONEPURE_SIZE_ ## THINGY, \ | |
| 100 | + .read = konepure_sysfs_read_ ## thingy, \ | |
| 101 | + .write = konepure_sysfs_write_ ## thingy \ | |
| 102 | +} | |
| 103 | + | |
| 104 | +#define KONEPURE_BIN_ATTRIBUTE_R(thingy, THINGY) \ | |
| 105 | +{ \ | |
| 106 | + .attr = { .name = #thingy, .mode = 0440 }, \ | |
| 107 | + .size = KONEPURE_SIZE_ ## THINGY, \ | |
| 108 | + .read = konepure_sysfs_read_ ## thingy, \ | |
| 109 | +} | |
| 110 | + | |
| 111 | +#define KONEPURE_BIN_ATTRIBUTE_W(thingy, THINGY) \ | |
| 112 | +{ \ | |
| 113 | + .attr = { .name = #thingy, .mode = 0220 }, \ | |
| 114 | + .size = KONEPURE_SIZE_ ## THINGY, \ | |
| 115 | + .write = konepure_sysfs_write_ ## thingy \ | |
| 116 | +} | |
| 117 | + | |
| 118 | +KONEPURE_SYSFS_RW(actual_profile, ACTUAL_PROFILE) | |
| 119 | +KONEPURE_SYSFS_W(control, CONTROL) | |
| 120 | +KONEPURE_SYSFS_RW(info, INFO) | |
| 121 | +KONEPURE_SYSFS_W(talk, TALK) | |
| 122 | +KONEPURE_SYSFS_W(macro, MACRO) | |
| 123 | +KONEPURE_SYSFS_RW(sensor, SENSOR) | |
| 124 | +KONEPURE_SYSFS_RW(tcu, TCU) | |
| 125 | +KONEPURE_SYSFS_R(tcu_image, TCU_IMAGE) | |
| 126 | +KONEPURE_SYSFS_RW(profile_settings, PROFILE_SETTINGS) | |
| 127 | +KONEPURE_SYSFS_RW(profile_buttons, PROFILE_BUTTONS) | |
| 128 | + | |
| 129 | +static struct bin_attribute konepure_bin_attributes[] = { | |
| 130 | + KONEPURE_BIN_ATTRIBUTE_RW(actual_profile, ACTUAL_PROFILE), | |
| 131 | + KONEPURE_BIN_ATTRIBUTE_W(control, CONTROL), | |
| 132 | + KONEPURE_BIN_ATTRIBUTE_RW(info, INFO), | |
| 133 | + KONEPURE_BIN_ATTRIBUTE_W(talk, TALK), | |
| 134 | + KONEPURE_BIN_ATTRIBUTE_W(macro, MACRO), | |
| 135 | + KONEPURE_BIN_ATTRIBUTE_RW(sensor, SENSOR), | |
| 136 | + KONEPURE_BIN_ATTRIBUTE_RW(tcu, TCU), | |
| 137 | + KONEPURE_BIN_ATTRIBUTE_R(tcu_image, TCU_IMAGE), | |
| 138 | + KONEPURE_BIN_ATTRIBUTE_RW(profile_settings, PROFILE_SETTINGS), | |
| 139 | + KONEPURE_BIN_ATTRIBUTE_RW(profile_buttons, PROFILE_BUTTONS), | |
| 140 | + __ATTR_NULL | |
| 141 | +}; | |
| 142 | + | |
| 143 | +static int konepure_init_konepure_device_struct(struct usb_device *usb_dev, | |
| 144 | + struct konepure_device *konepure) | |
| 145 | +{ | |
| 146 | + mutex_init(&konepure->konepure_lock); | |
| 147 | + | |
| 148 | + return 0; | |
| 149 | +} | |
| 150 | + | |
| 151 | +static int konepure_init_specials(struct hid_device *hdev) | |
| 152 | +{ | |
| 153 | + struct usb_interface *intf = to_usb_interface(hdev->dev.parent); | |
| 154 | + struct usb_device *usb_dev = interface_to_usbdev(intf); | |
| 155 | + struct konepure_device *konepure; | |
| 156 | + int retval; | |
| 157 | + | |
| 158 | + if (intf->cur_altsetting->desc.bInterfaceProtocol | |
| 159 | + != USB_INTERFACE_PROTOCOL_MOUSE) { | |
| 160 | + hid_set_drvdata(hdev, NULL); | |
| 161 | + return 0; | |
| 162 | + } | |
| 163 | + | |
| 164 | + konepure = kzalloc(sizeof(*konepure), GFP_KERNEL); | |
| 165 | + if (!konepure) { | |
| 166 | + hid_err(hdev, "can't alloc device descriptor\n"); | |
| 167 | + return -ENOMEM; | |
| 168 | + } | |
| 169 | + hid_set_drvdata(hdev, konepure); | |
| 170 | + | |
| 171 | + retval = konepure_init_konepure_device_struct(usb_dev, konepure); | |
| 172 | + if (retval) { | |
| 173 | + hid_err(hdev, "couldn't init struct konepure_device\n"); | |
| 174 | + goto exit_free; | |
| 175 | + } | |
| 176 | + | |
| 177 | + retval = roccat_connect(konepure_class, hdev, | |
| 178 | + sizeof(struct konepure_mouse_report_button)); | |
| 179 | + if (retval < 0) { | |
| 180 | + hid_err(hdev, "couldn't init char dev\n"); | |
| 181 | + } else { | |
| 182 | + konepure->chrdev_minor = retval; | |
| 183 | + konepure->roccat_claimed = 1; | |
| 184 | + } | |
| 185 | + | |
| 186 | + return 0; | |
| 187 | +exit_free: | |
| 188 | + kfree(konepure); | |
| 189 | + return retval; | |
| 190 | +} | |
| 191 | + | |
| 192 | +static void konepure_remove_specials(struct hid_device *hdev) | |
| 193 | +{ | |
| 194 | + struct usb_interface *intf = to_usb_interface(hdev->dev.parent); | |
| 195 | + struct konepure_device *konepure; | |
| 196 | + | |
| 197 | + if (intf->cur_altsetting->desc.bInterfaceProtocol | |
| 198 | + != USB_INTERFACE_PROTOCOL_MOUSE) | |
| 199 | + return; | |
| 200 | + | |
| 201 | + konepure = hid_get_drvdata(hdev); | |
| 202 | + if (konepure->roccat_claimed) | |
| 203 | + roccat_disconnect(konepure->chrdev_minor); | |
| 204 | + kfree(konepure); | |
| 205 | +} | |
| 206 | + | |
| 207 | +static int konepure_probe(struct hid_device *hdev, | |
| 208 | + const struct hid_device_id *id) | |
| 209 | +{ | |
| 210 | + int retval; | |
| 211 | + | |
| 212 | + retval = hid_parse(hdev); | |
| 213 | + if (retval) { | |
| 214 | + hid_err(hdev, "parse failed\n"); | |
| 215 | + goto exit; | |
| 216 | + } | |
| 217 | + | |
| 218 | + retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT); | |
| 219 | + if (retval) { | |
| 220 | + hid_err(hdev, "hw start failed\n"); | |
| 221 | + goto exit; | |
| 222 | + } | |
| 223 | + | |
| 224 | + retval = konepure_init_specials(hdev); | |
| 225 | + if (retval) { | |
| 226 | + hid_err(hdev, "couldn't install mouse\n"); | |
| 227 | + goto exit_stop; | |
| 228 | + } | |
| 229 | + | |
| 230 | + return 0; | |
| 231 | + | |
| 232 | +exit_stop: | |
| 233 | + hid_hw_stop(hdev); | |
| 234 | +exit: | |
| 235 | + return retval; | |
| 236 | +} | |
| 237 | + | |
| 238 | +static void konepure_remove(struct hid_device *hdev) | |
| 239 | +{ | |
| 240 | + konepure_remove_specials(hdev); | |
| 241 | + hid_hw_stop(hdev); | |
| 242 | +} | |
| 243 | + | |
| 244 | +static int konepure_raw_event(struct hid_device *hdev, | |
| 245 | + struct hid_report *report, u8 *data, int size) | |
| 246 | +{ | |
| 247 | + struct usb_interface *intf = to_usb_interface(hdev->dev.parent); | |
| 248 | + struct konepure_device *konepure = hid_get_drvdata(hdev); | |
| 249 | + | |
| 250 | + if (intf->cur_altsetting->desc.bInterfaceProtocol | |
| 251 | + != USB_INTERFACE_PROTOCOL_MOUSE) | |
| 252 | + return 0; | |
| 253 | + | |
| 254 | + if (data[0] != KONEPURE_MOUSE_REPORT_NUMBER_BUTTON) | |
| 255 | + return 0; | |
| 256 | + | |
| 257 | + if (konepure != NULL && konepure->roccat_claimed) | |
| 258 | + roccat_report_event(konepure->chrdev_minor, data); | |
| 259 | + | |
| 260 | + return 0; | |
| 261 | +} | |
| 262 | + | |
| 263 | +static const struct hid_device_id konepure_devices[] = { | |
| 264 | + { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPURE) }, | |
| 265 | + { } | |
| 266 | +}; | |
| 267 | + | |
| 268 | +MODULE_DEVICE_TABLE(hid, konepure_devices); | |
| 269 | + | |
| 270 | +static struct hid_driver konepure_driver = { | |
| 271 | + .name = "konepure", | |
| 272 | + .id_table = konepure_devices, | |
| 273 | + .probe = konepure_probe, | |
| 274 | + .remove = konepure_remove, | |
| 275 | + .raw_event = konepure_raw_event | |
| 276 | +}; | |
| 277 | + | |
| 278 | +static int __init konepure_init(void) | |
| 279 | +{ | |
| 280 | + int retval; | |
| 281 | + | |
| 282 | + konepure_class = class_create(THIS_MODULE, "konepure"); | |
| 283 | + if (IS_ERR(konepure_class)) | |
| 284 | + return PTR_ERR(konepure_class); | |
| 285 | + konepure_class->dev_bin_attrs = konepure_bin_attributes; | |
| 286 | + | |
| 287 | + retval = hid_register_driver(&konepure_driver); | |
| 288 | + if (retval) | |
| 289 | + class_destroy(konepure_class); | |
| 290 | + return retval; | |
| 291 | +} | |
| 292 | + | |
| 293 | +static void __exit konepure_exit(void) | |
| 294 | +{ | |
| 295 | + hid_unregister_driver(&konepure_driver); | |
| 296 | + class_destroy(konepure_class); | |
| 297 | +} | |
| 298 | + | |
| 299 | +module_init(konepure_init); | |
| 300 | +module_exit(konepure_exit); | |
| 301 | + | |
| 302 | +MODULE_AUTHOR("Stefan Achatz"); | |
| 303 | +MODULE_DESCRIPTION("USB Roccat KonePure driver"); | |
| 304 | +MODULE_LICENSE("GPL v2"); | |
| @@ -0,0 +1,72 @@ | ||
| 1 | +#ifndef __HID_ROCCAT_KONEPURE_H | |
| 2 | +#define __HID_ROCCAT_KONEPURE_H | |
| 3 | + | |
| 4 | +/* | |
| 5 | + * Copyright (c) 2012 Stefan Achatz <erazor_de@users.sourceforge.net> | |
| 6 | + */ | |
| 7 | + | |
| 8 | +/* | |
| 9 | + * This program is free software; you can redistribute it and/or modify it | |
| 10 | + * under the terms of the GNU General Public License as published by the Free | |
| 11 | + * Software Foundation; either version 2 of the License, or (at your option) | |
| 12 | + * any later version. | |
| 13 | + */ | |
| 14 | + | |
| 15 | +#include <linux/types.h> | |
| 16 | + | |
| 17 | +enum { | |
| 18 | + KONEPURE_SIZE_ACTUAL_PROFILE = 0x03, | |
| 19 | + KONEPURE_SIZE_CONTROL = 0x03, | |
| 20 | + KONEPURE_SIZE_FIRMWARE_WRITE = 0x0402, | |
| 21 | + KONEPURE_SIZE_INFO = 0x06, | |
| 22 | + KONEPURE_SIZE_MACRO = 0x0822, | |
| 23 | + KONEPURE_SIZE_PROFILE_SETTINGS = 0x1f, | |
| 24 | + KONEPURE_SIZE_PROFILE_BUTTONS = 0x3b, | |
| 25 | + KONEPURE_SIZE_SENSOR = 0x06, | |
| 26 | + KONEPURE_SIZE_TALK = 0x10, | |
| 27 | + KONEPURE_SIZE_TCU = 0x04, | |
| 28 | + KONEPURE_SIZE_TCU_IMAGE = 0x0404, | |
| 29 | +}; | |
| 30 | + | |
| 31 | +enum konepure_control_requests { | |
| 32 | + KONEPURE_CONTROL_REQUEST_GENERAL = 0x80, | |
| 33 | + KONEPURE_CONTROL_REQUEST_BUTTONS = 0x90, | |
| 34 | +}; | |
| 35 | + | |
| 36 | +enum konepure_commands { | |
| 37 | + KONEPURE_COMMAND_CONTROL = 0x04, | |
| 38 | + KONEPURE_COMMAND_ACTUAL_PROFILE = 0x05, | |
| 39 | + KONEPURE_COMMAND_PROFILE_SETTINGS = 0x06, | |
| 40 | + KONEPURE_COMMAND_PROFILE_BUTTONS = 0x07, | |
| 41 | + KONEPURE_COMMAND_MACRO = 0x08, | |
| 42 | + KONEPURE_COMMAND_INFO = 0x09, | |
| 43 | + KONEPURE_COMMAND_TCU = 0x0c, | |
| 44 | + KONEPURE_COMMAND_TCU_IMAGE = 0x0c, | |
| 45 | + KONEPURE_COMMAND_E = 0x0e, | |
| 46 | + KONEPURE_COMMAND_SENSOR = 0x0f, | |
| 47 | + KONEPURE_COMMAND_TALK = 0x10, | |
| 48 | + KONEPURE_COMMAND_FIRMWARE_WRITE = 0x1b, | |
| 49 | + KONEPURE_COMMAND_FIRMWARE_WRITE_CONTROL = 0x1c, | |
| 50 | +}; | |
| 51 | + | |
| 52 | +enum { | |
| 53 | + KONEPURE_MOUSE_REPORT_NUMBER_BUTTON = 3, | |
| 54 | +}; | |
| 55 | + | |
| 56 | +struct konepure_mouse_report_button { | |
| 57 | + uint8_t report_number; /* always KONEPURE_MOUSE_REPORT_NUMBER_BUTTON */ | |
| 58 | + uint8_t zero; | |
| 59 | + uint8_t type; | |
| 60 | + uint8_t data1; | |
| 61 | + uint8_t data2; | |
| 62 | + uint8_t zero2; | |
| 63 | + uint8_t unknown[2]; | |
| 64 | +} __packed; | |
| 65 | + | |
| 66 | +struct konepure_device { | |
| 67 | + int roccat_claimed; | |
| 68 | + int chrdev_minor; | |
| 69 | + struct mutex konepure_lock; | |
| 70 | +}; | |
| 71 | + | |
| 72 | +#endif | |
| @@ -242,7 +242,6 @@ static int roccat_release(struct inode *inode, struct file *file) · 241 unmodified lines | ||
| 242 | 242 | * roccat_report_event() - output data to readers |
| 243 | 243 | * @minor: minor device number returned by roccat_connect() |
| 244 | 244 | * @data: pointer to data |
| 245 | − * @len: size of data | |
| 246 | 245 | * |
| 247 | 246 | * Return value is zero on success, a negative error code on failure. |
| 248 | 247 | * |
| @@ -290,6 +289,7 @@ EXPORT_SYMBOL_GPL(roccat_report_event); · 41 unmodified lines | ||
| 290 | 289 | * @class: the class thats used to create the device. Meant to hold device |
| 291 | 290 | * specific sysfs attributes. |
| 292 | 291 | * @hid: the hid device the char device should be connected to. |
| 292 | + * @report_size: size of reports | |
| 293 | 293 | * |
| 294 | 294 | * Return value is minor device number in Range [0, ROCCAT_MAX_DEVICES] on |
| 295 | 295 | * success, a negative error code on failure. |
| @@ -18,8 +18,6 @@ · 17 unmodified lines | ||
| 18 | 18 | */ |
| 19 | 19 | #include <linux/device.h> |
| 20 | 20 | #include <linux/hid.h> |
| 21 | −#include <linux/usb.h> | |
| 22 | −#include "usbhid/usbhid.h" | |
| 23 | 21 | #include <linux/module.h> |
| 24 | 22 | #include <linux/slab.h> |
| 25 | 23 | #include <linux/mfd/core.h> |
| @@ -204,8 +202,8 @@ int sensor_hub_set_feature(struct hid_sensor_hub_device *hsdev, u32 report_id, · 178 unmodified lines | ||
| 204 | 202 | goto done_proc; |
| 205 | 203 | } |
| 206 | 204 | hid_set_field(report->field[field_index], 0, value); |
| 207 | − usbhid_submit_report(hsdev->hdev, report, USB_DIR_OUT); | |
| 208 | − usbhid_wait_io(hsdev->hdev); | |
| 205 | + hid_hw_request(hsdev->hdev, report, HID_REQ_SET_REPORT); | |
| 206 | + hid_hw_wait(hsdev->hdev); | |
| 209 | 207 | |
| 210 | 208 | done_proc: |
| 211 | 209 | mutex_unlock(&data->mutex); |
| @@ -227,8 +225,8 @@ int sensor_hub_get_feature(struct hid_sensor_hub_device *hsdev, u32 report_id, · 15 unmodified lines | ||
| 227 | 225 | ret = -EINVAL; |
| 228 | 226 | goto done_proc; |
| 229 | 227 | } |
| 230 | − usbhid_submit_report(hsdev->hdev, report, USB_DIR_IN); | |
| 231 | − usbhid_wait_io(hsdev->hdev); | |
| 228 | + hid_hw_request(hsdev->hdev, report, HID_REQ_GET_REPORT); | |
| 229 | + hid_hw_wait(hsdev->hdev); | |
| 232 | 230 | *value = report->field[field_index]->value[0]; |
| 233 | 231 | |
| 234 | 232 | done_proc: |
| @@ -262,7 +260,7 @@ int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev, · 27 unmodified lines | ||
| 262 | 260 | spin_unlock_irqrestore(&data->lock, flags); |
| 263 | 261 | goto err_free; |
| 264 | 262 | } |
| 265 | − usbhid_submit_report(hsdev->hdev, report, USB_DIR_IN); | |
| 263 | + hid_hw_request(hsdev->hdev, report, HID_REQ_GET_REPORT); | |
| 266 | 264 | spin_unlock_irqrestore(&data->lock, flags); |
| 267 | 265 | wait_for_completion_interruptible_timeout(&data->pending.ready, HZ*5); |
| 268 | 266 | switch (data->pending.raw_size) { |
| @@ -28,13 +28,11 @@ · 27 unmodified lines | ||
| 28 | 28 | |
| 29 | 29 | #include <linux/input.h> |
| 30 | 30 | #include <linux/slab.h> |
| 31 | −#include <linux/usb.h> | |
| 32 | 31 | #include <linux/hid.h> |
| 33 | 32 | #include <linux/module.h> |
| 34 | 33 | #include "hid-ids.h" |
| 35 | 34 | |
| 36 | 35 | #ifdef CONFIG_SMARTJOYPLUS_FF |
| 37 | −#include "usbhid/usbhid.h" | |
| 38 | 36 | |
| 39 | 37 | struct sjoyff_device { |
| 40 | 38 | struct hid_report *report; |
| @@ -57,7 +55,7 @@ static int hid_sjoyff_play(struct input_dev *dev, void *data, · 16 unmodified lines | ||
| 57 | 55 | sjoyff->report->field[0]->value[1] = right; |
| 58 | 56 | sjoyff->report->field[0]->value[2] = left; |
| 59 | 57 | dev_dbg(&dev->dev, "running with 0x%02x 0x%02x\n", left, right); |
| 60 | − usbhid_submit_report(hid, sjoyff->report, USB_DIR_OUT); | |
| 58 | + hid_hw_request(hid, sjoyff->report, HID_REQ_SET_REPORT); | |
| 61 | 59 | |
| 62 | 60 | return 0; |
| 63 | 61 | } |
| @@ -115,7 +113,7 @@ static int sjoyff_init(struct hid_device *hid) · 51 unmodified lines | ||
| 115 | 113 | sjoyff->report->field[0]->value[0] = 0x01; |
| 116 | 114 | sjoyff->report->field[0]->value[1] = 0x00; |
| 117 | 115 | sjoyff->report->field[0]->value[2] = 0x00; |
| 118 | − usbhid_submit_report(hid, sjoyff->report, USB_DIR_OUT); | |
| 116 | + hid_hw_request(hid, sjoyff->report, HID_REQ_SET_REPORT); | |
| 119 | 117 | } |
| 120 | 118 | |
| 121 | 119 | hid_info(hid, "Force feedback for SmartJoy PLUS PS2/USB adapter\n"); |
| @@ -16,10 +16,8 @@ · 15 unmodified lines | ||
| 16 | 16 | #include <linux/device.h> |
| 17 | 17 | #include <linux/hid.h> |
| 18 | 18 | #include <linux/module.h> |
| 19 | −#include <linux/usb.h> | |
| 20 | 19 | |
| 21 | 20 | #include "hid-ids.h" |
| 22 | −#include "usbhid/usbhid.h" | |
| 23 | 21 | |
| 24 | 22 | static const struct hid_device_id speedlink_devices[] = { |
| 25 | 23 | { HID_USB_DEVICE(USB_VENDOR_ID_X_TENSIONS, USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE)}, |
| @@ -16,7 +16,6 @@ · 15 unmodified lines | ||
| 16 | 16 | #include <linux/hid.h> |
| 17 | 17 | #include <linux/module.h> |
| 18 | 18 | |
| 19 | −#include "usbhid/usbhid.h" | |
| 20 | 19 | #include "hid-ids.h" |
| 21 | 20 | |
| 22 | 21 | #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) · 109 unmodified lines | ||
| 132 | 131 | value[14] = 0x00; |
| 133 | 132 | value[15] = 0x00; |
| 134 | 133 | |
| 135 | − usbhid_submit_report(hdev, report, USB_DIR_OUT); | |
| 134 | + hid_hw_request(hdev, report, HID_REQ_SET_REPORT); | |
| 136 | 135 | |
| 137 | 136 | /* Note: LED change does not show on device until the device is read/polled */ |
| 138 | 137 | } |
| @@ -378,16 +377,5 @@ static struct hid_driver steelseries_srws1_driver = { · 239 unmodified lines | ||
| 378 | 377 | .report_fixup = steelseries_srws1_report_fixup |
| 379 | 378 | }; |
| 380 | 379 | |
| 381 | −static int __init steelseries_srws1_init(void) | |
| 382 | −{ | |
| 383 | − return hid_register_driver(&steelseries_srws1_driver); | |
| 384 | −} | |
| 385 | − | |
| 386 | −static void __exit steelseries_srws1_exit(void) | |
| 387 | −{ | |
| 388 | − hid_unregister_driver(&steelseries_srws1_driver); | |
| 389 | −} | |
| 390 | − | |
| 391 | −module_init(steelseries_srws1_init); | |
| 392 | −module_exit(steelseries_srws1_exit); | |
| 380 | +module_hid_driver(steelseries_srws1_driver); | |
| 393 | 381 | MODULE_LICENSE("GPL"); |
| @@ -12,7 +12,6 @@ · 11 unmodified lines | ||
| 12 | 12 | #include <linux/hid.h> |
| 13 | 13 | #include <linux/leds.h> |
| 14 | 14 | #include <linux/module.h> |
| 15 | −#include <linux/usb.h> | |
| 16 | 15 | |
| 17 | 16 | #include "hid-ids.h" |
| 18 | 17 | |
| @@ -30,7 +30,6 @@ · 29 unmodified lines | ||
| 30 | 30 | #include <linux/hid.h> |
| 31 | 31 | #include <linux/input.h> |
| 32 | 32 | #include <linux/slab.h> |
| 33 | −#include <linux/usb.h> | |
| 34 | 33 | #include <linux/module.h> |
| 35 | 34 | |
| 36 | 35 | #include "hid-ids.h" |
| @@ -46,7 +45,6 @@ static const signed short ff_joystick[] = { · 9 unmodified lines | ||
| 46 | 45 | }; |
| 47 | 46 | |
| 48 | 47 | #ifdef CONFIG_THRUSTMASTER_FF |
| 49 | −#include "usbhid/usbhid.h" | |
| 50 | 48 | |
| 51 | 49 | /* Usages for thrustmaster devices I know about */ |
| 52 | 50 | #define THRUSTMASTER_USAGE_FF (HID_UP_GENDESK | 0xbb) |
| @@ -103,7 +101,7 @@ static int tmff_play(struct input_dev *dev, void *data, · 50 unmodified lines | ||
| 103 | 101 | dbg_hid("(x, y)=(%04x, %04x)\n", x, y); |
| 104 | 102 | ff_field->value[0] = x; |
| 105 | 103 | ff_field->value[1] = y; |
| 106 | − usbhid_submit_report(hid, tmff->report, USB_DIR_OUT); | |
| 104 | + hid_hw_request(hid, tmff->report, HID_REQ_SET_REPORT); | |
| 107 | 105 | break; |
| 108 | 106 | |
| 109 | 107 | case FF_RUMBLE: |
| @@ -117,7 +115,7 @@ static int tmff_play(struct input_dev *dev, void *data, · 7 unmodified lines | ||
| 117 | 115 | dbg_hid("(left,right)=(%08x, %08x)\n", left, right); |
| 118 | 116 | ff_field->value[0] = left; |
| 119 | 117 | ff_field->value[1] = right; |
| 120 | − usbhid_submit_report(hid, tmff->report, USB_DIR_OUT); | |
| 118 | + hid_hw_request(hid, tmff->report, HID_REQ_SET_REPORT); | |
| 121 | 119 | break; |
| 122 | 120 | } |
| 123 | 121 | return 0; |
| @@ -789,12 +789,20 @@ static void __ir_to_input(struct wiimote_data *wdata, const __u8 *ir, · 788 unmodified lines | ||
| 789 | 789 | input_report_abs(wdata->ir, yid, y); |
| 790 | 790 | } |
| 791 | 791 | |
| 792 | −static void handler_status(struct wiimote_data *wdata, const __u8 *payload) | |
| 792 | +/* reduced status report with "BB BB" key data only */ | |
| 793 | +static void handler_status_K(struct wiimote_data *wdata, | |
| 794 | + const __u8 *payload) | |
| 793 | 795 | { |
| 794 | 796 | handler_keys(wdata, payload); |
| 795 | 797 | |
| 796 | 798 | /* on status reports the drm is reset so we need to resend the drm */ |
| 797 | 799 | wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL); |
| 800 | +} | |
| 801 | + | |
| 802 | +/* extended status report with "BB BB LF 00 00 VV" data */ | |
| 803 | +static void handler_status(struct wiimote_data *wdata, const __u8 *payload) | |
| 804 | +{ | |
| 805 | + handler_status_K(wdata, payload); | |
| 798 | 806 | |
| 799 | 807 | wiiext_event(wdata, payload[2] & 0x02); |
| 800 | 808 | |
| @@ -804,6 +812,12 @@ static void handler_status(struct wiimote_data *wdata, const __u8 *payload) · 3 unmodified lines | ||
| 804 | 812 | } |
| 805 | 813 | } |
| 806 | 814 | |
| 815 | +/* reduced generic report with "BB BB" key data only */ | |
| 816 | +static void handler_generic_K(struct wiimote_data *wdata, const __u8 *payload) | |
| 817 | +{ | |
| 818 | + handler_keys(wdata, payload); | |
| 819 | +} | |
| 820 | + | |
| 807 | 821 | static void handler_data(struct wiimote_data *wdata, const __u8 *payload) |
| 808 | 822 | { |
| 809 | 823 | __u16 offset = payload[3] << 8 | payload[4]; |
| @@ -947,16 +961,26 @@ struct wiiproto_handler { · 137 unmodified lines | ||
| 947 | 961 | |
| 948 | 962 | static struct wiiproto_handler handlers[] = { |
| 949 | 963 | { .id = WIIPROTO_REQ_STATUS, .size = 6, .func = handler_status }, |
| 964 | + { .id = WIIPROTO_REQ_STATUS, .size = 2, .func = handler_status_K }, | |
| 950 | 965 | { .id = WIIPROTO_REQ_DATA, .size = 21, .func = handler_data }, |
| 966 | + { .id = WIIPROTO_REQ_DATA, .size = 2, .func = handler_generic_K }, | |
| 951 | 967 | { .id = WIIPROTO_REQ_RETURN, .size = 4, .func = handler_return }, |
| 968 | + { .id = WIIPROTO_REQ_RETURN, .size = 2, .func = handler_generic_K }, | |
| 952 | 969 | { .id = WIIPROTO_REQ_DRM_K, .size = 2, .func = handler_keys }, |
| 953 | 970 | { .id = WIIPROTO_REQ_DRM_KA, .size = 5, .func = handler_drm_KA }, |
| 971 | + { .id = WIIPROTO_REQ_DRM_KA, .size = 2, .func = handler_generic_K }, | |
| 954 | 972 | { .id = WIIPROTO_REQ_DRM_KE, .size = 10, .func = handler_drm_KE }, |
| 973 | + { .id = WIIPROTO_REQ_DRM_KE, .size = 2, .func = handler_generic_K }, | |
| 955 | 974 | { .id = WIIPROTO_REQ_DRM_KAI, .size = 17, .func = handler_drm_KAI }, |
| 975 | + { .id = WIIPROTO_REQ_DRM_KAI, .size = 2, .func = handler_generic_K }, | |
| 956 | 976 | { .id = WIIPROTO_REQ_DRM_KEE, .size = 21, .func = handler_drm_KEE }, |
| 977 | + { .id = WIIPROTO_REQ_DRM_KEE, .size = 2, .func = handler_generic_K }, | |
| 957 | 978 | { .id = WIIPROTO_REQ_DRM_KAE, .size = 21, .func = handler_drm_KAE }, |
| 979 | + { .id = WIIPROTO_REQ_DRM_KAE, .size = 2, .func = handler_generic_K }, | |
| 958 | 980 | { .id = WIIPROTO_REQ_DRM_KIE, .size = 21, .func = handler_drm_KIE }, |
| 981 | + { .id = WIIPROTO_REQ_DRM_KIE, .size = 2, .func = handler_generic_K }, | |
| 959 | 982 | { .id = WIIPROTO_REQ_DRM_KAIE, .size = 21, .func = handler_drm_KAIE }, |
| 983 | + { .id = WIIPROTO_REQ_DRM_KAIE, .size = 2, .func = handler_generic_K }, | |
| 960 | 984 | { .id = WIIPROTO_REQ_DRM_E, .size = 21, .func = handler_drm_E }, |
| 961 | 985 | { .id = WIIPROTO_REQ_DRM_SKAI1, .size = 21, .func = handler_drm_SKAI1 }, |
| 962 | 986 | { .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, · 7 unmodified lines | ||
| 970 | 994 | struct wiiproto_handler *h; |
| 971 | 995 | int i; |
| 972 | 996 | unsigned long flags; |
| 973 | − bool handled = false; | |
| 974 | 997 | |
| 975 | 998 | if (size < 1) |
| 976 | 999 | return -EINVAL; |
| @@ -981,11 +1004,11 @@ static int wiimote_hid_event(struct hid_device *hdev, struct hid_report *report, · 4 unmodified lines | ||
| 981 | 1004 | h = &handlers[i]; |
| 982 | 1005 | if (h->id == raw_data[0] && h->size < size) { |
| 983 | 1006 | h->func(wdata, &raw_data[1]); |
| 984 | − handled = true; | |
| 1007 | + break; | |
| 985 | 1008 | } |
| 986 | 1009 | } |
| 987 | 1010 | |
| 988 | − if (!handled) | |
| 1011 | + if (!handlers[i].id) | |
| 989 | 1012 | hid_warn(hdev, "Unhandled report %hhu size %d\n", raw_data[0], |
| 990 | 1013 | size); |
| 991 | 1014 | |
| @@ -1160,6 +1183,7 @@ static void wiimote_destroy(struct wiimote_data *wdata) · 168 unmodified lines | ||
| 1160 | 1183 | wiimote_leds_destroy(wdata); |
| 1161 | 1184 | |
| 1162 | 1185 | power_supply_unregister(&wdata->battery); |
| 1186 | + kfree(wdata->battery.name); | |
| 1163 | 1187 | input_unregister_device(wdata->accel); |
| 1164 | 1188 | input_unregister_device(wdata->ir); |
| 1165 | 1189 | input_unregister_device(wdata->input); |
| @@ -1216,9 +1240,14 @@ static int wiimote_hid_probe(struct hid_device *hdev, · 50 unmodified lines | ||
| 1216 | 1240 | wdata->battery.properties = wiimote_battery_props; |
| 1217 | 1241 | wdata->battery.num_properties = ARRAY_SIZE(wiimote_battery_props); |
| 1218 | 1242 | wdata->battery.get_property = wiimote_battery_get_property; |
| 1219 | − wdata->battery.name = "wiimote_battery"; | |
| 1220 | 1243 | wdata->battery.type = POWER_SUPPLY_TYPE_BATTERY; |
| 1221 | 1244 | wdata->battery.use_for_apm = 0; |
| 1245 | + wdata->battery.name = kasprintf(GFP_KERNEL, "wiimote_battery_%s", | |
| 1246 | + wdata->hdev->uniq); | |
| 1247 | + if (!wdata->battery.name) { | |
| 1248 | + ret = -ENOMEM; | |
| 1249 | + goto err_battery_name; | |
| 1250 | + } | |
| 1222 | 1251 | |
| 1223 | 1252 | ret = power_supply_register(&wdata->hdev->dev, &wdata->battery); |
| 1224 | 1253 | if (ret) { |
| @@ -1254,6 +1283,8 @@ err_free: · 29 unmodified lines | ||
| 1254 | 1283 | return ret; |
| 1255 | 1284 | |
| 1256 | 1285 | err_battery: |
| 1286 | + kfree(wdata->battery.name); | |
| 1287 | +err_battery_name: | |
| 1257 | 1288 | input_unregister_device(wdata->input); |
| 1258 | 1289 | wdata->input = NULL; |
| 1259 | 1290 | err_input: |
| @@ -1283,6 +1314,8 @@ static void wiimote_hid_remove(struct hid_device *hdev) · 23 unmodified lines | ||
| 1283 | 1314 | static const struct hid_device_id wiimote_hid_devices[] = { |
| 1284 | 1315 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO, |
| 1285 | 1316 | USB_DEVICE_ID_NINTENDO_WIIMOTE) }, |
| 1317 | + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO, | |
| 1318 | + USB_DEVICE_ID_NINTENDO_WIIMOTE2) }, | |
| 1286 | 1319 | { } |
| 1287 | 1320 | }; |
| 1288 | 1321 | MODULE_DEVICE_TABLE(hid, wiimote_hid_devices); |
| @@ -24,13 +24,11 @@ · 23 unmodified lines | ||
| 24 | 24 | #include <linux/hid.h> |
| 25 | 25 | #include <linux/input.h> |
| 26 | 26 | #include <linux/slab.h> |
| 27 | −#include <linux/usb.h> | |
| 28 | 27 | #include <linux/module.h> |
| 29 | 28 | |
| 30 | 29 | #include "hid-ids.h" |
| 31 | 30 | |
| 32 | 31 | #ifdef CONFIG_ZEROPLUS_FF |
| 33 | −#include "usbhid/usbhid.h" | |
| 34 | 32 | |
| 35 | 33 | struct zpff_device { |
| 36 | 34 | struct hid_report *report; |
| @@ -59,7 +57,7 @@ static int zpff_play(struct input_dev *dev, void *data, · 22 unmodified lines | ||
| 59 | 57 | zpff->report->field[2]->value[0] = left; |
| 60 | 58 | zpff->report->field[3]->value[0] = right; |
| 61 | 59 | dbg_hid("running with 0x%02x 0x%02x\n", left, right); |
| 62 | − usbhid_submit_report(hid, zpff->report, USB_DIR_OUT); | |
| 60 | + hid_hw_request(hid, zpff->report, HID_REQ_SET_REPORT); | |
| 63 | 61 | |
| 64 | 62 | return 0; |
| 65 | 63 | } |
| @@ -104,7 +102,7 @@ static int zpff_init(struct hid_device *hid) · 38 unmodified lines | ||
| 104 | 102 | zpff->report->field[1]->value[0] = 0x02; |
| 105 | 103 | zpff->report->field[2]->value[0] = 0x00; |
| 106 | 104 | zpff->report->field[3]->value[0] = 0x00; |
| 107 | − usbhid_submit_report(hid, zpff->report, USB_DIR_OUT); | |
| 105 | + hid_hw_request(hid, zpff->report, HID_REQ_SET_REPORT); | |
| 108 | 106 | |
| 109 | 107 | hid_info(hid, "force feedback for Zeroplus based devices by Anssi Hannula <anssi.hannula@gmail.com>\n"); |
| 110 | 108 | |
| @@ -563,6 +563,36 @@ static int i2c_hid_output_raw_report(struct hid_device *hid, __u8 *buf, · 562 unmodified lines | ||
| 563 | 563 | return ret; |
| 564 | 564 | } |
| 565 | 565 | |
| 566 | +static void i2c_hid_request(struct hid_device *hid, struct hid_report *rep, | |
| 567 | + int reqtype) | |
| 568 | +{ | |
| 569 | + struct i2c_client *client = hid->driver_data; | |
| 570 | + char *buf; | |
| 571 | + int ret; | |
| 572 | + int len = i2c_hid_get_report_length(rep) - 2; | |
| 573 | + | |
| 574 | + buf = kzalloc(len, GFP_KERNEL); | |
| 575 | + if (!buf) | |
| 576 | + return; | |
| 577 | + | |
| 578 | + switch (reqtype) { | |
| 579 | + case HID_REQ_GET_REPORT: | |
| 580 | + ret = i2c_hid_get_raw_report(hid, rep->id, buf, len, rep->type); | |
| 581 | + if (ret < 0) | |
| 582 | + dev_err(&client->dev, "%s: unable to get report: %d\n", | |
| 583 | + __func__, ret); | |
| 584 | + else | |
| 585 | + hid_input_report(hid, rep->type, buf, ret, 0); | |
| 586 | + break; | |
| 587 | + case HID_REQ_SET_REPORT: | |
| 588 | + hid_output_report(rep, buf); | |
| 589 | + i2c_hid_output_raw_report(hid, buf, len, rep->type); | |
| 590 | + break; | |
| 591 | + } | |
| 592 | + | |
| 593 | + kfree(buf); | |
| 594 | +} | |
| 595 | + | |
| 566 | 596 | static int i2c_hid_parse(struct hid_device *hid) |
| 567 | 597 | { |
| 568 | 598 | struct i2c_client *client = hid->driver_data; |
| @@ -742,6 +772,7 @@ static struct hid_ll_driver i2c_hid_ll_driver = { · 173 unmodified lines | ||
| 742 | 772 | .open = i2c_hid_open, |
| 743 | 773 | .close = i2c_hid_close, |
| 744 | 774 | .power = i2c_hid_power, |
| 775 | + .request = i2c_hid_request, | |
| 745 | 776 | .hidinput_input_event = i2c_hid_hidinput_input_event, |
| 746 | 777 | }; |
| 747 | 778 | |
| @@ -639,7 +639,7 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re · 638 unmodified lines | ||
| 639 | 639 | } |
| 640 | 640 | } |
| 641 | 641 | |
| 642 | −void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir) | |
| 642 | +static void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir) | |
| 643 | 643 | { |
| 644 | 644 | struct usbhid_device *usbhid = hid->driver_data; |
| 645 | 645 | unsigned long flags; |
| @@ -648,7 +648,6 @@ void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, uns · 2 unmodified lines | ||
| 648 | 648 | __usbhid_submit_report(hid, report, dir); |
| 649 | 649 | spin_unlock_irqrestore(&usbhid->lock, flags); |
| 650 | 650 | } |
| 651 | −EXPORT_SYMBOL_GPL(usbhid_submit_report); | |
| 652 | 651 | |
| 653 | 652 | /* Workqueue routine to send requests to change LEDs */ |
| 654 | 653 | 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 · 51 unmodified lines | ||
| 706 | 705 | return 0; |
| 707 | 706 | } |
| 708 | 707 | |
| 709 | −int usbhid_wait_io(struct hid_device *hid) | |
| 708 | +static int usbhid_wait_io(struct hid_device *hid) | |
| 710 | 709 | { |
| 711 | 710 | struct usbhid_device *usbhid = hid->driver_data; |
| 712 | 711 | |
| @@ -720,7 +719,6 @@ int usbhid_wait_io(struct hid_device *hid) · 7 unmodified lines | ||
| 720 | 719 | |
| 721 | 720 | return 0; |
| 722 | 721 | } |
| 723 | −EXPORT_SYMBOL_GPL(usbhid_wait_io); | |
| 724 | 722 | |
| 725 | 723 | static int hid_set_idle(struct usb_device *dev, int ifnum, int report, int idle) |
| 726 | 724 | { |
| @@ -1243,6 +1241,32 @@ static int usbhid_power(struct hid_device *hid, int lvl) · 516 unmodified lines | ||
| 1243 | 1241 | return r; |
| 1244 | 1242 | } |
| 1245 | 1243 | |
| 1244 | +static void usbhid_request(struct hid_device *hid, struct hid_report *rep, int reqtype) | |
| 1245 | +{ | |
| 1246 | + switch (reqtype) { | |
| 1247 | + case HID_REQ_GET_REPORT: | |
| 1248 | + usbhid_submit_report(hid, rep, USB_DIR_IN); | |
| 1249 | + break; | |
| 1250 | + case HID_REQ_SET_REPORT: | |
| 1251 | + usbhid_submit_report(hid, rep, USB_DIR_OUT); | |
| 1252 | + break; | |
| 1253 | + } | |
| 1254 | +} | |
| 1255 | + | |
| 1256 | +static int usbhid_idle(struct hid_device *hid, int report, int idle, | |
| 1257 | + int reqtype) | |
| 1258 | +{ | |
| 1259 | + struct usb_device *dev = hid_to_usb_dev(hid); | |
| 1260 | + struct usb_interface *intf = to_usb_interface(hid->dev.parent); | |
| 1261 | + struct usb_host_interface *interface = intf->cur_altsetting; | |
| 1262 | + int ifnum = interface->desc.bInterfaceNumber; | |
| 1263 | + | |
| 1264 | + if (reqtype != HID_REQ_SET_IDLE) | |
| 1265 | + return -EINVAL; | |
| 1266 | + | |
| 1267 | + return hid_set_idle(dev, ifnum, report, idle); | |
| 1268 | +} | |
| 1269 | + | |
| 1246 | 1270 | static struct hid_ll_driver usb_hid_driver = { |
| 1247 | 1271 | .parse = usbhid_parse, |
| 1248 | 1272 | .start = usbhid_start, |
| @@ -1251,6 +1275,9 @@ static struct hid_ll_driver usb_hid_driver = { · 2 unmodified lines | ||
| 1251 | 1275 | .close = usbhid_close, |
| 1252 | 1276 | .power = usbhid_power, |
| 1253 | 1277 | .hidinput_input_event = usb_hidinput_input_event, |
| 1278 | + .request = usbhid_request, | |
| 1279 | + .wait = usbhid_wait_io, | |
| 1280 | + .idle = usbhid_idle, | |
| 1254 | 1281 | }; |
| 1255 | 1282 | |
| 1256 | 1283 | static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id *id) |
| @@ -263,8 +263,8 @@ static void pidff_set_envelope_report(struct pidff_device *pidff, · 262 unmodified lines | ||
| 263 | 263 | envelope->attack_level, |
| 264 | 264 | pidff->set_envelope[PID_ATTACK_LEVEL].value[0]); |
| 265 | 265 | |
| 266 | − usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_ENVELOPE], | |
| 267 | − USB_DIR_OUT); | |
| 266 | + hid_hw_request(pidff->hid, pidff->reports[PID_SET_ENVELOPE], | |
| 267 | + HID_REQ_SET_REPORT); | |
| 268 | 268 | } |
| 269 | 269 | |
| 270 | 270 | /* |
| @@ -290,8 +290,8 @@ static void pidff_set_constant_force_report(struct pidff_device *pidff, · 19 unmodified lines | ||
| 290 | 290 | pidff_set_signed(&pidff->set_constant[PID_MAGNITUDE], |
| 291 | 291 | effect->u.constant.level); |
| 292 | 292 | |
| 293 | − usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_CONSTANT], | |
| 294 | − USB_DIR_OUT); | |
| 293 | + hid_hw_request(pidff->hid, pidff->reports[PID_SET_CONSTANT], | |
| 294 | + HID_REQ_SET_REPORT); | |
| 295 | 295 | } |
| 296 | 296 | |
| 297 | 297 | /* |
| @@ -325,8 +325,8 @@ static void pidff_set_effect_report(struct pidff_device *pidff, · 27 unmodified lines | ||
| 325 | 325 | pidff->effect_direction); |
| 326 | 326 | pidff->set_effect[PID_START_DELAY].value[0] = effect->replay.delay; |
| 327 | 327 | |
| 328 | − usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT], | |
| 329 | − USB_DIR_OUT); | |
| 328 | + hid_hw_request(pidff->hid, pidff->reports[PID_SET_EFFECT], | |
| 329 | + HID_REQ_SET_REPORT); | |
| 330 | 330 | } |
| 331 | 331 | |
| 332 | 332 | /* |
| @@ -357,8 +357,8 @@ static void pidff_set_periodic_report(struct pidff_device *pidff, · 24 unmodified lines | ||
| 357 | 357 | pidff_set(&pidff->set_periodic[PID_PHASE], effect->u.periodic.phase); |
| 358 | 358 | pidff->set_periodic[PID_PERIOD].value[0] = effect->u.periodic.period; |
| 359 | 359 | |
| 360 | − usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_PERIODIC], | |
| 361 | − USB_DIR_OUT); | |
| 360 | + hid_hw_request(pidff->hid, pidff->reports[PID_SET_PERIODIC], | |
| 361 | + HID_REQ_SET_REPORT); | |
| 362 | 362 | |
| 363 | 363 | } |
| 364 | 364 | |
| @@ -399,8 +399,8 @@ static void pidff_set_condition_report(struct pidff_device *pidff, · 34 unmodified lines | ||
| 399 | 399 | effect->u.condition[i].left_saturation); |
| 400 | 400 | pidff_set(&pidff->set_condition[PID_DEAD_BAND], |
| 401 | 401 | effect->u.condition[i].deadband); |
| 402 | − usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_CONDITION], | |
| 403 | − USB_DIR_OUT); | |
| 402 | + hid_hw_request(pidff->hid, pidff->reports[PID_SET_CONDITION], | |
| 403 | + HID_REQ_SET_REPORT); | |
| 404 | 404 | } |
| 405 | 405 | } |
| 406 | 406 | |
| @@ -440,8 +440,8 @@ static void pidff_set_ramp_force_report(struct pidff_device *pidff, · 33 unmodified lines | ||
| 440 | 440 | effect->u.ramp.start_level); |
| 441 | 441 | pidff_set_signed(&pidff->set_ramp[PID_RAMP_END], |
| 442 | 442 | effect->u.ramp.end_level); |
| 443 | − usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_RAMP], | |
| 444 | − USB_DIR_OUT); | |
| 443 | + hid_hw_request(pidff->hid, pidff->reports[PID_SET_RAMP], | |
| 444 | + HID_REQ_SET_REPORT); | |
| 445 | 445 | } |
| 446 | 446 | |
| 447 | 447 | /* |
| @@ -465,19 +465,19 @@ static int pidff_request_effect_upload(struct pidff_device *pidff, int efnum) · 17 unmodified lines | ||
| 465 | 465 | int j; |
| 466 | 466 | |
| 467 | 467 | pidff->create_new_effect_type->value[0] = efnum; |
| 468 | − usbhid_submit_report(pidff->hid, pidff->reports[PID_CREATE_NEW_EFFECT], | |
| 469 | − USB_DIR_OUT); | |
| 468 | + hid_hw_request(pidff->hid, pidff->reports[PID_CREATE_NEW_EFFECT], | |
| 469 | + HID_REQ_SET_REPORT); | |
| 470 | 470 | hid_dbg(pidff->hid, "create_new_effect sent, type: %d\n", efnum); |
| 471 | 471 | |
| 472 | 472 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0] = 0; |
| 473 | 473 | pidff->block_load_status->value[0] = 0; |
| 474 | − usbhid_wait_io(pidff->hid); | |
| 474 | + hid_hw_wait(pidff->hid); | |
| 475 | 475 | |
| 476 | 476 | for (j = 0; j < 60; j++) { |
| 477 | 477 | hid_dbg(pidff->hid, "pid_block_load requested\n"); |
| 478 | − usbhid_submit_report(pidff->hid, pidff->reports[PID_BLOCK_LOAD], | |
| 479 | − USB_DIR_IN); | |
| 480 | − usbhid_wait_io(pidff->hid); | |
| 478 | + hid_hw_request(pidff->hid, pidff->reports[PID_BLOCK_LOAD], | |
| 479 | + HID_REQ_GET_REPORT); | |
| 480 | + hid_hw_wait(pidff->hid); | |
| 481 | 481 | if (pidff->block_load_status->value[0] == |
| 482 | 482 | pidff->status_id[PID_BLOCK_LOAD_SUCCESS]) { |
| 483 | 483 | 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) · 29 unmodified lines | ||
| 513 | 513 | pidff->effect_operation[PID_LOOP_COUNT].value[0] = n; |
| 514 | 514 | } |
| 515 | 515 | |
| 516 | − usbhid_submit_report(pidff->hid, pidff->reports[PID_EFFECT_OPERATION], | |
| 517 | − USB_DIR_OUT); | |
| 516 | + hid_hw_request(pidff->hid, pidff->reports[PID_EFFECT_OPERATION], | |
| 517 | + HID_REQ_SET_REPORT); | |
| 518 | 518 | } |
| 519 | 519 | |
| 520 | 520 | /** |
| @@ -535,8 +535,8 @@ static int pidff_playback(struct input_dev *dev, int effect_id, int value) · 14 unmodified lines | ||
| 535 | 535 | static void pidff_erase_pid(struct pidff_device *pidff, int pid_id) |
| 536 | 536 | { |
| 537 | 537 | pidff->block_free[PID_EFFECT_BLOCK_INDEX].value[0] = pid_id; |
| 538 | − usbhid_submit_report(pidff->hid, pidff->reports[PID_BLOCK_FREE], | |
| 539 | − USB_DIR_OUT); | |
| 538 | + hid_hw_request(pidff->hid, pidff->reports[PID_BLOCK_FREE], | |
| 539 | + HID_REQ_SET_REPORT); | |
| 540 | 540 | } |
| 541 | 541 | |
| 542 | 542 | /* |
| @@ -551,7 +551,7 @@ static int pidff_erase_effect(struct input_dev *dev, int effect_id) · 8 unmodified lines | ||
| 551 | 551 | effect_id, pidff->pid_id[effect_id]); |
| 552 | 552 | /* Wait for the queue to clear. We do not want a full fifo to |
| 553 | 553 | prevent the effect removal. */ |
| 554 | − usbhid_wait_io(pidff->hid); | |
| 554 | + hid_hw_wait(pidff->hid); | |
| 555 | 555 | pidff_playback_pid(pidff, pid_id, 0); |
| 556 | 556 | pidff_erase_pid(pidff, pid_id); |
| 557 | 557 | |
| @@ -718,8 +718,8 @@ static void pidff_set_gain(struct input_dev *dev, u16 gain) · 160 unmodified lines | ||
| 718 | 718 | struct pidff_device *pidff = dev->ff->private; |
| 719 | 719 | |
| 720 | 720 | pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], gain); |
| 721 | − usbhid_submit_report(pidff->hid, pidff->reports[PID_DEVICE_GAIN], | |
| 722 | − USB_DIR_OUT); | |
| 721 | + hid_hw_request(pidff->hid, pidff->reports[PID_DEVICE_GAIN], | |
| 722 | + HID_REQ_SET_REPORT); | |
| 723 | 723 | } |
| 724 | 724 | |
| 725 | 725 | static void pidff_autocenter(struct pidff_device *pidff, u16 magnitude) |
| @@ -744,8 +744,8 @@ static void pidff_autocenter(struct pidff_device *pidff, u16 magnitude) · 18 unmodified lines | ||
| 744 | 744 | pidff->set_effect[PID_DIRECTION_ENABLE].value[0] = 1; |
| 745 | 745 | pidff->set_effect[PID_START_DELAY].value[0] = 0; |
| 746 | 746 | |
| 747 | − usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT], | |
| 748 | − USB_DIR_OUT); | |
| 747 | + hid_hw_request(pidff->hid, pidff->reports[PID_SET_EFFECT], | |
| 748 | + HID_REQ_SET_REPORT); | |
| 749 | 749 | } |
| 750 | 750 | |
| 751 | 751 | /* |
| @@ -1158,19 +1158,19 @@ static void pidff_reset(struct pidff_device *pidff) · 406 unmodified lines | ||
| 1158 | 1158 | |
| 1159 | 1159 | pidff->device_control->value[0] = pidff->control_id[PID_RESET]; |
| 1160 | 1160 | /* We reset twice as sometimes hid_wait_io isn't waiting long enough */ |
| 1161 | − usbhid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT); | |
| 1162 | − usbhid_wait_io(hid); | |
| 1163 | − usbhid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT); | |
| 1164 | − usbhid_wait_io(hid); | |
| 1161 | + hid_hw_request(hid, pidff->reports[PID_DEVICE_CONTROL], HID_REQ_SET_REPORT); | |
| 1162 | + hid_hw_wait(hid); | |
| 1163 | + hid_hw_request(hid, pidff->reports[PID_DEVICE_CONTROL], HID_REQ_SET_REPORT); | |
| 1164 | + hid_hw_wait(hid); | |
| 1165 | 1165 | |
| 1166 | 1166 | pidff->device_control->value[0] = |
| 1167 | 1167 | pidff->control_id[PID_ENABLE_ACTUATORS]; |
| 1168 | − usbhid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT); | |
| 1169 | − usbhid_wait_io(hid); | |
| 1168 | + hid_hw_request(hid, pidff->reports[PID_DEVICE_CONTROL], HID_REQ_SET_REPORT); | |
| 1169 | + hid_hw_wait(hid); | |
| 1170 | 1170 | |
| 1171 | 1171 | /* pool report is sometimes messed up, refetch it */ |
| 1172 | − usbhid_submit_report(hid, pidff->reports[PID_POOL], USB_DIR_IN); | |
| 1173 | − usbhid_wait_io(hid); | |
| 1172 | + hid_hw_request(hid, pidff->reports[PID_POOL], HID_REQ_GET_REPORT); | |
| 1173 | + hid_hw_wait(hid); | |
| 1174 | 1174 | |
| 1175 | 1175 | if (pidff->pool[PID_SIMULTANEOUS_MAX].value) { |
| 1176 | 1176 | while (pidff->pool[PID_SIMULTANEOUS_MAX].value[0] < 2) { |
| @@ -1181,9 +1181,9 @@ static void pidff_reset(struct pidff_device *pidff) · 4 unmodified lines | ||
| 1181 | 1181 | break; |
| 1182 | 1182 | } |
| 1183 | 1183 | hid_dbg(pidff->hid, "pid_pool requested again\n"); |
| 1184 | − usbhid_submit_report(hid, pidff->reports[PID_POOL], | |
| 1185 | − USB_DIR_IN); | |
| 1186 | − usbhid_wait_io(hid); | |
| 1184 | + hid_hw_request(hid, pidff->reports[PID_POOL], | |
| 1185 | + HID_REQ_GET_REPORT); | |
| 1186 | + hid_hw_wait(hid); | |
| 1187 | 1187 | } |
| 1188 | 1188 | } |
| 1189 | 1189 | } |
| @@ -1269,8 +1269,8 @@ int hid_pidff_init(struct hid_device *hid) · 79 unmodified lines | ||
| 1269 | 1269 | |
| 1270 | 1270 | if (test_bit(FF_GAIN, dev->ffbit)) { |
| 1271 | 1271 | pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], 0xffff); |
| 1272 | − usbhid_submit_report(hid, pidff->reports[PID_DEVICE_GAIN], | |
| 1273 | − USB_DIR_OUT); | |
| 1272 | + hid_hw_request(hid, pidff->reports[PID_DEVICE_GAIN], | |
| 1273 | + HID_REQ_SET_REPORT); | |
| 1274 | 1274 | } |
| 1275 | 1275 | |
| 1276 | 1276 | error = pidff_check_autocenter(pidff, dev); |
| @@ -705,8 +705,8 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) · 704 unmodified lines | ||
| 705 | 705 | if (report == NULL) |
| 706 | 706 | break; |
| 707 | 707 | |
| 708 | − usbhid_submit_report(hid, report, USB_DIR_IN); | |
| 709 | − usbhid_wait_io(hid); | |
| 708 | + hid_hw_request(hid, report, HID_REQ_GET_REPORT); | |
| 709 | + hid_hw_wait(hid); | |
| 710 | 710 | |
| 711 | 711 | r = 0; |
| 712 | 712 | break; |
| @@ -724,8 +724,8 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) · 11 unmodified lines | ||
| 724 | 724 | if (report == NULL) |
| 725 | 725 | break; |
| 726 | 726 | |
| 727 | − usbhid_submit_report(hid, report, USB_DIR_OUT); | |
| 728 | − usbhid_wait_io(hid); | |
| 727 | + hid_hw_request(hid, report, HID_REQ_SET_REPORT); | |
| 728 | + hid_hw_wait(hid); | |
| 729 | 729 | |
| 730 | 730 | r = 0; |
| 731 | 731 | break; |
| @@ -34,12 +34,9 @@ · 33 unmodified lines | ||
| 34 | 34 | #include <linux/input.h> |
| 35 | 35 | |
| 36 | 36 | /* API provided by hid-core.c for USB HID drivers */ |
| 37 | −int usbhid_wait_io(struct hid_device* hid); | |
| 38 | 37 | void usbhid_close(struct hid_device *hid); |
| 39 | 38 | int usbhid_open(struct hid_device *hid); |
| 40 | 39 | void usbhid_init_reports(struct hid_device *hid); |
| 41 | −void usbhid_submit_report | |
| 42 | −(struct hid_device *hid, struct hid_report *report, unsigned char dir); | |
| 43 | 40 | int usbhid_get_power(struct hid_device *hid); |
| 44 | 41 | void usbhid_put_power(struct hid_device *hid); |
| 45 | 42 | struct usb_interface *usbhid_find_interface(int minor); |
| @@ -22,11 +22,12 @@ · 21 unmodified lines | ||
| 22 | 22 | * |
| 23 | 23 | */ |
| 24 | 24 | |
| 25 | −#define HID_DEBUG_BUFSIZE 512 | |
| 26 | − | |
| 27 | 25 | #ifdef CONFIG_DEBUG_FS |
| 28 | 26 | |
| 27 | +#define HID_DEBUG_BUFSIZE 512 | |
| 28 | + | |
| 29 | 29 | void hid_dump_input(struct hid_device *, struct hid_usage *, __s32); |
| 30 | +void hid_dump_report(struct hid_device *, int , u8 *, int); | |
| 30 | 31 | void hid_dump_device(struct hid_device *, struct seq_file *); |
| 31 | 32 | void hid_dump_field(struct hid_field *, int, struct seq_file *); |
| 32 | 33 | char *hid_resolv_usage(unsigned, struct seq_file *); |
| @@ -50,6 +51,7 @@ struct hid_debug_list { · 17 unmodified lines | ||
| 50 | 51 | #else |
| 51 | 52 | |
| 52 | 53 | #define hid_dump_input(a,b,c) do { } while (0) |
| 54 | +#define hid_dump_report(a,b,c,d) do { } while (0) | |
| 53 | 55 | #define hid_dump_device(a,b) do { } while (0) |
| 54 | 56 | #define hid_dump_field(a,b,c) do { } while (0) |
| 55 | 57 | #define hid_resolv_usage(a,b) do { } while (0) |
| @@ -282,6 +282,7 @@ struct hid_item { · 281 unmodified lines | ||
| 282 | 282 | #define HID_QUIRK_BADPAD 0x00000020 |
| 283 | 283 | #define HID_QUIRK_MULTI_INPUT 0x00000040 |
| 284 | 284 | #define HID_QUIRK_HIDINPUT_FORCE 0x00000080 |
| 285 | +#define HID_QUIRK_NO_EMPTY_INPUT 0x00000100 | |
| 285 | 286 | #define HID_QUIRK_SKIP_OUTPUT_REPORTS 0x00010000 |
| 286 | 287 | #define HID_QUIRK_FULLSPEED_INTERVAL 0x10000000 |
| 287 | 288 | #define HID_QUIRK_NO_INIT_REPORTS 0x20000000 |
| @@ -456,7 +457,8 @@ struct hid_device { /* device report descriptor */ · 168 unmodified lines | ||
| 456 | 457 | unsigned country; /* HID country */ |
| 457 | 458 | struct hid_report_enum report_enum[HID_REPORT_TYPES]; |
| 458 | 459 | |
| 459 | − struct semaphore driver_lock; /* protects the current driver */ | |
| 460 | + struct semaphore driver_lock; /* protects the current driver, except during input */ | |
| 461 | + struct semaphore driver_input_lock; /* protects the current driver */ | |
| 460 | 462 | struct device dev; /* device */ |
| 461 | 463 | struct hid_driver *driver; |
| 462 | 464 | struct hid_ll_driver *ll_driver; |
| @@ -477,6 +479,7 @@ struct hid_device { /* device report descriptor */ · 14 unmodified lines | ||
| 477 | 479 | unsigned int status; /* see STAT flags above */ |
| 478 | 480 | unsigned claimed; /* Claimed by hidinput, hiddev? */ |
| 479 | 481 | unsigned quirks; /* Various quirks the device can pull on us */ |
| 482 | + bool io_started; /* Protected by driver_lock. If IO has started */ | |
| 480 | 483 | |
| 481 | 484 | struct list_head inputs; /* The list of inputs */ |
| 482 | 485 | void *hiddev; /* The hiddev structure */ |
| @@ -512,6 +515,7 @@ struct hid_device { /* device report descriptor */ · 29 unmodified lines | ||
| 512 | 515 | struct dentry *debug_rdesc; |
| 513 | 516 | struct dentry *debug_events; |
| 514 | 517 | struct list_head debug_list; |
| 518 | + struct mutex debug_list_lock; | |
| 515 | 519 | wait_queue_head_t debug_wait; |
| 516 | 520 | }; |
| 517 | 521 | |
| @@ -599,6 +603,10 @@ struct hid_usage_id { · 81 unmodified lines | ||
| 599 | 603 | * @resume: invoked on resume if device was not reset (NULL means nop) |
| 600 | 604 | * @reset_resume: invoked on resume if device was reset (NULL means nop) |
| 601 | 605 | * |
| 606 | + * probe should return -errno on error, or 0 on success. During probe, | |
| 607 | + * input will not be passed to raw_event unless hid_device_io_start is | |
| 608 | + * called. | |
| 609 | + * | |
| 602 | 610 | * raw_event and event should return 0 on no action performed, 1 when no |
| 603 | 611 | * further processing should be done and negative on error |
| 604 | 612 | * |
| @@ -662,6 +670,9 @@ struct hid_driver { · 57 unmodified lines | ||
| 662 | 670 | * @hidinput_input_event: event input event (e.g. ff or leds) |
| 663 | 671 | * @parse: this method is called only once to parse the device data, |
| 664 | 672 | * shouldn't allocate anything to not leak memory |
| 673 | + * @request: send report request to device (e.g. feature report) | |
| 674 | + * @wait: wait for buffered io to complete (send/recv reports) | |
| 675 | + * @idle: send idle request to device | |
| 665 | 676 | */ |
| 666 | 677 | struct hid_ll_driver { |
| 667 | 678 | int (*start)(struct hid_device *hdev); |
| @@ -676,6 +687,13 @@ struct hid_ll_driver { · 8 unmodified lines | ||
| 676 | 687 | unsigned int code, int value); |
| 677 | 688 | |
| 678 | 689 | int (*parse)(struct hid_device *hdev); |
| 690 | + | |
| 691 | + void (*request)(struct hid_device *hdev, | |
| 692 | + struct hid_report *report, int reqtype); | |
| 693 | + | |
| 694 | + int (*wait)(struct hid_device *hdev); | |
| 695 | + int (*idle)(struct hid_device *hdev, int report, int idle, int reqtype); | |
| 696 | + | |
| 679 | 697 | }; |
| 680 | 698 | |
| 681 | 699 | #define PM_HINT_FULLON 1<<5 |
| @@ -737,6 +755,44 @@ const struct hid_device_id *hid_match_id(struct hid_device *hdev, · 55 unmodified lines | ||
| 737 | 755 | const struct hid_device_id *id); |
| 738 | 756 | s32 hid_snto32(__u32 value, unsigned n); |
| 739 | 757 | |
| 758 | +/** | |
| 759 | + * hid_device_io_start - enable HID input during probe, remove | |
| 760 | + * | |
| 761 | + * @hid - the device | |
| 762 | + * | |
| 763 | + * This should only be called during probe or remove and only be | |
| 764 | + * called by the thread calling probe or remove. It will allow | |
| 765 | + * incoming packets to be delivered to the driver. | |
| 766 | + */ | |
| 767 | +static inline void hid_device_io_start(struct hid_device *hid) { | |
| 768 | + if (hid->io_started) { | |
| 769 | + dev_warn(&hid->dev, "io already started"); | |
| 770 | + return; | |
| 771 | + } | |
| 772 | + hid->io_started = true; | |
| 773 | + up(&hid->driver_input_lock); | |
| 774 | +} | |
| 775 | + | |
| 776 | +/** | |
| 777 | + * hid_device_io_stop - disable HID input during probe, remove | |
| 778 | + * | |
| 779 | + * @hid - the device | |
| 780 | + * | |
| 781 | + * Should only be called after hid_device_io_start. It will prevent | |
| 782 | + * incoming packets from going to the driver for the duration of | |
| 783 | + * probe, remove. If called during probe, packets will still go to the | |
| 784 | + * driver after probe is complete. This function should only be called | |
| 785 | + * by the thread calling probe or remove. | |
| 786 | + */ | |
| 787 | +static inline void hid_device_io_stop(struct hid_device *hid) { | |
| 788 | + if (!hid->io_started) { | |
| 789 | + dev_warn(&hid->dev, "io already stopped"); | |
| 790 | + return; | |
| 791 | + } | |
| 792 | + hid->io_started = false; | |
| 793 | + down(&hid->driver_input_lock); | |
| 794 | +} | |
| 795 | + | |
| 740 | 796 | /** |
| 741 | 797 | * hid_map_usage - map usage input bits |
| 742 | 798 | * |
| @@ -883,6 +939,49 @@ static inline int hid_hw_power(struct hid_device *hdev, int level) · 140 unmodified lines | ||
| 883 | 939 | return hdev->ll_driver->power ? hdev->ll_driver->power(hdev, level) : 0; |
| 884 | 940 | } |
| 885 | 941 | |
| 942 | + | |
| 943 | +/** | |
| 944 | + * hid_hw_request - send report request to device | |
| 945 | + * | |
| 946 | + * @hdev: hid device | |
| 947 | + * @report: report to send | |
| 948 | + * @reqtype: hid request type | |
| 949 | + */ | |
| 950 | +static inline void hid_hw_request(struct hid_device *hdev, | |
| 951 | + struct hid_report *report, int reqtype) | |
| 952 | +{ | |
| 953 | + if (hdev->ll_driver->request) | |
| 954 | + hdev->ll_driver->request(hdev, report, reqtype); | |
| 955 | +} | |
| 956 | + | |
| 957 | +/** | |
| 958 | + * hid_hw_idle - send idle request to device | |
| 959 | + * | |
| 960 | + * @hdev: hid device | |
| 961 | + * @report: report to control | |
| 962 | + * @idle: idle state | |
| 963 | + * @reqtype: hid request type | |
| 964 | + */ | |
| 965 | +static inline int hid_hw_idle(struct hid_device *hdev, int report, int idle, | |
| 966 | + int reqtype) | |
| 967 | +{ | |
| 968 | + if (hdev->ll_driver->idle) | |
| 969 | + return hdev->ll_driver->idle(hdev, report, idle, reqtype); | |
| 970 | + | |
| 971 | + return 0; | |
| 972 | +} | |
| 973 | + | |
| 974 | +/** | |
| 975 | + * hid_hw_wait - wait for buffered io to complete | |
| 976 | + * | |
| 977 | + * @hdev: hid device | |
| 978 | + */ | |
| 979 | +static inline void hid_hw_wait(struct hid_device *hdev) | |
| 980 | +{ | |
| 981 | + if (hdev->ll_driver->wait) | |
| 982 | + hdev->ll_driver->wait(hdev); | |
| 983 | +} | |
| 984 | + | |
| 886 | 985 | int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size, |
| 887 | 986 | int interrupt); |
| 888 | 987 | |
| @@ -17,10 +17,9 @@ · 16 unmodified lines | ||
| 17 | 17 | /* |
| 18 | 18 | * Ugly hack to work around failing compilation on systems that don't |
| 19 | 19 | * yet populate new version of hidraw.h to userspace. |
| 20 | − * | |
| 21 | − * If you need this, please have your distro update the kernel headers. | |
| 22 | 20 | */ |
| 23 | 21 | #ifndef HIDIOCSFEATURE |
| 22 | +#warning Please have your distro update the userspace kernel headers | |
| 24 | 23 | #define HIDIOCSFEATURE(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x06, len) |
| 25 | 24 | #define HIDIOCGFEATURE(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x07, len) |
| 26 | 25 | #endif |