diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /drivers/hid | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'drivers/hid')
76 files changed, 8939 insertions, 3128 deletions
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 6369ba7f96f8..36ca465c00ce 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig | |||
@@ -55,31 +55,31 @@ source "drivers/hid/usbhid/Kconfig" | |||
55 | menu "Special HID drivers" | 55 | menu "Special HID drivers" |
56 | depends on HID | 56 | depends on HID |
57 | 57 | ||
58 | config HID_3M_PCT | 58 | config HID_A4TECH |
59 | tristate "3M PCT" | 59 | tristate "A4 tech mice" if EXPERT |
60 | depends on USB_HID | 60 | depends on USB_HID |
61 | default !EXPERT | ||
61 | ---help--- | 62 | ---help--- |
62 | Support for 3M PCT touch screens. | 63 | Support for A4 tech X5 and WOP-35 / Trust 450L mice. |
63 | 64 | ||
64 | config HID_A4TECH | 65 | config HID_ACRUX |
65 | tristate "A4 tech" if EMBEDDED | 66 | tristate "ACRUX game controller support" |
66 | depends on USB_HID | 67 | depends on USB_HID |
67 | default !EMBEDDED | ||
68 | ---help--- | 68 | ---help--- |
69 | Support for A4 tech X5 and WOP-35 / Trust 450L mice. | 69 | Say Y here if you want to enable support for ACRUX game controllers. |
70 | 70 | ||
71 | config HID_ACRUX_FF | 71 | config HID_ACRUX_FF |
72 | tristate "ACRUX force feedback support" | 72 | tristate "ACRUX force feedback support" |
73 | depends on USB_HID | 73 | depends on HID_ACRUX |
74 | select INPUT_FF_MEMLESS | 74 | select INPUT_FF_MEMLESS |
75 | ---help--- | 75 | ---help--- |
76 | Say Y here if you want to enable force feedback support for ACRUX | 76 | Say Y here if you want to enable force feedback support for ACRUX |
77 | game controllers. | 77 | game controllers. |
78 | 78 | ||
79 | config HID_APPLE | 79 | config HID_APPLE |
80 | tristate "Apple" if EMBEDDED | 80 | tristate "Apple {i,Power,Mac}Books" if EXPERT |
81 | depends on (USB_HID || BT_HIDP) | 81 | depends on (USB_HID || BT_HIDP) |
82 | default !EMBEDDED | 82 | default !EXPERT |
83 | ---help--- | 83 | ---help--- |
84 | Support for some Apple devices which less or more break | 84 | Support for some Apple devices which less or more break |
85 | HID specification. | 85 | HID specification. |
@@ -88,29 +88,23 @@ config HID_APPLE | |||
88 | MacBooks, MacBook Pros and Apple Aluminum. | 88 | MacBooks, MacBook Pros and Apple Aluminum. |
89 | 89 | ||
90 | config HID_BELKIN | 90 | config HID_BELKIN |
91 | tristate "Belkin" if EMBEDDED | 91 | tristate "Belkin Flip KVM and Wireless keyboard" if EXPERT |
92 | depends on USB_HID | 92 | depends on USB_HID |
93 | default !EMBEDDED | 93 | default !EXPERT |
94 | ---help--- | 94 | ---help--- |
95 | Support for Belkin Flip KVM and Wireless keyboard. | 95 | Support for Belkin Flip KVM and Wireless keyboard. |
96 | 96 | ||
97 | config HID_CANDO | ||
98 | tristate "Cando dual touch panel" | ||
99 | depends on USB_HID | ||
100 | ---help--- | ||
101 | Support for Cando dual touch panel. | ||
102 | |||
103 | config HID_CHERRY | 97 | config HID_CHERRY |
104 | tristate "Cherry" if EMBEDDED | 98 | tristate "Cherry Cymotion keyboard" if EXPERT |
105 | depends on USB_HID | 99 | depends on USB_HID |
106 | default !EMBEDDED | 100 | default !EXPERT |
107 | ---help--- | 101 | ---help--- |
108 | Support for Cherry Cymotion keyboard. | 102 | Support for Cherry Cymotion keyboard. |
109 | 103 | ||
110 | config HID_CHICONY | 104 | config HID_CHICONY |
111 | tristate "Chicony" if EMBEDDED | 105 | tristate "Chicony Tactical pad" if EXPERT |
112 | depends on USB_HID | 106 | depends on USB_HID |
113 | default !EMBEDDED | 107 | default !EXPERT |
114 | ---help--- | 108 | ---help--- |
115 | Support for Chicony Tactical pad. | 109 | Support for Chicony Tactical pad. |
116 | 110 | ||
@@ -130,75 +124,110 @@ config HID_PRODIKEYS | |||
130 | and some additional multimedia keys. | 124 | and some additional multimedia keys. |
131 | 125 | ||
132 | config HID_CYPRESS | 126 | config HID_CYPRESS |
133 | tristate "Cypress" if EMBEDDED | 127 | tristate "Cypress mouse and barcode readers" if EXPERT |
134 | depends on USB_HID | 128 | depends on USB_HID |
135 | default !EMBEDDED | 129 | default !EXPERT |
136 | ---help--- | 130 | ---help--- |
137 | Support for cypress mouse and barcode readers. | 131 | Support for cypress mouse and barcode readers. |
138 | 132 | ||
139 | config HID_DRAGONRISE | 133 | config HID_DRAGONRISE |
140 | tristate "DragonRise Inc. support" | 134 | tristate "DragonRise Inc. game controller" |
141 | depends on USB_HID | 135 | depends on USB_HID |
142 | ---help--- | 136 | ---help--- |
143 | Say Y here if you have DragonRise Inc.game controllers. | 137 | Say Y here if you have DragonRise Inc. game controllers. |
138 | These might be branded as: | ||
139 | - Tesun USB-703 | ||
140 | - Media-tech MT1504 "Rogue" | ||
141 | - DVTech JS19 "Gear" | ||
142 | - Defender Game Master | ||
144 | 143 | ||
145 | config DRAGONRISE_FF | 144 | config DRAGONRISE_FF |
146 | bool "DragonRise Inc. force feedback support" | 145 | bool "DragonRise Inc. force feedback" |
147 | depends on HID_DRAGONRISE | 146 | depends on HID_DRAGONRISE |
148 | select INPUT_FF_MEMLESS | 147 | select INPUT_FF_MEMLESS |
149 | ---help--- | 148 | ---help--- |
150 | Say Y here if you want to enable force feedback support for DragonRise Inc. | 149 | Say Y here if you want to enable force feedback support for DragonRise Inc. |
151 | game controllers. | 150 | game controllers. |
152 | 151 | ||
153 | config HID_EGALAX | 152 | config HID_EMS_FF |
154 | tristate "eGalax multi-touch panel" | 153 | tristate "EMS Production Inc. force feedback support" |
155 | depends on USB_HID | 154 | depends on USB_HID |
155 | select INPUT_FF_MEMLESS | ||
156 | ---help--- | 156 | ---help--- |
157 | Support for the eGalax dual-touch panel. | 157 | Say Y here if you want to enable force feedback support for devices by |
158 | EMS Production Ltd. | ||
159 | Currently the following devices are known to be supported: | ||
160 | - Trio Linker Plus II | ||
158 | 161 | ||
159 | config HID_ELECOM | 162 | config HID_ELECOM |
160 | tristate "ELECOM" | 163 | tristate "ELECOM BM084 bluetooth mouse" |
161 | depends on BT_HIDP | 164 | depends on BT_HIDP |
162 | ---help--- | 165 | ---help--- |
163 | Support for the ELECOM BM084 (bluetooth mouse). | 166 | Support for the ELECOM BM084 (bluetooth mouse). |
164 | 167 | ||
165 | config HID_EZKEY | 168 | config HID_EZKEY |
166 | tristate "Ezkey" if EMBEDDED | 169 | tristate "Ezkey BTC 8193 keyboard" if EXPERT |
167 | depends on USB_HID | 170 | depends on USB_HID |
168 | default !EMBEDDED | 171 | default !EXPERT |
169 | ---help--- | 172 | ---help--- |
170 | Support for Ezkey BTC 8193 keyboard. | 173 | Support for Ezkey BTC 8193 keyboard. |
171 | 174 | ||
175 | config HID_KEYTOUCH | ||
176 | tristate "Keytouch HID devices" | ||
177 | depends on USB_HID | ||
178 | ---help--- | ||
179 | Support for Keytouch HID devices not fully compliant with | ||
180 | the specification. Currently supported: | ||
181 | - Keytouch IEC 60945 | ||
182 | |||
172 | config HID_KYE | 183 | config HID_KYE |
173 | tristate "Kye" if EMBEDDED | 184 | tristate "Kye/Genius Ergo Mouse" if EXPERT |
174 | depends on USB_HID | 185 | depends on USB_HID |
175 | default !EMBEDDED | 186 | default !EXPERT |
176 | ---help--- | 187 | ---help--- |
177 | Support for Kye/Genius Ergo Mouse. | 188 | Support for Kye/Genius Ergo Mouse. |
178 | 189 | ||
190 | config HID_UCLOGIC | ||
191 | tristate "UC-Logic" | ||
192 | depends on USB_HID | ||
193 | ---help--- | ||
194 | Support for UC-Logic tablets. | ||
195 | |||
196 | config HID_WALTOP | ||
197 | tristate "Waltop" | ||
198 | depends on USB_HID | ||
199 | ---help--- | ||
200 | Support for Waltop tablets. | ||
201 | |||
179 | config HID_GYRATION | 202 | config HID_GYRATION |
180 | tristate "Gyration" | 203 | tristate "Gyration remote control" |
181 | depends on USB_HID | 204 | depends on USB_HID |
182 | ---help--- | 205 | ---help--- |
183 | Support for Gyration remote control. | 206 | Support for Gyration remote control. |
184 | 207 | ||
185 | config HID_TWINHAN | 208 | config HID_TWINHAN |
186 | tristate "Twinhan" | 209 | tristate "Twinhan IR remote control" |
187 | depends on USB_HID | 210 | depends on USB_HID |
188 | ---help--- | 211 | ---help--- |
189 | Support for Twinhan IR remote control. | 212 | Support for Twinhan IR remote control. |
190 | 213 | ||
191 | config HID_KENSINGTON | 214 | config HID_KENSINGTON |
192 | tristate "Kensington" if EMBEDDED | 215 | tristate "Kensington Slimblade Trackball" if EXPERT |
193 | depends on USB_HID | 216 | depends on USB_HID |
194 | default !EMBEDDED | 217 | default !EXPERT |
195 | ---help--- | 218 | ---help--- |
196 | Support for Kensington Slimblade Trackball. | 219 | Support for Kensington Slimblade Trackball. |
197 | 220 | ||
221 | config HID_LCPOWER | ||
222 | tristate "LC-Power" | ||
223 | depends on USB_HID | ||
224 | ---help--- | ||
225 | Support for LC-Power RC1000MCE RF remote control. | ||
226 | |||
198 | config HID_LOGITECH | 227 | config HID_LOGITECH |
199 | tristate "Logitech" if EMBEDDED | 228 | tristate "Logitech devices" if EXPERT |
200 | depends on USB_HID | 229 | depends on USB_HID |
201 | default !EMBEDDED | 230 | default !EXPERT |
202 | ---help--- | 231 | ---help--- |
203 | Support for Logitech devices that are not fully compliant with HID standard. | 232 | Support for Logitech devices that are not fully compliant with HID standard. |
204 | 233 | ||
@@ -220,12 +249,12 @@ config LOGITECH_FF | |||
220 | force feedback. | 249 | force feedback. |
221 | 250 | ||
222 | config LOGIRUMBLEPAD2_FF | 251 | config LOGIRUMBLEPAD2_FF |
223 | bool "Logitech Rumblepad 2 force feedback support" | 252 | bool "Logitech RumblePad/Rumblepad 2 force feedback support" |
224 | depends on HID_LOGITECH | 253 | depends on HID_LOGITECH |
225 | select INPUT_FF_MEMLESS | 254 | select INPUT_FF_MEMLESS |
226 | help | 255 | help |
227 | Say Y here if you want to enable force feedback support for Logitech | 256 | Say Y here if you want to enable force feedback support for Logitech |
228 | Rumblepad 2 devices. | 257 | RumblePad and Rumblepad 2 devices. |
229 | 258 | ||
230 | config LOGIG940_FF | 259 | config LOGIG940_FF |
231 | bool "Logitech Flight System G940 force feedback support" | 260 | bool "Logitech Flight System G940 force feedback support" |
@@ -235,6 +264,14 @@ config LOGIG940_FF | |||
235 | Say Y here if you want to enable force feedback support for Logitech | 264 | Say Y here if you want to enable force feedback support for Logitech |
236 | Flight System G940 devices. | 265 | Flight System G940 devices. |
237 | 266 | ||
267 | config LOGIWII_FF | ||
268 | bool "Logitech Speed Force Wireless force feedback support" | ||
269 | depends on HID_LOGITECH | ||
270 | select INPUT_FF_MEMLESS | ||
271 | help | ||
272 | Say Y here if you want to enable force feedback support for Logitech | ||
273 | Speed Force Wireless (Wii) devices. | ||
274 | |||
238 | config HID_MAGICMOUSE | 275 | config HID_MAGICMOUSE |
239 | tristate "Apple MagicMouse multi-touch support" | 276 | tristate "Apple MagicMouse multi-touch support" |
240 | depends on BT_HIDP | 277 | depends on BT_HIDP |
@@ -245,39 +282,73 @@ config HID_MAGICMOUSE | |||
245 | Apple Wireless "Magic" Mouse. | 282 | Apple Wireless "Magic" Mouse. |
246 | 283 | ||
247 | config HID_MICROSOFT | 284 | config HID_MICROSOFT |
248 | tristate "Microsoft" if EMBEDDED | 285 | tristate "Microsoft non-fully HID-compliant devices" if EXPERT |
249 | depends on USB_HID | 286 | depends on USB_HID |
250 | default !EMBEDDED | 287 | default !EXPERT |
251 | ---help--- | 288 | ---help--- |
252 | Support for Microsoft devices that are not fully compliant with HID standard. | 289 | Support for Microsoft devices that are not fully compliant with HID standard. |
253 | 290 | ||
254 | config HID_MOSART | ||
255 | tristate "MosArt" | ||
256 | depends on USB_HID | ||
257 | ---help--- | ||
258 | Support for MosArt dual-touch panels. | ||
259 | |||
260 | config HID_MONTEREY | 291 | config HID_MONTEREY |
261 | tristate "Monterey" if EMBEDDED | 292 | tristate "Monterey Genius KB29E keyboard" if EXPERT |
262 | depends on USB_HID | 293 | depends on USB_HID |
263 | default !EMBEDDED | 294 | default !EXPERT |
264 | ---help--- | 295 | ---help--- |
265 | Support for Monterey Genius KB29E. | 296 | Support for Monterey Genius KB29E. |
266 | 297 | ||
298 | config HID_MULTITOUCH | ||
299 | tristate "HID Multitouch panels" | ||
300 | depends on USB_HID | ||
301 | ---help--- | ||
302 | Generic support for HID multitouch panels. | ||
303 | |||
304 | Say Y here if you have one of the following devices: | ||
305 | - 3M PCT touch screens | ||
306 | - ActionStar dual touch panels | ||
307 | - Cando dual touch panels | ||
308 | - Chunghwa panels | ||
309 | - CVTouch panels | ||
310 | - Cypress TrueTouch panels | ||
311 | - Elo TouchSystems IntelliTouch Plus panels | ||
312 | - GeneralTouch 'Sensing Win7-TwoFinger' panels | ||
313 | - GoodTouch panels | ||
314 | - Hanvon dual touch panels | ||
315 | - Ilitek dual touch panels | ||
316 | - IrTouch Infrared USB panels | ||
317 | - Lumio CrystalTouch panels | ||
318 | - MosArt dual-touch panels | ||
319 | - PenMount dual touch panels | ||
320 | - Pixcir dual touch panels | ||
321 | - eGalax dual-touch panels, including the Joojoo and Wetab tablets | ||
322 | - Stantum multitouch panels | ||
323 | - Touch International Panels | ||
324 | - Unitec Panels | ||
325 | |||
326 | If unsure, say N. | ||
327 | |||
328 | To compile this driver as a module, choose M here: the | ||
329 | module will be called hid-multitouch. | ||
330 | |||
267 | config HID_NTRIG | 331 | config HID_NTRIG |
268 | tristate "NTrig" | 332 | tristate "N-Trig touch screen" |
269 | depends on USB_HID | 333 | depends on USB_HID |
270 | ---help--- | 334 | ---help--- |
271 | Support for N-Trig touch screen. | 335 | Support for N-Trig touch screen. |
272 | 336 | ||
273 | config HID_ORTEK | 337 | config HID_ORTEK |
274 | tristate "Ortek" | 338 | tristate "Ortek PKB-1700/WKB-2000/Skycable wireless keyboard and mouse trackpad" |
275 | depends on USB_HID | 339 | depends on USB_HID |
276 | ---help--- | 340 | ---help--- |
277 | Support for Ortek WKB-2000 wireless keyboard + mouse trackpad. | 341 | There are certain devices which have LogicalMaximum wrong in the keyboard |
342 | usage page of their report descriptor. The most prevailing ones so far | ||
343 | are manufactured by Ortek, thus the name of the driver. Currently | ||
344 | supported devices by this driver are | ||
345 | |||
346 | - Ortek PKB-1700 | ||
347 | - Ortek WKB-2000 | ||
348 | - Skycable wireless presenter | ||
278 | 349 | ||
279 | config HID_PANTHERLORD | 350 | config HID_PANTHERLORD |
280 | tristate "Pantherlord support" | 351 | tristate "Pantherlord/GreenAsia game controller" |
281 | depends on USB_HID | 352 | depends on USB_HID |
282 | ---help--- | 353 | ---help--- |
283 | Say Y here if you have a PantherLord/GreenAsia based game controller | 354 | Say Y here if you have a PantherLord/GreenAsia based game controller |
@@ -292,7 +363,7 @@ config PANTHERLORD_FF | |||
292 | or adapter and want to enable force feedback support for it. | 363 | or adapter and want to enable force feedback support for it. |
293 | 364 | ||
294 | config HID_PETALYNX | 365 | config HID_PETALYNX |
295 | tristate "Petalynx" | 366 | tristate "Petalynx Maxter remote control" |
296 | depends on USB_HID | 367 | depends on USB_HID |
297 | ---help--- | 368 | ---help--- |
298 | Support for Petalynx Maxter remote control. | 369 | Support for Petalynx Maxter remote control. |
@@ -317,8 +388,8 @@ config HID_PICOLCD | |||
317 | - IR | 388 | - IR |
318 | 389 | ||
319 | config HID_PICOLCD_FB | 390 | config HID_PICOLCD_FB |
320 | bool "Framebuffer support" if EMBEDDED | 391 | bool "Framebuffer support" if EXPERT |
321 | default !EMBEDDED | 392 | default !EXPERT |
322 | depends on HID_PICOLCD | 393 | depends on HID_PICOLCD |
323 | depends on HID_PICOLCD=FB || FB=y | 394 | depends on HID_PICOLCD=FB || FB=y |
324 | select FB_DEFERRED_IO | 395 | select FB_DEFERRED_IO |
@@ -331,8 +402,8 @@ config HID_PICOLCD_FB | |||
331 | frambuffer device. | 402 | frambuffer device. |
332 | 403 | ||
333 | config HID_PICOLCD_BACKLIGHT | 404 | config HID_PICOLCD_BACKLIGHT |
334 | bool "Backlight control" if EMBEDDED | 405 | bool "Backlight control" if EXPERT |
335 | default !EMBEDDED | 406 | default !EXPERT |
336 | depends on HID_PICOLCD | 407 | depends on HID_PICOLCD |
337 | depends on HID_PICOLCD=BACKLIGHT_CLASS_DEVICE || BACKLIGHT_CLASS_DEVICE=y | 408 | depends on HID_PICOLCD=BACKLIGHT_CLASS_DEVICE || BACKLIGHT_CLASS_DEVICE=y |
338 | ---help--- | 409 | ---help--- |
@@ -340,23 +411,23 @@ config HID_PICOLCD_BACKLIGHT | |||
340 | class. | 411 | class. |
341 | 412 | ||
342 | config HID_PICOLCD_LCD | 413 | config HID_PICOLCD_LCD |
343 | bool "Contrast control" if EMBEDDED | 414 | bool "Contrast control" if EXPERT |
344 | default !EMBEDDED | 415 | default !EXPERT |
345 | depends on HID_PICOLCD | 416 | depends on HID_PICOLCD |
346 | depends on HID_PICOLCD=LCD_CLASS_DEVICE || LCD_CLASS_DEVICE=y | 417 | depends on HID_PICOLCD=LCD_CLASS_DEVICE || LCD_CLASS_DEVICE=y |
347 | ---help--- | 418 | ---help--- |
348 | Provide access to PicoLCD's LCD contrast via lcd class. | 419 | Provide access to PicoLCD's LCD contrast via lcd class. |
349 | 420 | ||
350 | config HID_PICOLCD_LEDS | 421 | config HID_PICOLCD_LEDS |
351 | bool "GPO via leds class" if EMBEDDED | 422 | bool "GPO via leds class" if EXPERT |
352 | default !EMBEDDED | 423 | default !EXPERT |
353 | depends on HID_PICOLCD | 424 | depends on HID_PICOLCD |
354 | depends on HID_PICOLCD=LEDS_CLASS || LEDS_CLASS=y | 425 | depends on HID_PICOLCD=LEDS_CLASS || LEDS_CLASS=y |
355 | ---help--- | 426 | ---help--- |
356 | Provide access to PicoLCD's GPO pins via leds class. | 427 | Provide access to PicoLCD's GPO pins via leds class. |
357 | 428 | ||
358 | config HID_QUANTA | 429 | config HID_QUANTA |
359 | tristate "Quanta Optical Touch" | 430 | tristate "Quanta Optical Touch panels" |
360 | depends on USB_HID | 431 | depends on USB_HID |
361 | ---help--- | 432 | ---help--- |
362 | Support for Quanta Optical Touch dual-touch panels. | 433 | Support for Quanta Optical Touch dual-touch panels. |
@@ -369,39 +440,69 @@ config HID_ROCCAT | |||
369 | Say Y here if you have a Roccat mouse or keyboard and want OSD or | 440 | Say Y here if you have a Roccat mouse or keyboard and want OSD or |
370 | macro execution support. | 441 | macro execution support. |
371 | 442 | ||
443 | config HID_ROCCAT_COMMON | ||
444 | tristate | ||
445 | |||
446 | config HID_ROCCAT_ARVO | ||
447 | tristate "Roccat Arvo keyboard support" | ||
448 | depends on USB_HID | ||
449 | select HID_ROCCAT | ||
450 | select HID_ROCCAT_COMMON | ||
451 | ---help--- | ||
452 | Support for Roccat Arvo keyboard. | ||
453 | |||
372 | config HID_ROCCAT_KONE | 454 | config HID_ROCCAT_KONE |
373 | tristate "Roccat Kone Mouse support" | 455 | tristate "Roccat Kone Mouse support" |
374 | depends on USB_HID | 456 | depends on USB_HID |
375 | select HID_ROCCAT | 457 | select HID_ROCCAT |
458 | select HID_ROCCAT_COMMON | ||
376 | ---help--- | 459 | ---help--- |
377 | Support for Roccat Kone mouse. | 460 | Support for Roccat Kone mouse. |
378 | 461 | ||
462 | config HID_ROCCAT_KONEPLUS | ||
463 | tristate "Roccat Kone[+] mouse support" | ||
464 | depends on USB_HID | ||
465 | select HID_ROCCAT | ||
466 | select HID_ROCCAT_COMMON | ||
467 | ---help--- | ||
468 | Support for Roccat Kone[+] mouse. | ||
469 | |||
470 | config HID_ROCCAT_KOVAPLUS | ||
471 | tristate "Roccat Kova[+] mouse support" | ||
472 | depends on USB_HID | ||
473 | select HID_ROCCAT | ||
474 | select HID_ROCCAT_COMMON | ||
475 | ---help--- | ||
476 | Support for Roccat Kova[+] mouse. | ||
477 | |||
478 | config HID_ROCCAT_PYRA | ||
479 | tristate "Roccat Pyra mouse support" | ||
480 | depends on USB_HID | ||
481 | select HID_ROCCAT | ||
482 | select HID_ROCCAT_COMMON | ||
483 | ---help--- | ||
484 | Support for Roccat Pyra mouse. | ||
485 | |||
379 | config HID_SAMSUNG | 486 | config HID_SAMSUNG |
380 | tristate "Samsung" | 487 | tristate "Samsung InfraRed remote control or keyboards" |
381 | depends on USB_HID | 488 | depends on USB_HID |
382 | ---help--- | 489 | ---help--- |
383 | Support for Samsung InfraRed remote control or keyboards. | 490 | Support for Samsung InfraRed remote control or keyboards. |
384 | 491 | ||
385 | config HID_SONY | 492 | config HID_SONY |
386 | tristate "Sony" | 493 | tristate "Sony PS3 controller" |
387 | depends on USB_HID | 494 | depends on USB_HID |
388 | ---help--- | 495 | ---help--- |
389 | Support for Sony PS3 controller. | 496 | Support for Sony PS3 controller. |
390 | 497 | ||
391 | config HID_STANTUM | ||
392 | tristate "Stantum" | ||
393 | depends on USB_HID | ||
394 | ---help--- | ||
395 | Support for Stantum multitouch panel. | ||
396 | |||
397 | config HID_SUNPLUS | 498 | config HID_SUNPLUS |
398 | tristate "Sunplus" | 499 | tristate "Sunplus wireless desktop" |
399 | depends on USB_HID | 500 | depends on USB_HID |
400 | ---help--- | 501 | ---help--- |
401 | Support for Sunplus wireless desktop. | 502 | Support for Sunplus wireless desktop. |
402 | 503 | ||
403 | config HID_GREENASIA | 504 | config HID_GREENASIA |
404 | tristate "GreenAsia (Product ID 0x12) support" | 505 | tristate "GreenAsia (Product ID 0x12) game controller support" |
405 | depends on USB_HID | 506 | depends on USB_HID |
406 | ---help--- | 507 | ---help--- |
407 | Say Y here if you have a GreenAsia (Product ID 0x12) based game | 508 | Say Y here if you have a GreenAsia (Product ID 0x12) based game |
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index 46f037f3df80..f8cc4ea7335a 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile | |||
@@ -1,7 +1,7 @@ | |||
1 | # | 1 | # |
2 | # Makefile for the HID driver | 2 | # Makefile for the HID driver |
3 | # | 3 | # |
4 | hid-objs := hid-core.o hid-input.o | 4 | hid-y := hid-core.o hid-input.o |
5 | 5 | ||
6 | ifdef CONFIG_DEBUG_FS | 6 | ifdef CONFIG_DEBUG_FS |
7 | hid-objs += hid-debug.o | 7 | hid-objs += hid-debug.o |
@@ -11,38 +11,41 @@ obj-$(CONFIG_HID) += hid.o | |||
11 | 11 | ||
12 | hid-$(CONFIG_HIDRAW) += hidraw.o | 12 | hid-$(CONFIG_HIDRAW) += hidraw.o |
13 | 13 | ||
14 | hid-logitech-objs := hid-lg.o | 14 | hid-logitech-y := hid-lg.o |
15 | ifdef CONFIG_LOGITECH_FF | 15 | ifdef CONFIG_LOGITECH_FF |
16 | hid-logitech-objs += hid-lgff.o | 16 | hid-logitech-y += hid-lgff.o |
17 | endif | 17 | endif |
18 | ifdef CONFIG_LOGIRUMBLEPAD2_FF | 18 | ifdef CONFIG_LOGIRUMBLEPAD2_FF |
19 | hid-logitech-objs += hid-lg2ff.o | 19 | hid-logitech-y += hid-lg2ff.o |
20 | endif | 20 | endif |
21 | ifdef CONFIG_LOGIG940_FF | 21 | ifdef CONFIG_LOGIG940_FF |
22 | hid-logitech-objs += hid-lg3ff.o | 22 | hid-logitech-y += hid-lg3ff.o |
23 | endif | ||
24 | ifdef CONFIG_LOGIWII_FF | ||
25 | hid-logitech-y += hid-lg4ff.o | ||
23 | endif | 26 | endif |
24 | 27 | ||
25 | obj-$(CONFIG_HID_3M_PCT) += hid-3m-pct.o | ||
26 | obj-$(CONFIG_HID_A4TECH) += hid-a4tech.o | 28 | obj-$(CONFIG_HID_A4TECH) += hid-a4tech.o |
27 | obj-$(CONFIG_HID_ACRUX_FF) += hid-axff.o | 29 | obj-$(CONFIG_HID_ACRUX) += hid-axff.o |
28 | obj-$(CONFIG_HID_APPLE) += hid-apple.o | 30 | obj-$(CONFIG_HID_APPLE) += hid-apple.o |
29 | obj-$(CONFIG_HID_BELKIN) += hid-belkin.o | 31 | obj-$(CONFIG_HID_BELKIN) += hid-belkin.o |
30 | obj-$(CONFIG_HID_CANDO) += hid-cando.o | ||
31 | obj-$(CONFIG_HID_CHERRY) += hid-cherry.o | 32 | obj-$(CONFIG_HID_CHERRY) += hid-cherry.o |
32 | obj-$(CONFIG_HID_CHICONY) += hid-chicony.o | 33 | obj-$(CONFIG_HID_CHICONY) += hid-chicony.o |
33 | obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o | 34 | obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o |
34 | obj-$(CONFIG_HID_DRAGONRISE) += hid-drff.o | 35 | obj-$(CONFIG_HID_DRAGONRISE) += hid-dr.o |
35 | obj-$(CONFIG_HID_EGALAX) += hid-egalax.o | 36 | obj-$(CONFIG_HID_EMS_FF) += hid-emsff.o |
36 | obj-$(CONFIG_HID_ELECOM) += hid-elecom.o | 37 | obj-$(CONFIG_HID_ELECOM) += hid-elecom.o |
37 | obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o | 38 | obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o |
38 | obj-$(CONFIG_HID_GYRATION) += hid-gyration.o | 39 | obj-$(CONFIG_HID_GYRATION) += hid-gyration.o |
39 | obj-$(CONFIG_HID_KENSINGTON) += hid-kensington.o | 40 | obj-$(CONFIG_HID_KENSINGTON) += hid-kensington.o |
41 | obj-$(CONFIG_HID_KEYTOUCH) += hid-keytouch.o | ||
40 | obj-$(CONFIG_HID_KYE) += hid-kye.o | 42 | obj-$(CONFIG_HID_KYE) += hid-kye.o |
43 | obj-$(CONFIG_HID_LCPOWER) += hid-lcpower.o | ||
41 | obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o | 44 | obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o |
42 | obj-$(CONFIG_HID_MAGICMOUSE) += hid-magicmouse.o | 45 | obj-$(CONFIG_HID_MAGICMOUSE) += hid-magicmouse.o |
43 | obj-$(CONFIG_HID_MICROSOFT) += hid-microsoft.o | 46 | obj-$(CONFIG_HID_MICROSOFT) += hid-microsoft.o |
44 | obj-$(CONFIG_HID_MONTEREY) += hid-monterey.o | 47 | obj-$(CONFIG_HID_MONTEREY) += hid-monterey.o |
45 | obj-$(CONFIG_HID_MOSART) += hid-mosart.o | 48 | obj-$(CONFIG_HID_MULTITOUCH) += hid-multitouch.o |
46 | obj-$(CONFIG_HID_NTRIG) += hid-ntrig.o | 49 | obj-$(CONFIG_HID_NTRIG) += hid-ntrig.o |
47 | obj-$(CONFIG_HID_ORTEK) += hid-ortek.o | 50 | obj-$(CONFIG_HID_ORTEK) += hid-ortek.o |
48 | obj-$(CONFIG_HID_PRODIKEYS) += hid-prodikeys.o | 51 | obj-$(CONFIG_HID_PRODIKEYS) += hid-prodikeys.o |
@@ -51,19 +54,25 @@ obj-$(CONFIG_HID_PANTHERLORD) += hid-pl.o | |||
51 | obj-$(CONFIG_HID_PETALYNX) += hid-petalynx.o | 54 | obj-$(CONFIG_HID_PETALYNX) += hid-petalynx.o |
52 | obj-$(CONFIG_HID_PICOLCD) += hid-picolcd.o | 55 | obj-$(CONFIG_HID_PICOLCD) += hid-picolcd.o |
53 | obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o | 56 | obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o |
57 | obj-$(CONFIG_HID_ROCCAT_COMMON) += hid-roccat-common.o | ||
58 | obj-$(CONFIG_HID_ROCCAT_ARVO) += hid-roccat-arvo.o | ||
54 | obj-$(CONFIG_HID_ROCCAT_KONE) += hid-roccat-kone.o | 59 | obj-$(CONFIG_HID_ROCCAT_KONE) += hid-roccat-kone.o |
60 | obj-$(CONFIG_HID_ROCCAT_KONEPLUS) += hid-roccat-koneplus.o | ||
61 | obj-$(CONFIG_HID_ROCCAT_KOVAPLUS) += hid-roccat-kovaplus.o | ||
62 | obj-$(CONFIG_HID_ROCCAT_PYRA) += hid-roccat-pyra.o | ||
55 | obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o | 63 | obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o |
56 | obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o | 64 | obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o |
57 | obj-$(CONFIG_HID_SONY) += hid-sony.o | 65 | obj-$(CONFIG_HID_SONY) += hid-sony.o |
58 | obj-$(CONFIG_HID_STANTUM) += hid-stantum.o | ||
59 | obj-$(CONFIG_HID_SUNPLUS) += hid-sunplus.o | 66 | obj-$(CONFIG_HID_SUNPLUS) += hid-sunplus.o |
60 | obj-$(CONFIG_HID_GREENASIA) += hid-gaff.o | 67 | obj-$(CONFIG_HID_GREENASIA) += hid-gaff.o |
61 | obj-$(CONFIG_HID_THRUSTMASTER) += hid-tmff.o | 68 | obj-$(CONFIG_HID_THRUSTMASTER) += hid-tmff.o |
62 | obj-$(CONFIG_HID_TOPSEED) += hid-topseed.o | 69 | obj-$(CONFIG_HID_TOPSEED) += hid-topseed.o |
63 | obj-$(CONFIG_HID_TWINHAN) += hid-twinhan.o | 70 | obj-$(CONFIG_HID_TWINHAN) += hid-twinhan.o |
71 | obj-$(CONFIG_HID_UCLOGIC) += hid-uclogic.o | ||
64 | obj-$(CONFIG_HID_ZEROPLUS) += hid-zpff.o | 72 | obj-$(CONFIG_HID_ZEROPLUS) += hid-zpff.o |
65 | obj-$(CONFIG_HID_ZYDACRON) += hid-zydacron.o | 73 | obj-$(CONFIG_HID_ZYDACRON) += hid-zydacron.o |
66 | obj-$(CONFIG_HID_WACOM) += hid-wacom.o | 74 | obj-$(CONFIG_HID_WACOM) += hid-wacom.o |
75 | obj-$(CONFIG_HID_WALTOP) += hid-waltop.o | ||
67 | 76 | ||
68 | obj-$(CONFIG_USB_HID) += usbhid/ | 77 | obj-$(CONFIG_USB_HID) += usbhid/ |
69 | obj-$(CONFIG_USB_MOUSE) += usbhid/ | 78 | obj-$(CONFIG_USB_MOUSE) += usbhid/ |
diff --git a/drivers/hid/hid-3m-pct.c b/drivers/hid/hid-3m-pct.c deleted file mode 100644 index 2a0d56b7a02b..000000000000 --- a/drivers/hid/hid-3m-pct.c +++ /dev/null | |||
@@ -1,316 +0,0 @@ | |||
1 | /* | ||
2 | * HID driver for 3M PCT multitouch panels | ||
3 | * | ||
4 | * Copyright (c) 2009-2010 Stephane Chatty <chatty@enac.fr> | ||
5 | * | ||
6 | */ | ||
7 | |||
8 | /* | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the Free | ||
11 | * Software Foundation; either version 2 of the License, or (at your option) | ||
12 | * any later version. | ||
13 | */ | ||
14 | |||
15 | #include <linux/device.h> | ||
16 | #include <linux/hid.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/slab.h> | ||
19 | #include <linux/usb.h> | ||
20 | |||
21 | MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>"); | ||
22 | MODULE_DESCRIPTION("3M PCT multitouch panels"); | ||
23 | MODULE_LICENSE("GPL"); | ||
24 | |||
25 | #include "hid-ids.h" | ||
26 | |||
27 | struct mmm_finger { | ||
28 | __s32 x, y, w, h; | ||
29 | __u8 rank; | ||
30 | bool touch, valid; | ||
31 | }; | ||
32 | |||
33 | struct mmm_data { | ||
34 | struct mmm_finger f[10]; | ||
35 | __u8 curid, num; | ||
36 | bool touch, valid; | ||
37 | }; | ||
38 | |||
39 | static int mmm_input_mapping(struct hid_device *hdev, struct hid_input *hi, | ||
40 | struct hid_field *field, struct hid_usage *usage, | ||
41 | unsigned long **bit, int *max) | ||
42 | { | ||
43 | switch (usage->hid & HID_USAGE_PAGE) { | ||
44 | |||
45 | case HID_UP_BUTTON: | ||
46 | return -1; | ||
47 | |||
48 | case HID_UP_GENDESK: | ||
49 | switch (usage->hid) { | ||
50 | case HID_GD_X: | ||
51 | hid_map_usage(hi, usage, bit, max, | ||
52 | EV_ABS, ABS_MT_POSITION_X); | ||
53 | /* touchscreen emulation */ | ||
54 | input_set_abs_params(hi->input, ABS_X, | ||
55 | field->logical_minimum, | ||
56 | field->logical_maximum, 0, 0); | ||
57 | return 1; | ||
58 | case HID_GD_Y: | ||
59 | hid_map_usage(hi, usage, bit, max, | ||
60 | EV_ABS, ABS_MT_POSITION_Y); | ||
61 | /* touchscreen emulation */ | ||
62 | input_set_abs_params(hi->input, ABS_Y, | ||
63 | field->logical_minimum, | ||
64 | field->logical_maximum, 0, 0); | ||
65 | return 1; | ||
66 | } | ||
67 | return 0; | ||
68 | |||
69 | case HID_UP_DIGITIZER: | ||
70 | switch (usage->hid) { | ||
71 | /* we do not want to map these: no input-oriented meaning */ | ||
72 | case 0x14: | ||
73 | case 0x23: | ||
74 | case HID_DG_INPUTMODE: | ||
75 | case HID_DG_DEVICEINDEX: | ||
76 | case HID_DG_CONTACTCOUNT: | ||
77 | case HID_DG_CONTACTMAX: | ||
78 | case HID_DG_INRANGE: | ||
79 | case HID_DG_CONFIDENCE: | ||
80 | return -1; | ||
81 | case HID_DG_TIPSWITCH: | ||
82 | /* touchscreen emulation */ | ||
83 | hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); | ||
84 | return 1; | ||
85 | case HID_DG_WIDTH: | ||
86 | hid_map_usage(hi, usage, bit, max, | ||
87 | EV_ABS, ABS_MT_TOUCH_MAJOR); | ||
88 | return 1; | ||
89 | case HID_DG_HEIGHT: | ||
90 | hid_map_usage(hi, usage, bit, max, | ||
91 | EV_ABS, ABS_MT_TOUCH_MINOR); | ||
92 | input_set_abs_params(hi->input, ABS_MT_ORIENTATION, | ||
93 | 1, 1, 0, 0); | ||
94 | return 1; | ||
95 | case HID_DG_CONTACTID: | ||
96 | field->logical_maximum = 59; | ||
97 | hid_map_usage(hi, usage, bit, max, | ||
98 | EV_ABS, ABS_MT_TRACKING_ID); | ||
99 | return 1; | ||
100 | } | ||
101 | /* let hid-input decide for the others */ | ||
102 | return 0; | ||
103 | |||
104 | case 0xff000000: | ||
105 | /* we do not want to map these: no input-oriented meaning */ | ||
106 | return -1; | ||
107 | } | ||
108 | |||
109 | return 0; | ||
110 | } | ||
111 | |||
112 | static int mmm_input_mapped(struct hid_device *hdev, struct hid_input *hi, | ||
113 | struct hid_field *field, struct hid_usage *usage, | ||
114 | unsigned long **bit, int *max) | ||
115 | { | ||
116 | if (usage->type == EV_KEY || usage->type == EV_ABS) | ||
117 | clear_bit(usage->code, *bit); | ||
118 | |||
119 | return 0; | ||
120 | } | ||
121 | |||
122 | /* | ||
123 | * this function is called when a whole packet has been received and processed, | ||
124 | * so that it can decide what to send to the input layer. | ||
125 | */ | ||
126 | static void mmm_filter_event(struct mmm_data *md, struct input_dev *input) | ||
127 | { | ||
128 | struct mmm_finger *oldest = 0; | ||
129 | bool pressed = false, released = false; | ||
130 | int i; | ||
131 | |||
132 | /* | ||
133 | * we need to iterate on all fingers to decide if we have a press | ||
134 | * or a release event in our touchscreen emulation. | ||
135 | */ | ||
136 | for (i = 0; i < 10; ++i) { | ||
137 | struct mmm_finger *f = &md->f[i]; | ||
138 | if (!f->valid) { | ||
139 | /* this finger is just placeholder data, ignore */ | ||
140 | } else if (f->touch) { | ||
141 | /* this finger is on the screen */ | ||
142 | int wide = (f->w > f->h); | ||
143 | input_event(input, EV_ABS, ABS_MT_TRACKING_ID, i); | ||
144 | input_event(input, EV_ABS, ABS_MT_POSITION_X, f->x); | ||
145 | input_event(input, EV_ABS, ABS_MT_POSITION_Y, f->y); | ||
146 | input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide); | ||
147 | input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, | ||
148 | wide ? f->w : f->h); | ||
149 | input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, | ||
150 | wide ? f->h : f->w); | ||
151 | input_mt_sync(input); | ||
152 | /* | ||
153 | * touchscreen emulation: maintain the age rank | ||
154 | * of this finger, decide if we have a press | ||
155 | */ | ||
156 | if (f->rank == 0) { | ||
157 | f->rank = ++(md->num); | ||
158 | if (f->rank == 1) | ||
159 | pressed = true; | ||
160 | } | ||
161 | if (f->rank == 1) | ||
162 | oldest = f; | ||
163 | } else { | ||
164 | /* this finger took off the screen */ | ||
165 | /* touchscreen emulation: maintain age rank of others */ | ||
166 | int j; | ||
167 | |||
168 | for (j = 0; j < 10; ++j) { | ||
169 | struct mmm_finger *g = &md->f[j]; | ||
170 | if (g->rank > f->rank) { | ||
171 | g->rank--; | ||
172 | if (g->rank == 1) | ||
173 | oldest = g; | ||
174 | } | ||
175 | } | ||
176 | f->rank = 0; | ||
177 | --(md->num); | ||
178 | if (md->num == 0) | ||
179 | released = true; | ||
180 | } | ||
181 | f->valid = 0; | ||
182 | } | ||
183 | |||
184 | /* touchscreen emulation */ | ||
185 | if (oldest) { | ||
186 | if (pressed) | ||
187 | input_event(input, EV_KEY, BTN_TOUCH, 1); | ||
188 | input_event(input, EV_ABS, ABS_X, oldest->x); | ||
189 | input_event(input, EV_ABS, ABS_Y, oldest->y); | ||
190 | } else if (released) { | ||
191 | input_event(input, EV_KEY, BTN_TOUCH, 0); | ||
192 | } | ||
193 | } | ||
194 | |||
195 | /* | ||
196 | * this function is called upon all reports | ||
197 | * so that we can accumulate contact point information, | ||
198 | * and call input_mt_sync after each point. | ||
199 | */ | ||
200 | static int mmm_event(struct hid_device *hid, struct hid_field *field, | ||
201 | struct hid_usage *usage, __s32 value) | ||
202 | { | ||
203 | struct mmm_data *md = hid_get_drvdata(hid); | ||
204 | /* | ||
205 | * strangely, this function can be called before | ||
206 | * field->hidinput is initialized! | ||
207 | */ | ||
208 | if (hid->claimed & HID_CLAIMED_INPUT) { | ||
209 | struct input_dev *input = field->hidinput->input; | ||
210 | switch (usage->hid) { | ||
211 | case HID_DG_TIPSWITCH: | ||
212 | md->touch = value; | ||
213 | break; | ||
214 | case HID_DG_CONFIDENCE: | ||
215 | md->valid = value; | ||
216 | break; | ||
217 | case HID_DG_WIDTH: | ||
218 | if (md->valid) | ||
219 | md->f[md->curid].w = value; | ||
220 | break; | ||
221 | case HID_DG_HEIGHT: | ||
222 | if (md->valid) | ||
223 | md->f[md->curid].h = value; | ||
224 | break; | ||
225 | case HID_DG_CONTACTID: | ||
226 | if (md->valid) { | ||
227 | md->curid = value; | ||
228 | md->f[value].touch = md->touch; | ||
229 | md->f[value].valid = 1; | ||
230 | } | ||
231 | break; | ||
232 | case HID_GD_X: | ||
233 | if (md->valid) | ||
234 | md->f[md->curid].x = value; | ||
235 | break; | ||
236 | case HID_GD_Y: | ||
237 | if (md->valid) | ||
238 | md->f[md->curid].y = value; | ||
239 | break; | ||
240 | case HID_DG_CONTACTCOUNT: | ||
241 | mmm_filter_event(md, input); | ||
242 | break; | ||
243 | } | ||
244 | } | ||
245 | |||
246 | /* we have handled the hidinput part, now remains hiddev */ | ||
247 | if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event) | ||
248 | hid->hiddev_hid_event(hid, field, usage, value); | ||
249 | |||
250 | return 1; | ||
251 | } | ||
252 | |||
253 | static int mmm_probe(struct hid_device *hdev, const struct hid_device_id *id) | ||
254 | { | ||
255 | int ret; | ||
256 | struct mmm_data *md; | ||
257 | |||
258 | md = kzalloc(sizeof(struct mmm_data), GFP_KERNEL); | ||
259 | if (!md) { | ||
260 | dev_err(&hdev->dev, "cannot allocate 3M data\n"); | ||
261 | return -ENOMEM; | ||
262 | } | ||
263 | hid_set_drvdata(hdev, md); | ||
264 | |||
265 | ret = hid_parse(hdev); | ||
266 | if (!ret) | ||
267 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); | ||
268 | |||
269 | if (ret) | ||
270 | kfree(md); | ||
271 | return ret; | ||
272 | } | ||
273 | |||
274 | static void mmm_remove(struct hid_device *hdev) | ||
275 | { | ||
276 | hid_hw_stop(hdev); | ||
277 | kfree(hid_get_drvdata(hdev)); | ||
278 | hid_set_drvdata(hdev, NULL); | ||
279 | } | ||
280 | |||
281 | static const struct hid_device_id mmm_devices[] = { | ||
282 | { HID_USB_DEVICE(USB_VENDOR_ID_3M, USB_DEVICE_ID_3M1968) }, | ||
283 | { HID_USB_DEVICE(USB_VENDOR_ID_3M, USB_DEVICE_ID_3M2256) }, | ||
284 | { } | ||
285 | }; | ||
286 | MODULE_DEVICE_TABLE(hid, mmm_devices); | ||
287 | |||
288 | static const struct hid_usage_id mmm_grabbed_usages[] = { | ||
289 | { HID_ANY_ID, HID_ANY_ID, HID_ANY_ID }, | ||
290 | { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1} | ||
291 | }; | ||
292 | |||
293 | static struct hid_driver mmm_driver = { | ||
294 | .name = "3m-pct", | ||
295 | .id_table = mmm_devices, | ||
296 | .probe = mmm_probe, | ||
297 | .remove = mmm_remove, | ||
298 | .input_mapping = mmm_input_mapping, | ||
299 | .input_mapped = mmm_input_mapped, | ||
300 | .usage_table = mmm_grabbed_usages, | ||
301 | .event = mmm_event, | ||
302 | }; | ||
303 | |||
304 | static int __init mmm_init(void) | ||
305 | { | ||
306 | return hid_register_driver(&mmm_driver); | ||
307 | } | ||
308 | |||
309 | static void __exit mmm_exit(void) | ||
310 | { | ||
311 | hid_unregister_driver(&mmm_driver); | ||
312 | } | ||
313 | |||
314 | module_init(mmm_init); | ||
315 | module_exit(mmm_exit); | ||
316 | |||
diff --git a/drivers/hid/hid-a4tech.c b/drivers/hid/hid-a4tech.c index 3a2b223c1da4..902d1dfeb1b5 100644 --- a/drivers/hid/hid-a4tech.c +++ b/drivers/hid/hid-a4tech.c | |||
@@ -93,7 +93,7 @@ static int a4_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
93 | 93 | ||
94 | a4 = kzalloc(sizeof(*a4), GFP_KERNEL); | 94 | a4 = kzalloc(sizeof(*a4), GFP_KERNEL); |
95 | if (a4 == NULL) { | 95 | if (a4 == NULL) { |
96 | dev_err(&hdev->dev, "can't alloc device descriptor\n"); | 96 | hid_err(hdev, "can't alloc device descriptor\n"); |
97 | ret = -ENOMEM; | 97 | ret = -ENOMEM; |
98 | goto err_free; | 98 | goto err_free; |
99 | } | 99 | } |
@@ -104,13 +104,13 @@ static int a4_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
104 | 104 | ||
105 | ret = hid_parse(hdev); | 105 | ret = hid_parse(hdev); |
106 | if (ret) { | 106 | if (ret) { |
107 | dev_err(&hdev->dev, "parse failed\n"); | 107 | hid_err(hdev, "parse failed\n"); |
108 | goto err_free; | 108 | goto err_free; |
109 | } | 109 | } |
110 | 110 | ||
111 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); | 111 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); |
112 | if (ret) { | 112 | if (ret) { |
113 | dev_err(&hdev->dev, "hw start failed\n"); | 113 | hid_err(hdev, "hw start failed\n"); |
114 | goto err_free; | 114 | goto err_free; |
115 | } | 115 | } |
116 | 116 | ||
@@ -133,6 +133,8 @@ static const struct hid_device_id a4_devices[] = { | |||
133 | .driver_data = A4_2WHEEL_MOUSE_HACK_7 }, | 133 | .driver_data = A4_2WHEEL_MOUSE_HACK_7 }, |
134 | { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D), | 134 | { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D), |
135 | .driver_data = A4_2WHEEL_MOUSE_HACK_B8 }, | 135 | .driver_data = A4_2WHEEL_MOUSE_HACK_B8 }, |
136 | { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_RP_649), | ||
137 | .driver_data = A4_2WHEEL_MOUSE_HACK_B8 }, | ||
136 | { } | 138 | { } |
137 | }; | 139 | }; |
138 | MODULE_DEVICE_TABLE(hid, a4_devices); | 140 | MODULE_DEVICE_TABLE(hid, a4_devices); |
diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index bba05d0a8980..b85744fe8464 100644 --- a/drivers/hid/hid-apple.c +++ b/drivers/hid/hid-apple.c | |||
@@ -16,6 +16,8 @@ | |||
16 | * any later version. | 16 | * any later version. |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
20 | |||
19 | #include <linux/device.h> | 21 | #include <linux/device.h> |
20 | #include <linux/hid.h> | 22 | #include <linux/hid.h> |
21 | #include <linux/module.h> | 23 | #include <linux/module.h> |
@@ -59,6 +61,27 @@ struct apple_key_translation { | |||
59 | u8 flags; | 61 | u8 flags; |
60 | }; | 62 | }; |
61 | 63 | ||
64 | static const struct apple_key_translation macbookair_fn_keys[] = { | ||
65 | { KEY_BACKSPACE, KEY_DELETE }, | ||
66 | { KEY_ENTER, KEY_INSERT }, | ||
67 | { KEY_F1, KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY }, | ||
68 | { KEY_F2, KEY_BRIGHTNESSUP, APPLE_FLAG_FKEY }, | ||
69 | { KEY_F3, KEY_SCALE, APPLE_FLAG_FKEY }, | ||
70 | { KEY_F4, KEY_DASHBOARD, APPLE_FLAG_FKEY }, | ||
71 | { KEY_F6, KEY_PREVIOUSSONG, APPLE_FLAG_FKEY }, | ||
72 | { KEY_F7, KEY_PLAYPAUSE, APPLE_FLAG_FKEY }, | ||
73 | { KEY_F8, KEY_NEXTSONG, APPLE_FLAG_FKEY }, | ||
74 | { KEY_F9, KEY_MUTE, APPLE_FLAG_FKEY }, | ||
75 | { KEY_F10, KEY_VOLUMEDOWN, APPLE_FLAG_FKEY }, | ||
76 | { KEY_F11, KEY_VOLUMEUP, APPLE_FLAG_FKEY }, | ||
77 | { KEY_F12, KEY_EJECTCD, APPLE_FLAG_FKEY }, | ||
78 | { KEY_UP, KEY_PAGEUP }, | ||
79 | { KEY_DOWN, KEY_PAGEDOWN }, | ||
80 | { KEY_LEFT, KEY_HOME }, | ||
81 | { KEY_RIGHT, KEY_END }, | ||
82 | { } | ||
83 | }; | ||
84 | |||
62 | static const struct apple_key_translation apple_fn_keys[] = { | 85 | static const struct apple_key_translation apple_fn_keys[] = { |
63 | { KEY_BACKSPACE, KEY_DELETE }, | 86 | { KEY_BACKSPACE, KEY_DELETE }, |
64 | { KEY_ENTER, KEY_INSERT }, | 87 | { KEY_ENTER, KEY_INSERT }, |
@@ -146,7 +169,7 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input, | |||
146 | struct hid_usage *usage, __s32 value) | 169 | struct hid_usage *usage, __s32 value) |
147 | { | 170 | { |
148 | struct apple_sc *asc = hid_get_drvdata(hid); | 171 | struct apple_sc *asc = hid_get_drvdata(hid); |
149 | const struct apple_key_translation *trans; | 172 | const struct apple_key_translation *trans, *table; |
150 | 173 | ||
151 | if (usage->code == KEY_FN) { | 174 | if (usage->code == KEY_FN) { |
152 | asc->fn_on = !!value; | 175 | asc->fn_on = !!value; |
@@ -157,10 +180,16 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input, | |||
157 | if (fnmode) { | 180 | if (fnmode) { |
158 | int do_translate; | 181 | int do_translate; |
159 | 182 | ||
160 | trans = apple_find_translation((hid->product < 0x21d || | 183 | if (hid->product >= USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI && |
161 | hid->product >= 0x300) ? | 184 | hid->product <= USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) |
162 | powerbook_fn_keys : apple_fn_keys, | 185 | table = macbookair_fn_keys; |
163 | usage->code); | 186 | else if (hid->product < 0x21d || hid->product >= 0x300) |
187 | table = powerbook_fn_keys; | ||
188 | else | ||
189 | table = apple_fn_keys; | ||
190 | |||
191 | trans = apple_find_translation (table, usage->code); | ||
192 | |||
164 | if (trans) { | 193 | if (trans) { |
165 | if (test_bit(usage->code, asc->pressed_fn)) | 194 | if (test_bit(usage->code, asc->pressed_fn)) |
166 | do_translate = 1; | 195 | do_translate = 1; |
@@ -246,17 +275,18 @@ static int apple_event(struct hid_device *hdev, struct hid_field *field, | |||
246 | /* | 275 | /* |
247 | * MacBook JIS keyboard has wrong logical maximum | 276 | * MacBook JIS keyboard has wrong logical maximum |
248 | */ | 277 | */ |
249 | static void apple_report_fixup(struct hid_device *hdev, __u8 *rdesc, | 278 | static __u8 *apple_report_fixup(struct hid_device *hdev, __u8 *rdesc, |
250 | unsigned int rsize) | 279 | unsigned int *rsize) |
251 | { | 280 | { |
252 | struct apple_sc *asc = hid_get_drvdata(hdev); | 281 | struct apple_sc *asc = hid_get_drvdata(hdev); |
253 | 282 | ||
254 | if ((asc->quirks & APPLE_RDESC_JIS) && rsize >= 60 && | 283 | if ((asc->quirks & APPLE_RDESC_JIS) && *rsize >= 60 && |
255 | rdesc[53] == 0x65 && rdesc[59] == 0x65) { | 284 | rdesc[53] == 0x65 && rdesc[59] == 0x65) { |
256 | dev_info(&hdev->dev, "fixing up MacBook JIS keyboard report " | 285 | hid_info(hdev, |
257 | "descriptor\n"); | 286 | "fixing up MacBook JIS keyboard report descriptor\n"); |
258 | rdesc[53] = rdesc[59] = 0xe7; | 287 | rdesc[53] = rdesc[59] = 0xe7; |
259 | } | 288 | } |
289 | return rdesc; | ||
260 | } | 290 | } |
261 | 291 | ||
262 | static void apple_setup_input(struct input_dev *input) | 292 | static void apple_setup_input(struct input_dev *input) |
@@ -323,7 +353,7 @@ static int apple_probe(struct hid_device *hdev, | |||
323 | 353 | ||
324 | asc = kzalloc(sizeof(*asc), GFP_KERNEL); | 354 | asc = kzalloc(sizeof(*asc), GFP_KERNEL); |
325 | if (asc == NULL) { | 355 | if (asc == NULL) { |
326 | dev_err(&hdev->dev, "can't alloc apple descriptor\n"); | 356 | hid_err(hdev, "can't alloc apple descriptor\n"); |
327 | return -ENOMEM; | 357 | return -ENOMEM; |
328 | } | 358 | } |
329 | 359 | ||
@@ -333,7 +363,7 @@ static int apple_probe(struct hid_device *hdev, | |||
333 | 363 | ||
334 | ret = hid_parse(hdev); | 364 | ret = hid_parse(hdev); |
335 | if (ret) { | 365 | if (ret) { |
336 | dev_err(&hdev->dev, "parse failed\n"); | 366 | hid_err(hdev, "parse failed\n"); |
337 | goto err_free; | 367 | goto err_free; |
338 | } | 368 | } |
339 | 369 | ||
@@ -344,7 +374,7 @@ static int apple_probe(struct hid_device *hdev, | |||
344 | 374 | ||
345 | ret = hid_hw_start(hdev, connect_mask); | 375 | ret = hid_hw_start(hdev, connect_mask); |
346 | if (ret) { | 376 | if (ret) { |
347 | dev_err(&hdev->dev, "hw start failed\n"); | 377 | hid_err(hdev, "hw start failed\n"); |
348 | goto err_free; | 378 | goto err_free; |
349 | } | 379 | } |
350 | 380 | ||
@@ -439,6 +469,24 @@ static const struct hid_device_id apple_devices[] = { | |||
439 | .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, | 469 | .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, |
440 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS), | 470 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS), |
441 | .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, | 471 | .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, |
472 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI), | ||
473 | .driver_data = APPLE_HAS_FN }, | ||
474 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ISO), | ||
475 | .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, | ||
476 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_JIS), | ||
477 | .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, | ||
478 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI), | ||
479 | .driver_data = APPLE_HAS_FN }, | ||
480 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO), | ||
481 | .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, | ||
482 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS), | ||
483 | .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, | ||
484 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI), | ||
485 | .driver_data = APPLE_HAS_FN }, | ||
486 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO), | ||
487 | .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, | ||
488 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS), | ||
489 | .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, | ||
442 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI), | 490 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI), |
443 | .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, | 491 | .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, |
444 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO), | 492 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO), |
@@ -472,7 +520,7 @@ static int __init apple_init(void) | |||
472 | 520 | ||
473 | ret = hid_register_driver(&apple_driver); | 521 | ret = hid_register_driver(&apple_driver); |
474 | if (ret) | 522 | if (ret) |
475 | printk(KERN_ERR "can't register apple driver\n"); | 523 | pr_err("can't register apple driver\n"); |
476 | 524 | ||
477 | return ret; | 525 | return ret; |
478 | } | 526 | } |
diff --git a/drivers/hid/hid-axff.c b/drivers/hid/hid-axff.c index f42ee140738a..b4554288de00 100644 --- a/drivers/hid/hid-axff.c +++ b/drivers/hid/hid-axff.c | |||
@@ -33,6 +33,8 @@ | |||
33 | #include <linux/hid.h> | 33 | #include <linux/hid.h> |
34 | 34 | ||
35 | #include "hid-ids.h" | 35 | #include "hid-ids.h" |
36 | |||
37 | #ifdef CONFIG_HID_ACRUX_FF | ||
36 | #include "usbhid/usbhid.h" | 38 | #include "usbhid/usbhid.h" |
37 | 39 | ||
38 | struct axff_device { | 40 | struct axff_device { |
@@ -73,14 +75,14 @@ static int axff_init(struct hid_device *hid) | |||
73 | int error; | 75 | int error; |
74 | 76 | ||
75 | if (list_empty(report_list)) { | 77 | if (list_empty(report_list)) { |
76 | dev_err(&hid->dev, "no output reports found\n"); | 78 | hid_err(hid, "no output reports found\n"); |
77 | return -ENODEV; | 79 | return -ENODEV; |
78 | } | 80 | } |
79 | 81 | ||
80 | report = list_first_entry(report_list, struct hid_report, list); | 82 | report = list_first_entry(report_list, struct hid_report, list); |
81 | 83 | ||
82 | if (report->maxfield < 4) { | 84 | if (report->maxfield < 4) { |
83 | dev_err(&hid->dev, "no fields in the report: %d\n", report->maxfield); | 85 | hid_err(hid, "no fields in the report: %d\n", report->maxfield); |
84 | return -ENODEV; | 86 | return -ENODEV; |
85 | } | 87 | } |
86 | 88 | ||
@@ -101,7 +103,7 @@ static int axff_init(struct hid_device *hid) | |||
101 | axff->report->field[3]->value[0] = 0x00; | 103 | axff->report->field[3]->value[0] = 0x00; |
102 | usbhid_submit_report(hid, axff->report, USB_DIR_OUT); | 104 | usbhid_submit_report(hid, axff->report, USB_DIR_OUT); |
103 | 105 | ||
104 | dev_info(&hid->dev, "Force Feedback for ACRUX game controllers by Sergei Kolzun<x0r@dv-life.ru>\n"); | 106 | hid_info(hid, "Force Feedback for ACRUX game controllers by Sergei Kolzun<x0r@dv-life.ru>\n"); |
105 | 107 | ||
106 | return 0; | 108 | return 0; |
107 | 109 | ||
@@ -109,22 +111,28 @@ err_free_mem: | |||
109 | kfree(axff); | 111 | kfree(axff); |
110 | return error; | 112 | return error; |
111 | } | 113 | } |
114 | #else | ||
115 | static inline int axff_init(struct hid_device *hid) | ||
116 | { | ||
117 | return 0; | ||
118 | } | ||
119 | #endif | ||
112 | 120 | ||
113 | static int ax_probe(struct hid_device *hdev, const struct hid_device_id *id) | 121 | static int ax_probe(struct hid_device *hdev, const struct hid_device_id *id) |
114 | { | 122 | { |
115 | int error; | 123 | int error; |
116 | 124 | ||
117 | dev_dbg(&hdev->dev, "ACRUX HID hardware probe..."); | 125 | dev_dbg(&hdev->dev, "ACRUX HID hardware probe...\n"); |
118 | 126 | ||
119 | error = hid_parse(hdev); | 127 | error = hid_parse(hdev); |
120 | if (error) { | 128 | if (error) { |
121 | dev_err(&hdev->dev, "parse failed\n"); | 129 | hid_err(hdev, "parse failed\n"); |
122 | return error; | 130 | return error; |
123 | } | 131 | } |
124 | 132 | ||
125 | error = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); | 133 | error = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); |
126 | if (error) { | 134 | if (error) { |
127 | dev_err(&hdev->dev, "hw start failed\n"); | 135 | hid_err(hdev, "hw start failed\n"); |
128 | return error; | 136 | return error; |
129 | } | 137 | } |
130 | 138 | ||
@@ -134,14 +142,30 @@ static int ax_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
134 | * Do not fail device initialization completely as device | 142 | * Do not fail device initialization completely as device |
135 | * may still be partially operable, just warn. | 143 | * may still be partially operable, just warn. |
136 | */ | 144 | */ |
137 | dev_warn(&hdev->dev, | 145 | hid_warn(hdev, |
138 | "Failed to enable force feedback support, error: %d\n", | 146 | "Failed to enable force feedback support, error: %d\n", |
139 | error); | 147 | error); |
140 | } | 148 | } |
141 | 149 | ||
150 | /* | ||
151 | * We need to start polling device right away, otherwise | ||
152 | * it will go into a coma. | ||
153 | */ | ||
154 | error = hid_hw_open(hdev); | ||
155 | if (error) { | ||
156 | dev_err(&hdev->dev, "hw open failed\n"); | ||
157 | return error; | ||
158 | } | ||
159 | |||
142 | return 0; | 160 | return 0; |
143 | } | 161 | } |
144 | 162 | ||
163 | static void ax_remove(struct hid_device *hdev) | ||
164 | { | ||
165 | hid_hw_close(hdev); | ||
166 | hid_hw_stop(hdev); | ||
167 | } | ||
168 | |||
145 | static const struct hid_device_id ax_devices[] = { | 169 | static const struct hid_device_id ax_devices[] = { |
146 | { HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0x0802), }, | 170 | { HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0x0802), }, |
147 | { } | 171 | { } |
@@ -149,9 +173,10 @@ static const struct hid_device_id ax_devices[] = { | |||
149 | MODULE_DEVICE_TABLE(hid, ax_devices); | 173 | MODULE_DEVICE_TABLE(hid, ax_devices); |
150 | 174 | ||
151 | static struct hid_driver ax_driver = { | 175 | static struct hid_driver ax_driver = { |
152 | .name = "acrux", | 176 | .name = "acrux", |
153 | .id_table = ax_devices, | 177 | .id_table = ax_devices, |
154 | .probe = ax_probe, | 178 | .probe = ax_probe, |
179 | .remove = ax_remove, | ||
155 | }; | 180 | }; |
156 | 181 | ||
157 | static int __init ax_init(void) | 182 | static int __init ax_init(void) |
diff --git a/drivers/hid/hid-belkin.c b/drivers/hid/hid-belkin.c index 4ce7aa3a519f..a1a765a5b08a 100644 --- a/drivers/hid/hid-belkin.c +++ b/drivers/hid/hid-belkin.c | |||
@@ -56,14 +56,14 @@ static int belkin_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
56 | 56 | ||
57 | ret = hid_parse(hdev); | 57 | ret = hid_parse(hdev); |
58 | if (ret) { | 58 | if (ret) { |
59 | dev_err(&hdev->dev, "parse failed\n"); | 59 | hid_err(hdev, "parse failed\n"); |
60 | goto err_free; | 60 | goto err_free; |
61 | } | 61 | } |
62 | 62 | ||
63 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT | | 63 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT | |
64 | ((quirks & BELKIN_HIDDEV) ? HID_CONNECT_HIDDEV_FORCE : 0)); | 64 | ((quirks & BELKIN_HIDDEV) ? HID_CONNECT_HIDDEV_FORCE : 0)); |
65 | if (ret) { | 65 | if (ret) { |
66 | dev_err(&hdev->dev, "hw start failed\n"); | 66 | hid_err(hdev, "hw start failed\n"); |
67 | goto err_free; | 67 | goto err_free; |
68 | } | 68 | } |
69 | 69 | ||
diff --git a/drivers/hid/hid-cando.c b/drivers/hid/hid-cando.c deleted file mode 100644 index 5925bdcd417d..000000000000 --- a/drivers/hid/hid-cando.c +++ /dev/null | |||
@@ -1,274 +0,0 @@ | |||
1 | /* | ||
2 | * HID driver for Cando dual-touch panels | ||
3 | * | ||
4 | * Copyright (c) 2010 Stephane Chatty <chatty@enac.fr> | ||
5 | * | ||
6 | */ | ||
7 | |||
8 | /* | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the Free | ||
11 | * Software Foundation; either version 2 of the License, or (at your option) | ||
12 | * any later version. | ||
13 | */ | ||
14 | |||
15 | #include <linux/device.h> | ||
16 | #include <linux/hid.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/slab.h> | ||
19 | |||
20 | MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>"); | ||
21 | MODULE_DESCRIPTION("Cando dual-touch panel"); | ||
22 | MODULE_LICENSE("GPL"); | ||
23 | |||
24 | #include "hid-ids.h" | ||
25 | |||
26 | struct cando_data { | ||
27 | __u16 x, y; | ||
28 | __u8 id; | ||
29 | __s8 oldest; /* id of the oldest finger in previous frame */ | ||
30 | bool valid; /* valid finger data, or just placeholder? */ | ||
31 | bool first; /* is this the first finger in this frame? */ | ||
32 | __s8 firstid; /* id of the first finger in the frame */ | ||
33 | __u16 firstx, firsty; /* (x, y) of the first finger in the frame */ | ||
34 | }; | ||
35 | |||
36 | static int cando_input_mapping(struct hid_device *hdev, struct hid_input *hi, | ||
37 | struct hid_field *field, struct hid_usage *usage, | ||
38 | unsigned long **bit, int *max) | ||
39 | { | ||
40 | switch (usage->hid & HID_USAGE_PAGE) { | ||
41 | |||
42 | case HID_UP_GENDESK: | ||
43 | switch (usage->hid) { | ||
44 | case HID_GD_X: | ||
45 | hid_map_usage(hi, usage, bit, max, | ||
46 | EV_ABS, ABS_MT_POSITION_X); | ||
47 | /* touchscreen emulation */ | ||
48 | input_set_abs_params(hi->input, ABS_X, | ||
49 | field->logical_minimum, | ||
50 | field->logical_maximum, 0, 0); | ||
51 | return 1; | ||
52 | case HID_GD_Y: | ||
53 | hid_map_usage(hi, usage, bit, max, | ||
54 | EV_ABS, ABS_MT_POSITION_Y); | ||
55 | /* touchscreen emulation */ | ||
56 | input_set_abs_params(hi->input, ABS_Y, | ||
57 | field->logical_minimum, | ||
58 | field->logical_maximum, 0, 0); | ||
59 | return 1; | ||
60 | } | ||
61 | return 0; | ||
62 | |||
63 | case HID_UP_DIGITIZER: | ||
64 | switch (usage->hid) { | ||
65 | case HID_DG_TIPSWITCH: | ||
66 | case HID_DG_CONTACTMAX: | ||
67 | return -1; | ||
68 | case HID_DG_INRANGE: | ||
69 | /* touchscreen emulation */ | ||
70 | hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); | ||
71 | return 1; | ||
72 | case HID_DG_CONTACTID: | ||
73 | hid_map_usage(hi, usage, bit, max, | ||
74 | EV_ABS, ABS_MT_TRACKING_ID); | ||
75 | return 1; | ||
76 | } | ||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | return 0; | ||
81 | } | ||
82 | |||
83 | static int cando_input_mapped(struct hid_device *hdev, struct hid_input *hi, | ||
84 | struct hid_field *field, struct hid_usage *usage, | ||
85 | unsigned long **bit, int *max) | ||
86 | { | ||
87 | if (usage->type == EV_KEY || usage->type == EV_ABS) | ||
88 | clear_bit(usage->code, *bit); | ||
89 | |||
90 | return 0; | ||
91 | } | ||
92 | |||
93 | /* | ||
94 | * this function is called when a whole finger has been parsed, | ||
95 | * so that it can decide what to send to the input layer. | ||
96 | */ | ||
97 | static void cando_filter_event(struct cando_data *td, struct input_dev *input) | ||
98 | { | ||
99 | td->first = !td->first; /* touchscreen emulation */ | ||
100 | |||
101 | if (!td->valid) { | ||
102 | /* | ||
103 | * touchscreen emulation: if this is the second finger and | ||
104 | * the first was valid, the first was the oldest; if the | ||
105 | * first was not valid and there was a valid finger in the | ||
106 | * previous frame, this is a release. | ||
107 | */ | ||
108 | if (td->first) { | ||
109 | td->firstid = -1; | ||
110 | } else if (td->firstid >= 0) { | ||
111 | input_event(input, EV_ABS, ABS_X, td->firstx); | ||
112 | input_event(input, EV_ABS, ABS_Y, td->firsty); | ||
113 | td->oldest = td->firstid; | ||
114 | } else if (td->oldest >= 0) { | ||
115 | input_event(input, EV_KEY, BTN_TOUCH, 0); | ||
116 | td->oldest = -1; | ||
117 | } | ||
118 | |||
119 | return; | ||
120 | } | ||
121 | |||
122 | input_event(input, EV_ABS, ABS_MT_TRACKING_ID, td->id); | ||
123 | input_event(input, EV_ABS, ABS_MT_POSITION_X, td->x); | ||
124 | input_event(input, EV_ABS, ABS_MT_POSITION_Y, td->y); | ||
125 | |||
126 | input_mt_sync(input); | ||
127 | |||
128 | /* | ||
129 | * touchscreen emulation: if there was no touching finger previously, | ||
130 | * emit touch event | ||
131 | */ | ||
132 | if (td->oldest < 0) { | ||
133 | input_event(input, EV_KEY, BTN_TOUCH, 1); | ||
134 | td->oldest = td->id; | ||
135 | } | ||
136 | |||
137 | /* | ||
138 | * touchscreen emulation: if this is the first finger, wait for the | ||
139 | * second; the oldest is then the second if it was the oldest already | ||
140 | * or if there was no first, the first otherwise. | ||
141 | */ | ||
142 | if (td->first) { | ||
143 | td->firstx = td->x; | ||
144 | td->firsty = td->y; | ||
145 | td->firstid = td->id; | ||
146 | } else { | ||
147 | int x, y, oldest; | ||
148 | if (td->id == td->oldest || td->firstid < 0) { | ||
149 | x = td->x; | ||
150 | y = td->y; | ||
151 | oldest = td->id; | ||
152 | } else { | ||
153 | x = td->firstx; | ||
154 | y = td->firsty; | ||
155 | oldest = td->firstid; | ||
156 | } | ||
157 | input_event(input, EV_ABS, ABS_X, x); | ||
158 | input_event(input, EV_ABS, ABS_Y, y); | ||
159 | td->oldest = oldest; | ||
160 | } | ||
161 | } | ||
162 | |||
163 | |||
164 | static int cando_event(struct hid_device *hid, struct hid_field *field, | ||
165 | struct hid_usage *usage, __s32 value) | ||
166 | { | ||
167 | struct cando_data *td = hid_get_drvdata(hid); | ||
168 | |||
169 | if (hid->claimed & HID_CLAIMED_INPUT) { | ||
170 | struct input_dev *input = field->hidinput->input; | ||
171 | |||
172 | switch (usage->hid) { | ||
173 | case HID_DG_INRANGE: | ||
174 | td->valid = value; | ||
175 | break; | ||
176 | case HID_DG_CONTACTID: | ||
177 | td->id = value; | ||
178 | break; | ||
179 | case HID_GD_X: | ||
180 | td->x = value; | ||
181 | break; | ||
182 | case HID_GD_Y: | ||
183 | td->y = value; | ||
184 | cando_filter_event(td, input); | ||
185 | break; | ||
186 | case HID_DG_TIPSWITCH: | ||
187 | /* avoid interference from generic hidinput handling */ | ||
188 | break; | ||
189 | |||
190 | default: | ||
191 | /* fallback to the generic hidinput handling */ | ||
192 | return 0; | ||
193 | } | ||
194 | } | ||
195 | |||
196 | /* we have handled the hidinput part, now remains hiddev */ | ||
197 | if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event) | ||
198 | hid->hiddev_hid_event(hid, field, usage, value); | ||
199 | |||
200 | return 1; | ||
201 | } | ||
202 | |||
203 | static int cando_probe(struct hid_device *hdev, const struct hid_device_id *id) | ||
204 | { | ||
205 | int ret; | ||
206 | struct cando_data *td; | ||
207 | |||
208 | td = kmalloc(sizeof(struct cando_data), GFP_KERNEL); | ||
209 | if (!td) { | ||
210 | dev_err(&hdev->dev, "cannot allocate Cando Touch data\n"); | ||
211 | return -ENOMEM; | ||
212 | } | ||
213 | hid_set_drvdata(hdev, td); | ||
214 | td->first = false; | ||
215 | td->oldest = -1; | ||
216 | td->valid = false; | ||
217 | |||
218 | ret = hid_parse(hdev); | ||
219 | if (!ret) | ||
220 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); | ||
221 | |||
222 | if (ret) | ||
223 | kfree(td); | ||
224 | |||
225 | return ret; | ||
226 | } | ||
227 | |||
228 | static void cando_remove(struct hid_device *hdev) | ||
229 | { | ||
230 | hid_hw_stop(hdev); | ||
231 | kfree(hid_get_drvdata(hdev)); | ||
232 | hid_set_drvdata(hdev, NULL); | ||
233 | } | ||
234 | |||
235 | static const struct hid_device_id cando_devices[] = { | ||
236 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, | ||
237 | USB_DEVICE_ID_CANDO_MULTI_TOUCH) }, | ||
238 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, | ||
239 | USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) }, | ||
240 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, | ||
241 | USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) }, | ||
242 | { } | ||
243 | }; | ||
244 | MODULE_DEVICE_TABLE(hid, cando_devices); | ||
245 | |||
246 | static const struct hid_usage_id cando_grabbed_usages[] = { | ||
247 | { HID_ANY_ID, HID_ANY_ID, HID_ANY_ID }, | ||
248 | { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1} | ||
249 | }; | ||
250 | |||
251 | static struct hid_driver cando_driver = { | ||
252 | .name = "cando-touch", | ||
253 | .id_table = cando_devices, | ||
254 | .probe = cando_probe, | ||
255 | .remove = cando_remove, | ||
256 | .input_mapping = cando_input_mapping, | ||
257 | .input_mapped = cando_input_mapped, | ||
258 | .usage_table = cando_grabbed_usages, | ||
259 | .event = cando_event, | ||
260 | }; | ||
261 | |||
262 | static int __init cando_init(void) | ||
263 | { | ||
264 | return hid_register_driver(&cando_driver); | ||
265 | } | ||
266 | |||
267 | static void __exit cando_exit(void) | ||
268 | { | ||
269 | hid_unregister_driver(&cando_driver); | ||
270 | } | ||
271 | |||
272 | module_init(cando_init); | ||
273 | module_exit(cando_exit); | ||
274 | |||
diff --git a/drivers/hid/hid-cherry.c b/drivers/hid/hid-cherry.c index 24663a8717b1..888ece68a47c 100644 --- a/drivers/hid/hid-cherry.c +++ b/drivers/hid/hid-cherry.c | |||
@@ -26,15 +26,15 @@ | |||
26 | * Cherry Cymotion keyboard have an invalid HID report descriptor, | 26 | * Cherry Cymotion keyboard have an invalid HID report descriptor, |
27 | * that needs fixing before we can parse it. | 27 | * that needs fixing before we can parse it. |
28 | */ | 28 | */ |
29 | static void ch_report_fixup(struct hid_device *hdev, __u8 *rdesc, | 29 | static __u8 *ch_report_fixup(struct hid_device *hdev, __u8 *rdesc, |
30 | unsigned int rsize) | 30 | unsigned int *rsize) |
31 | { | 31 | { |
32 | if (rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) { | 32 | if (*rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) { |
33 | dev_info(&hdev->dev, "fixing up Cherry Cymotion report " | 33 | hid_info(hdev, "fixing up Cherry Cymotion report descriptor\n"); |
34 | "descriptor\n"); | ||
35 | rdesc[11] = rdesc[16] = 0xff; | 34 | rdesc[11] = rdesc[16] = 0xff; |
36 | rdesc[12] = rdesc[17] = 0x03; | 35 | rdesc[12] = rdesc[17] = 0x03; |
37 | } | 36 | } |
37 | return rdesc; | ||
38 | } | 38 | } |
39 | 39 | ||
40 | #define ch_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ | 40 | #define ch_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ |
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index a0dea3d1296e..6f3289a57888 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
@@ -14,6 +14,8 @@ | |||
14 | * any later version. | 14 | * any later version. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
18 | |||
17 | #include <linux/module.h> | 19 | #include <linux/module.h> |
18 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
19 | #include <linux/init.h> | 21 | #include <linux/init.h> |
@@ -59,7 +61,8 @@ struct hid_report *hid_register_report(struct hid_device *device, unsigned type, | |||
59 | if (report_enum->report_id_hash[id]) | 61 | if (report_enum->report_id_hash[id]) |
60 | return report_enum->report_id_hash[id]; | 62 | return report_enum->report_id_hash[id]; |
61 | 63 | ||
62 | if (!(report = kzalloc(sizeof(struct hid_report), GFP_KERNEL))) | 64 | report = kzalloc(sizeof(struct hid_report), GFP_KERNEL); |
65 | if (!report) | ||
63 | return NULL; | 66 | return NULL; |
64 | 67 | ||
65 | if (id != 0) | 68 | if (id != 0) |
@@ -90,8 +93,11 @@ static struct hid_field *hid_register_field(struct hid_report *report, unsigned | |||
90 | return NULL; | 93 | return NULL; |
91 | } | 94 | } |
92 | 95 | ||
93 | if (!(field = kzalloc(sizeof(struct hid_field) + usages * sizeof(struct hid_usage) | 96 | field = kzalloc((sizeof(struct hid_field) + |
94 | + values * sizeof(unsigned), GFP_KERNEL))) return NULL; | 97 | usages * sizeof(struct hid_usage) + |
98 | values * sizeof(unsigned)), GFP_KERNEL); | ||
99 | if (!field) | ||
100 | return NULL; | ||
95 | 101 | ||
96 | field->index = report->maxfield++; | 102 | field->index = report->maxfield++; |
97 | report->field[field->index] = field; | 103 | report->field[field->index] = field; |
@@ -172,10 +178,14 @@ static int close_collection(struct hid_parser *parser) | |||
172 | 178 | ||
173 | static unsigned hid_lookup_collection(struct hid_parser *parser, unsigned type) | 179 | static unsigned hid_lookup_collection(struct hid_parser *parser, unsigned type) |
174 | { | 180 | { |
181 | struct hid_collection *collection = parser->device->collection; | ||
175 | int n; | 182 | int n; |
176 | for (n = parser->collection_stack_ptr - 1; n >= 0; n--) | 183 | |
177 | if (parser->device->collection[parser->collection_stack[n]].type == type) | 184 | for (n = parser->collection_stack_ptr - 1; n >= 0; n--) { |
178 | return parser->device->collection[parser->collection_stack[n]].usage; | 185 | unsigned index = parser->collection_stack[n]; |
186 | if (collection[index].type == type) | ||
187 | return collection[index].usage; | ||
188 | } | ||
179 | return 0; /* we know nothing about this usage type */ | 189 | return 0; /* we know nothing about this usage type */ |
180 | } | 190 | } |
181 | 191 | ||
@@ -209,7 +219,8 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign | |||
209 | unsigned offset; | 219 | unsigned offset; |
210 | int i; | 220 | int i; |
211 | 221 | ||
212 | if (!(report = hid_register_report(parser->device, report_type, parser->global.report_id))) { | 222 | report = hid_register_report(parser->device, report_type, parser->global.report_id); |
223 | if (!report) { | ||
213 | dbg_hid("hid_register_report failed\n"); | 224 | dbg_hid("hid_register_report failed\n"); |
214 | return -1; | 225 | return -1; |
215 | } | 226 | } |
@@ -227,7 +238,8 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign | |||
227 | 238 | ||
228 | usages = max_t(int, parser->local.usage_index, parser->global.report_count); | 239 | usages = max_t(int, parser->local.usage_index, parser->global.report_count); |
229 | 240 | ||
230 | if ((field = hid_register_field(report, usages, parser->global.report_count)) == NULL) | 241 | field = hid_register_field(report, usages, parser->global.report_count); |
242 | if (!field) | ||
231 | return 0; | 243 | return 0; |
232 | 244 | ||
233 | field->physical = hid_lookup_collection(parser, HID_COLLECTION_PHYSICAL); | 245 | field->physical = hid_lookup_collection(parser, HID_COLLECTION_PHYSICAL); |
@@ -294,7 +306,7 @@ static int hid_parser_global(struct hid_parser *parser, struct hid_item *item) | |||
294 | case HID_GLOBAL_ITEM_TAG_PUSH: | 306 | case HID_GLOBAL_ITEM_TAG_PUSH: |
295 | 307 | ||
296 | if (parser->global_stack_ptr == HID_GLOBAL_STACK_SIZE) { | 308 | if (parser->global_stack_ptr == HID_GLOBAL_STACK_SIZE) { |
297 | dbg_hid("global enviroment stack overflow\n"); | 309 | dbg_hid("global environment stack overflow\n"); |
298 | return -1; | 310 | return -1; |
299 | } | 311 | } |
300 | 312 | ||
@@ -305,7 +317,7 @@ static int hid_parser_global(struct hid_parser *parser, struct hid_item *item) | |||
305 | case HID_GLOBAL_ITEM_TAG_POP: | 317 | case HID_GLOBAL_ITEM_TAG_POP: |
306 | 318 | ||
307 | if (!parser->global_stack_ptr) { | 319 | if (!parser->global_stack_ptr) { |
308 | dbg_hid("global enviroment stack underflow\n"); | 320 | dbg_hid("global environment stack underflow\n"); |
309 | return -1; | 321 | return -1; |
310 | } | 322 | } |
311 | 323 | ||
@@ -388,12 +400,6 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item) | |||
388 | __u32 data; | 400 | __u32 data; |
389 | unsigned n; | 401 | unsigned n; |
390 | 402 | ||
391 | /* Local delimiter could have value 0, which allows size to be 0 */ | ||
392 | if (item->size == 0 && item->tag != HID_LOCAL_ITEM_TAG_DELIMITER) { | ||
393 | dbg_hid("item data expected for local item\n"); | ||
394 | return -1; | ||
395 | } | ||
396 | |||
397 | data = item_udata(item); | 403 | data = item_udata(item); |
398 | 404 | ||
399 | switch (item->tag) { | 405 | switch (item->tag) { |
@@ -651,20 +657,19 @@ int hid_parse_report(struct hid_device *device, __u8 *start, | |||
651 | }; | 657 | }; |
652 | 658 | ||
653 | if (device->driver->report_fixup) | 659 | if (device->driver->report_fixup) |
654 | device->driver->report_fixup(device, start, size); | 660 | start = device->driver->report_fixup(device, start, &size); |
655 | 661 | ||
656 | device->rdesc = kmemdup(start, size, GFP_KERNEL); | 662 | device->rdesc = kmemdup(start, size, GFP_KERNEL); |
657 | if (device->rdesc == NULL) | 663 | if (device->rdesc == NULL) |
658 | return -ENOMEM; | 664 | return -ENOMEM; |
659 | device->rsize = size; | 665 | device->rsize = size; |
660 | 666 | ||
661 | parser = vmalloc(sizeof(struct hid_parser)); | 667 | parser = vzalloc(sizeof(struct hid_parser)); |
662 | if (!parser) { | 668 | if (!parser) { |
663 | ret = -ENOMEM; | 669 | ret = -ENOMEM; |
664 | goto err; | 670 | goto err; |
665 | } | 671 | } |
666 | 672 | ||
667 | memset(parser, 0, sizeof(struct hid_parser)); | ||
668 | parser->device = device; | 673 | parser->device = device; |
669 | 674 | ||
670 | end = start + size; | 675 | end = start + size; |
@@ -678,7 +683,8 @@ int hid_parse_report(struct hid_device *device, __u8 *start, | |||
678 | 683 | ||
679 | if (dispatch_type[item.type](parser, &item)) { | 684 | if (dispatch_type[item.type](parser, &item)) { |
680 | dbg_hid("item %u %u %u %u parsing failed\n", | 685 | dbg_hid("item %u %u %u %u parsing failed\n", |
681 | item.format, (unsigned)item.size, (unsigned)item.type, (unsigned)item.tag); | 686 | item.format, (unsigned)item.size, |
687 | (unsigned)item.type, (unsigned)item.tag); | ||
682 | goto err; | 688 | goto err; |
683 | } | 689 | } |
684 | 690 | ||
@@ -743,13 +749,14 @@ static u32 s32ton(__s32 value, unsigned n) | |||
743 | * Search linux-kernel and linux-usb-devel archives for "hid-core extract". | 749 | * Search linux-kernel and linux-usb-devel archives for "hid-core extract". |
744 | */ | 750 | */ |
745 | 751 | ||
746 | static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n) | 752 | static __u32 extract(const struct hid_device *hid, __u8 *report, |
753 | unsigned offset, unsigned n) | ||
747 | { | 754 | { |
748 | u64 x; | 755 | u64 x; |
749 | 756 | ||
750 | if (n > 32) | 757 | if (n > 32) |
751 | printk(KERN_WARNING "HID: extract() called with n (%d) > 32! (%s)\n", | 758 | hid_warn(hid, "extract() called with n (%d) > 32! (%s)\n", |
752 | n, current->comm); | 759 | n, current->comm); |
753 | 760 | ||
754 | report += offset >> 3; /* adjust byte index */ | 761 | report += offset >> 3; /* adjust byte index */ |
755 | offset &= 7; /* now only need bit offset into one byte */ | 762 | offset &= 7; /* now only need bit offset into one byte */ |
@@ -766,18 +773,19 @@ static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n) | |||
766 | * endianness of register values by considering a register | 773 | * endianness of register values by considering a register |
767 | * a "cached" copy of the little endiad bit stream. | 774 | * a "cached" copy of the little endiad bit stream. |
768 | */ | 775 | */ |
769 | static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u32 value) | 776 | static void implement(const struct hid_device *hid, __u8 *report, |
777 | unsigned offset, unsigned n, __u32 value) | ||
770 | { | 778 | { |
771 | u64 x; | 779 | u64 x; |
772 | u64 m = (1ULL << n) - 1; | 780 | u64 m = (1ULL << n) - 1; |
773 | 781 | ||
774 | if (n > 32) | 782 | if (n > 32) |
775 | printk(KERN_WARNING "HID: implement() called with n (%d) > 32! (%s)\n", | 783 | hid_warn(hid, "%s() called with n (%d) > 32! (%s)\n", |
776 | n, current->comm); | 784 | __func__, n, current->comm); |
777 | 785 | ||
778 | if (value > m) | 786 | if (value > m) |
779 | printk(KERN_WARNING "HID: implement() called with too large value %d! (%s)\n", | 787 | hid_warn(hid, "%s() called with too large value %d! (%s)\n", |
780 | value, current->comm); | 788 | __func__, value, current->comm); |
781 | WARN_ON(value > m); | 789 | WARN_ON(value > m); |
782 | value &= m; | 790 | value &= m; |
783 | 791 | ||
@@ -794,7 +802,7 @@ static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u3 | |||
794 | * Search an array for a value. | 802 | * Search an array for a value. |
795 | */ | 803 | */ |
796 | 804 | ||
797 | static __inline__ int search(__s32 *array, __s32 value, unsigned n) | 805 | static int search(__s32 *array, __s32 value, unsigned n) |
798 | { | 806 | { |
799 | while (n--) { | 807 | while (n--) { |
800 | if (*array++ == value) | 808 | if (*array++ == value) |
@@ -893,18 +901,22 @@ static void hid_input_field(struct hid_device *hid, struct hid_field *field, | |||
893 | __s32 max = field->logical_maximum; | 901 | __s32 max = field->logical_maximum; |
894 | __s32 *value; | 902 | __s32 *value; |
895 | 903 | ||
896 | if (!(value = kmalloc(sizeof(__s32) * count, GFP_ATOMIC))) | 904 | value = kmalloc(sizeof(__s32) * count, GFP_ATOMIC); |
905 | if (!value) | ||
897 | return; | 906 | return; |
898 | 907 | ||
899 | for (n = 0; n < count; n++) { | 908 | for (n = 0; n < count; n++) { |
900 | 909 | ||
901 | value[n] = min < 0 ? snto32(extract(data, offset + n * size, size), size) : | 910 | value[n] = min < 0 ? |
902 | extract(data, offset + n * size, size); | 911 | snto32(extract(hid, data, offset + n * size, size), |
912 | size) : | ||
913 | extract(hid, data, offset + n * size, size); | ||
903 | 914 | ||
904 | if (!(field->flags & HID_MAIN_ITEM_VARIABLE) /* Ignore report if ErrorRollOver */ | 915 | /* Ignore report if ErrorRollOver */ |
905 | && value[n] >= min && value[n] <= max | 916 | if (!(field->flags & HID_MAIN_ITEM_VARIABLE) && |
906 | && field->usage[value[n] - min].hid == HID_UP_KEYBOARD + 1) | 917 | value[n] >= min && value[n] <= max && |
907 | goto exit; | 918 | field->usage[value[n] - min].hid == HID_UP_KEYBOARD + 1) |
919 | goto exit; | ||
908 | } | 920 | } |
909 | 921 | ||
910 | for (n = 0; n < count; n++) { | 922 | for (n = 0; n < count; n++) { |
@@ -934,7 +946,8 @@ exit: | |||
934 | * Output the field into the report. | 946 | * Output the field into the report. |
935 | */ | 947 | */ |
936 | 948 | ||
937 | static void hid_output_field(struct hid_field *field, __u8 *data) | 949 | static void hid_output_field(const struct hid_device *hid, |
950 | struct hid_field *field, __u8 *data) | ||
938 | { | 951 | { |
939 | unsigned count = field->report_count; | 952 | unsigned count = field->report_count; |
940 | unsigned offset = field->report_offset; | 953 | unsigned offset = field->report_offset; |
@@ -943,9 +956,11 @@ static void hid_output_field(struct hid_field *field, __u8 *data) | |||
943 | 956 | ||
944 | for (n = 0; n < count; n++) { | 957 | for (n = 0; n < count; n++) { |
945 | if (field->logical_minimum < 0) /* signed values */ | 958 | if (field->logical_minimum < 0) /* signed values */ |
946 | implement(data, offset + n * size, size, s32ton(field->value[n], size)); | 959 | implement(hid, data, offset + n * size, size, |
960 | s32ton(field->value[n], size)); | ||
947 | else /* unsigned values */ | 961 | else /* unsigned values */ |
948 | implement(data, offset + n * size, size, field->value[n]); | 962 | implement(hid, data, offset + n * size, size, |
963 | field->value[n]); | ||
949 | } | 964 | } |
950 | } | 965 | } |
951 | 966 | ||
@@ -962,7 +977,7 @@ void hid_output_report(struct hid_report *report, __u8 *data) | |||
962 | 977 | ||
963 | memset(data, 0, ((report->size - 1) >> 3) + 1); | 978 | memset(data, 0, ((report->size - 1) >> 3) + 1); |
964 | for (n = 0; n < report->maxfield; n++) | 979 | for (n = 0; n < report->maxfield; n++) |
965 | hid_output_field(report->field[n], data); | 980 | hid_output_field(report->device, report->field[n], data); |
966 | } | 981 | } |
967 | EXPORT_SYMBOL_GPL(hid_output_report); | 982 | EXPORT_SYMBOL_GPL(hid_output_report); |
968 | 983 | ||
@@ -1030,6 +1045,9 @@ void hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size, | |||
1030 | 1045 | ||
1031 | rsize = ((report->size - 1) >> 3) + 1; | 1046 | rsize = ((report->size - 1) >> 3) + 1; |
1032 | 1047 | ||
1048 | if (rsize > HID_MAX_BUFFER_SIZE) | ||
1049 | rsize = HID_MAX_BUFFER_SIZE; | ||
1050 | |||
1033 | if (csize < rsize) { | 1051 | if (csize < rsize) { |
1034 | dbg_hid("report %d is too short, (%d < %d)\n", report->id, | 1052 | dbg_hid("report %d is too short, (%d < %d)\n", report->id, |
1035 | csize, rsize); | 1053 | csize, rsize); |
@@ -1144,6 +1162,32 @@ static bool hid_hiddev(struct hid_device *hdev) | |||
1144 | return !!hid_match_id(hdev, hid_hiddev_list); | 1162 | return !!hid_match_id(hdev, hid_hiddev_list); |
1145 | } | 1163 | } |
1146 | 1164 | ||
1165 | |||
1166 | static ssize_t | ||
1167 | read_report_descriptor(struct file *filp, struct kobject *kobj, | ||
1168 | struct bin_attribute *attr, | ||
1169 | char *buf, loff_t off, size_t count) | ||
1170 | { | ||
1171 | struct device *dev = container_of(kobj, struct device, kobj); | ||
1172 | struct hid_device *hdev = container_of(dev, struct hid_device, dev); | ||
1173 | |||
1174 | if (off >= hdev->rsize) | ||
1175 | return 0; | ||
1176 | |||
1177 | if (off + count > hdev->rsize) | ||
1178 | count = hdev->rsize - off; | ||
1179 | |||
1180 | memcpy(buf, hdev->rdesc + off, count); | ||
1181 | |||
1182 | return count; | ||
1183 | } | ||
1184 | |||
1185 | static struct bin_attribute dev_bin_attr_report_desc = { | ||
1186 | .attr = { .name = "report_descriptor", .mode = 0444 }, | ||
1187 | .read = read_report_descriptor, | ||
1188 | .size = HID_MAX_DESCRIPTOR_SIZE, | ||
1189 | }; | ||
1190 | |||
1147 | int hid_connect(struct hid_device *hdev, unsigned int connect_mask) | 1191 | int hid_connect(struct hid_device *hdev, unsigned int connect_mask) |
1148 | { | 1192 | { |
1149 | static const char *types[] = { "Device", "Pointer", "Mouse", "Device", | 1193 | static const char *types[] = { "Device", "Pointer", "Mouse", "Device", |
@@ -1154,6 +1198,7 @@ int hid_connect(struct hid_device *hdev, unsigned int connect_mask) | |||
1154 | char buf[64]; | 1198 | char buf[64]; |
1155 | unsigned int i; | 1199 | unsigned int i; |
1156 | int len; | 1200 | int len; |
1201 | int ret; | ||
1157 | 1202 | ||
1158 | if (hdev->quirks & HID_QUIRK_HIDDEV_FORCE) | 1203 | if (hdev->quirks & HID_QUIRK_HIDDEV_FORCE) |
1159 | connect_mask |= (HID_CONNECT_HIDDEV_FORCE | HID_CONNECT_HIDDEV); | 1204 | connect_mask |= (HID_CONNECT_HIDDEV_FORCE | HID_CONNECT_HIDDEV); |
@@ -1175,8 +1220,7 @@ int hid_connect(struct hid_device *hdev, unsigned int connect_mask) | |||
1175 | hdev->claimed |= HID_CLAIMED_HIDRAW; | 1220 | hdev->claimed |= HID_CLAIMED_HIDRAW; |
1176 | 1221 | ||
1177 | if (!hdev->claimed) { | 1222 | if (!hdev->claimed) { |
1178 | dev_err(&hdev->dev, "claimed by neither input, hiddev nor " | 1223 | hid_err(hdev, "claimed by neither input, hiddev nor hidraw\n"); |
1179 | "hidraw\n"); | ||
1180 | return -ENODEV; | 1224 | return -ENODEV; |
1181 | } | 1225 | } |
1182 | 1226 | ||
@@ -1216,9 +1260,14 @@ int hid_connect(struct hid_device *hdev, unsigned int connect_mask) | |||
1216 | bus = "<UNKNOWN>"; | 1260 | bus = "<UNKNOWN>"; |
1217 | } | 1261 | } |
1218 | 1262 | ||
1219 | dev_info(&hdev->dev, "%s: %s HID v%x.%02x %s [%s] on %s\n", | 1263 | ret = device_create_bin_file(&hdev->dev, &dev_bin_attr_report_desc); |
1220 | buf, bus, hdev->version >> 8, hdev->version & 0xff, | 1264 | if (ret) |
1221 | type, hdev->name, hdev->phys); | 1265 | hid_warn(hdev, |
1266 | "can't create sysfs report descriptor attribute err: %d\n", ret); | ||
1267 | |||
1268 | hid_info(hdev, "%s: %s HID v%x.%02x %s [%s] on %s\n", | ||
1269 | buf, bus, hdev->version >> 8, hdev->version & 0xff, | ||
1270 | type, hdev->name, hdev->phys); | ||
1222 | 1271 | ||
1223 | return 0; | 1272 | return 0; |
1224 | } | 1273 | } |
@@ -1226,6 +1275,7 @@ EXPORT_SYMBOL_GPL(hid_connect); | |||
1226 | 1275 | ||
1227 | void hid_disconnect(struct hid_device *hdev) | 1276 | void hid_disconnect(struct hid_device *hdev) |
1228 | { | 1277 | { |
1278 | device_remove_bin_file(&hdev->dev, &dev_bin_attr_report_desc); | ||
1229 | if (hdev->claimed & HID_CLAIMED_INPUT) | 1279 | if (hdev->claimed & HID_CLAIMED_INPUT) |
1230 | hidinput_disconnect(hdev); | 1280 | hidinput_disconnect(hdev); |
1231 | if (hdev->claimed & HID_CLAIMED_HIDDEV) | 1281 | if (hdev->claimed & HID_CLAIMED_HIDDEV) |
@@ -1236,18 +1286,19 @@ void hid_disconnect(struct hid_device *hdev) | |||
1236 | EXPORT_SYMBOL_GPL(hid_disconnect); | 1286 | EXPORT_SYMBOL_GPL(hid_disconnect); |
1237 | 1287 | ||
1238 | /* a list of devices for which there is a specialized driver on HID bus */ | 1288 | /* a list of devices for which there is a specialized driver on HID bus */ |
1239 | static const struct hid_device_id hid_blacklist[] = { | 1289 | static const struct hid_device_id hid_have_special_driver[] = { |
1240 | { HID_USB_DEVICE(USB_VENDOR_ID_3M, USB_DEVICE_ID_3M1968) }, | 1290 | { HID_USB_DEVICE(USB_VENDOR_ID_3M, USB_DEVICE_ID_3M1968) }, |
1241 | { HID_USB_DEVICE(USB_VENDOR_ID_3M, USB_DEVICE_ID_3M2256) }, | 1291 | { HID_USB_DEVICE(USB_VENDOR_ID_3M, USB_DEVICE_ID_3M2256) }, |
1242 | { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU) }, | 1292 | { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU) }, |
1243 | { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D) }, | 1293 | { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D) }, |
1244 | #if defined(CONFIG_HID_ACRUX_FF) || defined(CONFIG_HID_ACRUX_FF_MODULE) | 1294 | { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_RP_649) }, |
1245 | { HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0x0802) }, | 1295 | { HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0x0802) }, |
1246 | #endif | 1296 | { HID_USB_DEVICE(USB_VENDOR_ID_ACTIONSTAR, USB_DEVICE_ID_ACTIONSTAR_1011) }, |
1247 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ATV_IRCONTROL) }, | 1297 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ATV_IRCONTROL) }, |
1248 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4) }, | 1298 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4) }, |
1249 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE) }, | 1299 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE) }, |
1250 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICMOUSE) }, | 1300 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICMOUSE) }, |
1301 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICTRACKPAD) }, | ||
1251 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI) }, | 1302 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI) }, |
1252 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO) }, | 1303 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO) }, |
1253 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI) }, | 1304 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI) }, |
@@ -1280,6 +1331,15 @@ static const struct hid_device_id hid_blacklist[] = { | |||
1280 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI) }, | 1331 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI) }, |
1281 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO) }, | 1332 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO) }, |
1282 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS) }, | 1333 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS) }, |
1334 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI) }, | ||
1335 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ISO) }, | ||
1336 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_JIS) }, | ||
1337 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI) }, | ||
1338 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO) }, | ||
1339 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) }, | ||
1340 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI) }, | ||
1341 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO) }, | ||
1342 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS) }, | ||
1283 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) }, | 1343 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) }, |
1284 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) }, | 1344 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) }, |
1285 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) }, | 1345 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) }, |
@@ -1290,32 +1350,51 @@ static const struct hid_device_id hid_blacklist[] = { | |||
1290 | { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) }, | 1350 | { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) }, |
1291 | { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) }, | 1351 | { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) }, |
1292 | { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) }, | 1352 | { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) }, |
1353 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) }, | ||
1293 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH) }, | 1354 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH) }, |
1355 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_10_1) }, | ||
1294 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) }, | 1356 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) }, |
1295 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) }, | 1357 | { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) }, |
1296 | { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) }, | 1358 | { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) }, |
1297 | { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR) }, | 1359 | { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR) }, |
1298 | { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) }, | 1360 | { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) }, |
1361 | { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS) }, | ||
1362 | { HID_USB_DEVICE(USB_VENDOR_ID_CHUNGHWAT, USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH) }, | ||
1299 | { HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) }, | 1363 | { HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) }, |
1364 | { HID_USB_DEVICE(USB_VENDOR_ID_CVTOUCH, USB_DEVICE_ID_CVTOUCH_SCREEN) }, | ||
1300 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) }, | 1365 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) }, |
1301 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) }, | 1366 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) }, |
1302 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_3) }, | 1367 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_3) }, |
1303 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE) }, | 1368 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE) }, |
1369 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_TRUETOUCH) }, | ||
1304 | { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) }, | 1370 | { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) }, |
1371 | { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0011) }, | ||
1305 | { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH) }, | 1372 | { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH) }, |
1306 | { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1) }, | 1373 | { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1) }, |
1374 | { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH2) }, | ||
1375 | { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH3) }, | ||
1376 | { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH4) }, | ||
1307 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) }, | 1377 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) }, |
1378 | { HID_USB_DEVICE(USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2515) }, | ||
1379 | { HID_USB_DEVICE(USB_VENDOR_ID_EMS, USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II) }, | ||
1308 | { HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) }, | 1380 | { HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) }, |
1309 | { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) }, | 1381 | { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) }, |
1310 | { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR) }, | 1382 | { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR) }, |
1383 | { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS) }, | ||
1384 | { HID_USB_DEVICE(USB_VENDOR_ID_GOODTOUCH, USB_DEVICE_ID_GOODTOUCH_000f) }, | ||
1311 | { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003) }, | 1385 | { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003) }, |
1312 | { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0012) }, | 1386 | { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0012) }, |
1313 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) }, | 1387 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) }, |
1314 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) }, | 1388 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) }, |
1315 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) }, | 1389 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) }, |
1390 | { HID_USB_DEVICE(USB_VENDOR_ID_HANVON, USB_DEVICE_ID_HANVON_MULTITOUCH) }, | ||
1391 | { HID_USB_DEVICE(USB_VENDOR_ID_ILITEK, USB_DEVICE_ID_ILITEK_MULTITOUCH) }, | ||
1392 | { HID_USB_DEVICE(USB_VENDOR_ID_IRTOUCHSYSTEMS, USB_DEVICE_ID_IRTOUCH_INFRARED_USB) }, | ||
1316 | { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) }, | 1393 | { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) }, |
1394 | { HID_USB_DEVICE(USB_VENDOR_ID_KEYTOUCH, USB_DEVICE_ID_KEYTOUCH_IEC) }, | ||
1317 | { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) }, | 1395 | { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) }, |
1318 | { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) }, | 1396 | { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) }, |
1397 | { HID_USB_DEVICE(USB_VENDOR_ID_LCPOWER, USB_DEVICE_ID_LCPOWER_LC1000 ) }, | ||
1319 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) }, | 1398 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) }, |
1320 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) }, | 1399 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) }, |
1321 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2) }, | 1400 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2) }, |
@@ -1327,6 +1406,7 @@ static const struct hid_device_id hid_blacklist[] = { | |||
1327 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500) }, | 1406 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500) }, |
1328 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D) }, | 1407 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D) }, |
1329 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL) }, | 1408 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL) }, |
1409 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD) }, | ||
1330 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD) }, | 1410 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD) }, |
1331 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2) }, | 1411 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2) }, |
1332 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_F3D) }, | 1412 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_F3D) }, |
@@ -1335,10 +1415,15 @@ static const struct hid_device_id hid_blacklist[] = { | |||
1335 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FLIGHT_SYSTEM_G940) }, | 1415 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FLIGHT_SYSTEM_G940) }, |
1336 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL) }, | 1416 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL) }, |
1337 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2) }, | 1417 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2) }, |
1418 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFP_WHEEL) }, | ||
1338 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL) }, | 1419 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL) }, |
1420 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G27_WHEEL) }, | ||
1421 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WII_WHEEL) }, | ||
1339 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2) }, | 1422 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2) }, |
1340 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACETRAVELLER) }, | 1423 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACETRAVELLER) }, |
1341 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACENAVIGATOR) }, | 1424 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACENAVIGATOR) }, |
1425 | { HID_USB_DEVICE(USB_VENDOR_ID_LUMIO, USB_DEVICE_ID_CRYSTALTOUCH) }, | ||
1426 | { HID_USB_DEVICE(USB_VENDOR_ID_LUMIO, USB_DEVICE_ID_CRYSTALTOUCH_DUAL) }, | ||
1342 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD) }, | 1427 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD) }, |
1343 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD_BOOTLOADER) }, | 1428 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD_BOOTLOADER) }, |
1344 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV) }, | 1429 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV) }, |
@@ -1366,17 +1451,28 @@ static const struct hid_device_id hid_blacklist[] = { | |||
1366 | { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_16) }, | 1451 | { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_16) }, |
1367 | { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_17) }, | 1452 | { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_17) }, |
1368 | { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_18) }, | 1453 | { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_18) }, |
1454 | { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_PKB1700) }, | ||
1369 | { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) }, | 1455 | { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) }, |
1456 | { HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_PCI) }, | ||
1370 | { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) }, | 1457 | { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) }, |
1371 | { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) }, | 1458 | { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) }, |
1372 | { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN) }, | 1459 | { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN) }, |
1373 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONE) }, | 1460 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONE) }, |
1461 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ARVO) }, | ||
1462 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) }, | ||
1463 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KOVAPLUS) }, | ||
1464 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRED) }, | ||
1465 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS) }, | ||
1374 | { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, | 1466 | { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, |
1375 | { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) }, | 1467 | { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) }, |
1468 | { HID_USB_DEVICE(USB_VENDOR_ID_SKYCABLE, USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER) }, | ||
1376 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, | 1469 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, |
1470 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER) }, | ||
1377 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, | 1471 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, |
1378 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) }, | 1472 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) }, |
1379 | { HID_USB_DEVICE(USB_VENDOR_ID_STANTUM, USB_DEVICE_ID_MTP) }, | 1473 | { HID_USB_DEVICE(USB_VENDOR_ID_STANTUM, USB_DEVICE_ID_MTP) }, |
1474 | { HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_STM, USB_DEVICE_ID_MTP_STM) }, | ||
1475 | { HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_SITRONIX, USB_DEVICE_ID_MTP_SITRONIX) }, | ||
1380 | { HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) }, | 1476 | { HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) }, |
1381 | { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300) }, | 1477 | { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300) }, |
1382 | { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304) }, | 1478 | { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304) }, |
@@ -1385,11 +1481,24 @@ static const struct hid_device_id hid_blacklist[] = { | |||
1385 | { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb651) }, | 1481 | { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb651) }, |
1386 | { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb653) }, | 1482 | { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb653) }, |
1387 | { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb654) }, | 1483 | { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb654) }, |
1484 | { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb65a) }, | ||
1388 | { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) }, | 1485 | { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) }, |
1389 | { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED2, USB_DEVICE_ID_TOPSEED2_RF_COMBO) }, | 1486 | { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED2, USB_DEVICE_ID_TOPSEED2_RF_COMBO) }, |
1487 | { HID_USB_DEVICE(USB_VENDOR_ID_TOUCH_INTL, USB_DEVICE_ID_TOUCH_INTL_MULTI_TOUCH) }, | ||
1390 | { HID_USB_DEVICE(USB_VENDOR_ID_TWINHAN, USB_DEVICE_ID_TWINHAN_IR_REMOTE) }, | 1488 | { HID_USB_DEVICE(USB_VENDOR_ID_TWINHAN, USB_DEVICE_ID_TWINHAN_IR_REMOTE) }, |
1489 | { HID_USB_DEVICE(USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART) }, | ||
1490 | { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209) }, | ||
1491 | { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U) }, | ||
1492 | { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U) }, | ||
1493 | { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U) }, | ||
1494 | { HID_USB_DEVICE(USB_VENDOR_ID_UNITEC, USB_DEVICE_ID_UNITEC_USB_TOUCH_0709) }, | ||
1495 | { HID_USB_DEVICE(USB_VENDOR_ID_UNITEC, USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19) }, | ||
1391 | { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) }, | 1496 | { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) }, |
1392 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) }, | 1497 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) }, |
1498 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH) }, | ||
1499 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_12_1_INCH) }, | ||
1500 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH) }, | ||
1501 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH) }, | ||
1393 | { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) }, | 1502 | { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) }, |
1394 | { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) }, | 1503 | { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) }, |
1395 | { HID_USB_DEVICE(USB_VENDOR_ID_ZYDACRON, USB_DEVICE_ID_ZYDACRON_REMOTE_CONTROL) }, | 1504 | { HID_USB_DEVICE(USB_VENDOR_ID_ZYDACRON, USB_DEVICE_ID_ZYDACRON_REMOTE_CONTROL) }, |
@@ -1486,9 +1595,9 @@ static int hid_bus_match(struct device *dev, struct device_driver *drv) | |||
1486 | if (!hid_match_device(hdev, hdrv)) | 1595 | if (!hid_match_device(hdev, hdrv)) |
1487 | return 0; | 1596 | return 0; |
1488 | 1597 | ||
1489 | /* generic wants all non-blacklisted */ | 1598 | /* generic wants all that don't have specialized driver */ |
1490 | if (!strncmp(hdrv->name, "generic-", 8)) | 1599 | if (!strncmp(hdrv->name, "generic-", 8)) |
1491 | return !hid_match_id(hdev, hid_blacklist); | 1600 | return !hid_match_id(hdev, hid_have_special_driver); |
1492 | 1601 | ||
1493 | return 1; | 1602 | return 1; |
1494 | } | 1603 | } |
@@ -1594,10 +1703,10 @@ static const struct hid_device_id hid_ignore_list[] = { | |||
1594 | { HID_USB_DEVICE(USB_VENDOR_ID_DEALEXTREAME, USB_DEVICE_ID_DEALEXTREAME_RADIO_SI4701) }, | 1703 | { HID_USB_DEVICE(USB_VENDOR_ID_DEALEXTREAME, USB_DEVICE_ID_DEALEXTREAME_RADIO_SI4701) }, |
1595 | { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE) }, | 1704 | { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE) }, |
1596 | { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20) }, | 1705 | { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20) }, |
1706 | { HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, 0x0004) }, | ||
1597 | { HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) }, | 1707 | { HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) }, |
1598 | { HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC5UH) }, | 1708 | { HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC5UH) }, |
1599 | { HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC4UM) }, | 1709 | { HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC4UM) }, |
1600 | { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0001) }, | ||
1601 | { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0002) }, | 1710 | { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0002) }, |
1602 | { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0003) }, | 1711 | { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0003) }, |
1603 | { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0004) }, | 1712 | { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0004) }, |
@@ -1662,24 +1771,43 @@ static const struct hid_device_id hid_ignore_list[] = { | |||
1662 | { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1006) }, | 1771 | { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1006) }, |
1663 | { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1007) }, | 1772 | { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1007) }, |
1664 | { HID_USB_DEVICE(USB_VENDOR_ID_IMATION, USB_DEVICE_ID_DISC_STAKKA) }, | 1773 | { HID_USB_DEVICE(USB_VENDOR_ID_IMATION, USB_DEVICE_ID_DISC_STAKKA) }, |
1774 | { HID_USB_DEVICE(USB_VENDOR_ID_JESS, USB_DEVICE_ID_JESS_YUREX) }, | ||
1665 | { HID_USB_DEVICE(USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO) }, | 1775 | { HID_USB_DEVICE(USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO) }, |
1666 | { HID_USB_DEVICE(USB_VENDOR_ID_KWORLD, USB_DEVICE_ID_KWORLD_RADIO_FM700) }, | 1776 | { HID_USB_DEVICE(USB_VENDOR_ID_KWORLD, USB_DEVICE_ID_KWORLD_RADIO_FM700) }, |
1667 | { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_GPEN_560) }, | 1777 | { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_GPEN_560) }, |
1668 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_KYE, 0x0058) }, | 1778 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_KYE, 0x0058) }, |
1669 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY) }, | 1779 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY) }, |
1780 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY2) }, | ||
1670 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POCKETCASSY) }, | 1781 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POCKETCASSY) }, |
1782 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POCKETCASSY2) }, | ||
1671 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOBILECASSY) }, | 1783 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOBILECASSY) }, |
1784 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOBILECASSY2) }, | ||
1785 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MICROCASSYVOLTAGE) }, | ||
1786 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MICROCASSYCURRENT) }, | ||
1787 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MICROCASSYTIME) }, | ||
1788 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MICROCASSYTEMPERATURE) }, | ||
1789 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MICROCASSYPH) }, | ||
1672 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_JWM) }, | 1790 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_JWM) }, |
1673 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_DMMP) }, | 1791 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_DMMP) }, |
1674 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_UMIP) }, | 1792 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_UMIP) }, |
1675 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY1) }, | 1793 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_UMIC) }, |
1794 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_UMIB) }, | ||
1795 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY) }, | ||
1676 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY2) }, | 1796 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY2) }, |
1677 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_VIDEOCOM) }, | 1797 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_VIDEOCOM) }, |
1798 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOTOR) }, | ||
1678 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_COM3LAB) }, | 1799 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_COM3LAB) }, |
1679 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_TELEPORT) }, | 1800 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_TELEPORT) }, |
1680 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_NETWORKANALYSER) }, | 1801 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_NETWORKANALYSER) }, |
1681 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POWERCONTROL) }, | 1802 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POWERCONTROL) }, |
1682 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MACHINETEST) }, | 1803 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MACHINETEST) }, |
1804 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOSTANALYSER) }, | ||
1805 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOSTANALYSER2) }, | ||
1806 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_ABSESP) }, | ||
1807 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_AUTODATABUS) }, | ||
1808 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MCT) }, | ||
1809 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_HYBRID) }, | ||
1810 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_HEATCONTROL) }, | ||
1683 | { HID_USB_DEVICE(USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1024LS) }, | 1811 | { HID_USB_DEVICE(USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1024LS) }, |
1684 | { HID_USB_DEVICE(USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1208LS) }, | 1812 | { HID_USB_DEVICE(USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1208LS) }, |
1685 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICKIT1) }, | 1813 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICKIT1) }, |
@@ -1746,6 +1874,15 @@ static const struct hid_device_id hid_mouse_ignore_list[] = { | |||
1746 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI) }, | 1874 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI) }, |
1747 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO) }, | 1875 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO) }, |
1748 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS) }, | 1876 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS) }, |
1877 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI) }, | ||
1878 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ISO) }, | ||
1879 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_JIS) }, | ||
1880 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI) }, | ||
1881 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO) }, | ||
1882 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) }, | ||
1883 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI) }, | ||
1884 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO) }, | ||
1885 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS) }, | ||
1749 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, | 1886 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, |
1750 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, | 1887 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, |
1751 | { } | 1888 | { } |
@@ -1770,6 +1907,11 @@ static bool hid_ignore(struct hid_device *hdev) | |||
1770 | hdev->product <= USB_DEVICE_ID_SOUNDGRAPH_IMON_LAST) | 1907 | hdev->product <= USB_DEVICE_ID_SOUNDGRAPH_IMON_LAST) |
1771 | return true; | 1908 | return true; |
1772 | break; | 1909 | break; |
1910 | case USB_VENDOR_ID_HANWANG: | ||
1911 | if (hdev->product >= USB_DEVICE_ID_HANWANG_TABLET_FIRST && | ||
1912 | hdev->product <= USB_DEVICE_ID_HANWANG_TABLET_LAST) | ||
1913 | return true; | ||
1914 | break; | ||
1773 | } | 1915 | } |
1774 | 1916 | ||
1775 | if (hdev->type == HID_TYPE_USBMOUSE && | 1917 | if (hdev->type == HID_TYPE_USBMOUSE && |
@@ -1932,12 +2074,12 @@ static int __init hid_init(void) | |||
1932 | int ret; | 2074 | int ret; |
1933 | 2075 | ||
1934 | if (hid_debug) | 2076 | if (hid_debug) |
1935 | printk(KERN_WARNING "HID: hid_debug is now used solely for parser and driver debugging.\n" | 2077 | pr_warn("hid_debug is now used solely for parser and driver debugging.\n" |
1936 | "HID: debugfs is now used for inspecting the device (report descriptor, reports)\n"); | 2078 | "debugfs is now used for inspecting the device (report descriptor, reports)\n"); |
1937 | 2079 | ||
1938 | ret = bus_register(&hid_bus_type); | 2080 | ret = bus_register(&hid_bus_type); |
1939 | if (ret) { | 2081 | if (ret) { |
1940 | printk(KERN_ERR "HID: can't register hid bus\n"); | 2082 | pr_err("can't register hid bus\n"); |
1941 | goto err; | 2083 | goto err; |
1942 | } | 2084 | } |
1943 | 2085 | ||
diff --git a/drivers/hid/hid-cypress.c b/drivers/hid/hid-cypress.c index 998b6f443d7d..2f0be4c66af7 100644 --- a/drivers/hid/hid-cypress.c +++ b/drivers/hid/hid-cypress.c | |||
@@ -31,16 +31,16 @@ | |||
31 | * Some USB barcode readers from cypress have usage min and usage max in | 31 | * Some USB barcode readers from cypress have usage min and usage max in |
32 | * the wrong order | 32 | * the wrong order |
33 | */ | 33 | */ |
34 | static void cp_report_fixup(struct hid_device *hdev, __u8 *rdesc, | 34 | static __u8 *cp_report_fixup(struct hid_device *hdev, __u8 *rdesc, |
35 | unsigned int rsize) | 35 | unsigned int *rsize) |
36 | { | 36 | { |
37 | unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); | 37 | unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); |
38 | unsigned int i; | 38 | unsigned int i; |
39 | 39 | ||
40 | if (!(quirks & CP_RDESC_SWAPPED_MIN_MAX)) | 40 | if (!(quirks & CP_RDESC_SWAPPED_MIN_MAX)) |
41 | return; | 41 | return rdesc; |
42 | 42 | ||
43 | for (i = 0; i < rsize - 4; i++) | 43 | for (i = 0; i < *rsize - 4; i++) |
44 | if (rdesc[i] == 0x29 && rdesc[i + 2] == 0x19) { | 44 | if (rdesc[i] == 0x29 && rdesc[i + 2] == 0x19) { |
45 | __u8 tmp; | 45 | __u8 tmp; |
46 | 46 | ||
@@ -50,6 +50,7 @@ static void cp_report_fixup(struct hid_device *hdev, __u8 *rdesc, | |||
50 | rdesc[i + 3] = rdesc[i + 1]; | 50 | rdesc[i + 3] = rdesc[i + 1]; |
51 | rdesc[i + 1] = tmp; | 51 | rdesc[i + 1] = tmp; |
52 | } | 52 | } |
53 | return rdesc; | ||
53 | } | 54 | } |
54 | 55 | ||
55 | static int cp_input_mapped(struct hid_device *hdev, struct hid_input *hi, | 56 | static int cp_input_mapped(struct hid_device *hdev, struct hid_input *hi, |
@@ -106,13 +107,13 @@ static int cp_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
106 | 107 | ||
107 | ret = hid_parse(hdev); | 108 | ret = hid_parse(hdev); |
108 | if (ret) { | 109 | if (ret) { |
109 | dev_err(&hdev->dev, "parse failed\n"); | 110 | hid_err(hdev, "parse failed\n"); |
110 | goto err_free; | 111 | goto err_free; |
111 | } | 112 | } |
112 | 113 | ||
113 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); | 114 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); |
114 | if (ret) { | 115 | if (ret) { |
115 | dev_err(&hdev->dev, "hw start failed\n"); | 116 | hid_err(hdev, "hw start failed\n"); |
116 | goto err_free; | 117 | goto err_free; |
117 | } | 118 | } |
118 | 119 | ||
diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c index 850d02a7a925..bae48745bb42 100644 --- a/drivers/hid/hid-debug.c +++ b/drivers/hid/hid-debug.c | |||
@@ -26,6 +26,8 @@ | |||
26 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic | 26 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic |
27 | */ | 27 | */ |
28 | 28 | ||
29 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
30 | |||
29 | #include <linux/debugfs.h> | 31 | #include <linux/debugfs.h> |
30 | #include <linux/seq_file.h> | 32 | #include <linux/seq_file.h> |
31 | #include <linux/sched.h> | 33 | #include <linux/sched.h> |
@@ -339,7 +341,7 @@ static const struct hid_usage_entry hid_usage_table[] = { | |||
339 | { 0x85, 0x83, "DesignCapacity" }, | 341 | { 0x85, 0x83, "DesignCapacity" }, |
340 | { 0x85, 0x85, "ManufacturerDate" }, | 342 | { 0x85, 0x85, "ManufacturerDate" }, |
341 | { 0x85, 0x89, "iDeviceChemistry" }, | 343 | { 0x85, 0x89, "iDeviceChemistry" }, |
342 | { 0x85, 0x8b, "Rechargable" }, | 344 | { 0x85, 0x8b, "Rechargeable" }, |
343 | { 0x85, 0x8f, "iOEMInformation" }, | 345 | { 0x85, 0x8f, "iOEMInformation" }, |
344 | { 0x85, 0x8d, "CapacityGranularity1" }, | 346 | { 0x85, 0x8d, "CapacityGranularity1" }, |
345 | { 0x85, 0xd0, "ACPresent" }, | 347 | { 0x85, 0xd0, "ACPresent" }, |
@@ -393,7 +395,7 @@ char *hid_resolv_usage(unsigned usage, struct seq_file *f) { | |||
393 | 395 | ||
394 | buf = resolv_usage_page(usage >> 16, f); | 396 | buf = resolv_usage_page(usage >> 16, f); |
395 | if (IS_ERR(buf)) { | 397 | if (IS_ERR(buf)) { |
396 | printk(KERN_ERR "error allocating HID debug buffer\n"); | 398 | pr_err("error allocating HID debug buffer\n"); |
397 | return NULL; | 399 | return NULL; |
398 | } | 400 | } |
399 | 401 | ||
@@ -570,6 +572,8 @@ void hid_debug_event(struct hid_device *hdev, char *buf) | |||
570 | buf[i]; | 572 | buf[i]; |
571 | list->tail = (list->tail + i) % HID_DEBUG_BUFSIZE; | 573 | list->tail = (list->tail + i) % HID_DEBUG_BUFSIZE; |
572 | } | 574 | } |
575 | |||
576 | wake_up_interruptible(&hdev->debug_wait); | ||
573 | } | 577 | } |
574 | EXPORT_SYMBOL_GPL(hid_debug_event); | 578 | EXPORT_SYMBOL_GPL(hid_debug_event); |
575 | 579 | ||
@@ -1051,6 +1055,7 @@ static const struct file_operations hid_debug_events_fops = { | |||
1051 | .read = hid_debug_events_read, | 1055 | .read = hid_debug_events_read, |
1052 | .poll = hid_debug_events_poll, | 1056 | .poll = hid_debug_events_poll, |
1053 | .release = hid_debug_events_release, | 1057 | .release = hid_debug_events_release, |
1058 | .llseek = noop_llseek, | ||
1054 | }; | 1059 | }; |
1055 | 1060 | ||
1056 | 1061 | ||
diff --git a/drivers/hid/hid-drff.c b/drivers/hid/hid-dr.c index 968b04f9b796..61eece47204d 100644 --- a/drivers/hid/hid-drff.c +++ b/drivers/hid/hid-dr.c | |||
@@ -96,18 +96,18 @@ static int drff_init(struct hid_device *hid) | |||
96 | int error; | 96 | int error; |
97 | 97 | ||
98 | if (list_empty(report_list)) { | 98 | if (list_empty(report_list)) { |
99 | dev_err(&hid->dev, "no output reports found\n"); | 99 | hid_err(hid, "no output reports found\n"); |
100 | return -ENODEV; | 100 | return -ENODEV; |
101 | } | 101 | } |
102 | 102 | ||
103 | report = list_first_entry(report_list, struct hid_report, list); | 103 | report = list_first_entry(report_list, struct hid_report, list); |
104 | if (report->maxfield < 1) { | 104 | if (report->maxfield < 1) { |
105 | dev_err(&hid->dev, "no fields in the report\n"); | 105 | hid_err(hid, "no fields in the report\n"); |
106 | return -ENODEV; | 106 | return -ENODEV; |
107 | } | 107 | } |
108 | 108 | ||
109 | if (report->field[0]->report_count < 7) { | 109 | if (report->field[0]->report_count < 7) { |
110 | dev_err(&hid->dev, "not enough values in the field\n"); | 110 | hid_err(hid, "not enough values in the field\n"); |
111 | return -ENODEV; | 111 | return -ENODEV; |
112 | } | 112 | } |
113 | 113 | ||
@@ -133,8 +133,8 @@ static int drff_init(struct hid_device *hid) | |||
133 | drff->report->field[0]->value[6] = 0x00; | 133 | drff->report->field[0]->value[6] = 0x00; |
134 | usbhid_submit_report(hid, drff->report, USB_DIR_OUT); | 134 | usbhid_submit_report(hid, drff->report, USB_DIR_OUT); |
135 | 135 | ||
136 | dev_info(&hid->dev, "Force Feedback for DragonRise Inc. game " | 136 | hid_info(hid, "Force Feedback for DragonRise Inc. " |
137 | "controllers by Richard Walmsley <richwalm@gmail.com>\n"); | 137 | "game controllers by Richard Walmsley <richwalm@gmail.com>\n"); |
138 | 138 | ||
139 | return 0; | 139 | return 0; |
140 | } | 140 | } |
@@ -145,6 +145,110 @@ static inline int drff_init(struct hid_device *hid) | |||
145 | } | 145 | } |
146 | #endif | 146 | #endif |
147 | 147 | ||
148 | /* | ||
149 | * The original descriptor of joystick with PID 0x0011, represented by DVTech PC | ||
150 | * JS19. It seems both copied from another device and a result of confusion | ||
151 | * either about the specification or about the program used to create the | ||
152 | * descriptor. In any case, it's a wonder it works on Windows. | ||
153 | * | ||
154 | * Usage Page (Desktop), ; Generic desktop controls (01h) | ||
155 | * Usage (Joystik), ; Joystik (04h, application collection) | ||
156 | * Collection (Application), | ||
157 | * Collection (Logical), | ||
158 | * Report Size (8), | ||
159 | * Report Count (5), | ||
160 | * Logical Minimum (0), | ||
161 | * Logical Maximum (255), | ||
162 | * Physical Minimum (0), | ||
163 | * Physical Maximum (255), | ||
164 | * Usage (X), ; X (30h, dynamic value) | ||
165 | * Usage (X), ; X (30h, dynamic value) | ||
166 | * Usage (X), ; X (30h, dynamic value) | ||
167 | * Usage (X), ; X (30h, dynamic value) | ||
168 | * Usage (Y), ; Y (31h, dynamic value) | ||
169 | * Input (Variable), | ||
170 | * Report Size (4), | ||
171 | * Report Count (1), | ||
172 | * Logical Maximum (7), | ||
173 | * Physical Maximum (315), | ||
174 | * Unit (Degrees), | ||
175 | * Usage (00h), | ||
176 | * Input (Variable, Null State), | ||
177 | * Unit, | ||
178 | * Report Size (1), | ||
179 | * Report Count (10), | ||
180 | * Logical Maximum (1), | ||
181 | * Physical Maximum (1), | ||
182 | * Usage Page (Button), ; Button (09h) | ||
183 | * Usage Minimum (01h), | ||
184 | * Usage Maximum (0Ah), | ||
185 | * Input (Variable), | ||
186 | * Usage Page (FF00h), ; FF00h, vendor-defined | ||
187 | * Report Size (1), | ||
188 | * Report Count (10), | ||
189 | * Logical Maximum (1), | ||
190 | * Physical Maximum (1), | ||
191 | * Usage (01h), | ||
192 | * Input (Variable), | ||
193 | * End Collection, | ||
194 | * Collection (Logical), | ||
195 | * Report Size (8), | ||
196 | * Report Count (4), | ||
197 | * Physical Maximum (255), | ||
198 | * Logical Maximum (255), | ||
199 | * Usage (02h), | ||
200 | * Output (Variable), | ||
201 | * End Collection, | ||
202 | * End Collection | ||
203 | */ | ||
204 | |||
205 | /* Size of the original descriptor of the PID 0x0011 joystick */ | ||
206 | #define PID0011_RDESC_ORIG_SIZE 101 | ||
207 | |||
208 | /* Fixed report descriptor for PID 0x011 joystick */ | ||
209 | static __u8 pid0011_rdesc_fixed[] = { | ||
210 | 0x05, 0x01, /* Usage Page (Desktop), */ | ||
211 | 0x09, 0x04, /* Usage (Joystik), */ | ||
212 | 0xA1, 0x01, /* Collection (Application), */ | ||
213 | 0xA1, 0x02, /* Collection (Logical), */ | ||
214 | 0x14, /* Logical Minimum (0), */ | ||
215 | 0x75, 0x08, /* Report Size (8), */ | ||
216 | 0x95, 0x03, /* Report Count (3), */ | ||
217 | 0x81, 0x01, /* Input (Constant), */ | ||
218 | 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ | ||
219 | 0x95, 0x02, /* Report Count (2), */ | ||
220 | 0x09, 0x30, /* Usage (X), */ | ||
221 | 0x09, 0x31, /* Usage (Y), */ | ||
222 | 0x81, 0x02, /* Input (Variable), */ | ||
223 | 0x75, 0x01, /* Report Size (1), */ | ||
224 | 0x95, 0x04, /* Report Count (4), */ | ||
225 | 0x81, 0x01, /* Input (Constant), */ | ||
226 | 0x25, 0x01, /* Logical Maximum (1), */ | ||
227 | 0x95, 0x0A, /* Report Count (10), */ | ||
228 | 0x05, 0x09, /* Usage Page (Button), */ | ||
229 | 0x19, 0x01, /* Usage Minimum (01h), */ | ||
230 | 0x29, 0x0A, /* Usage Maximum (0Ah), */ | ||
231 | 0x81, 0x02, /* Input (Variable), */ | ||
232 | 0x95, 0x0A, /* Report Count (10), */ | ||
233 | 0x81, 0x01, /* Input (Constant), */ | ||
234 | 0xC0, /* End Collection, */ | ||
235 | 0xC0 /* End Collection */ | ||
236 | }; | ||
237 | |||
238 | static __u8 *dr_report_fixup(struct hid_device *hdev, __u8 *rdesc, | ||
239 | unsigned int *rsize) | ||
240 | { | ||
241 | switch (hdev->product) { | ||
242 | case 0x0011: | ||
243 | if (*rsize == PID0011_RDESC_ORIG_SIZE) { | ||
244 | rdesc = pid0011_rdesc_fixed; | ||
245 | *rsize = sizeof(pid0011_rdesc_fixed); | ||
246 | } | ||
247 | break; | ||
248 | } | ||
249 | return rdesc; | ||
250 | } | ||
251 | |||
148 | static int dr_probe(struct hid_device *hdev, const struct hid_device_id *id) | 252 | static int dr_probe(struct hid_device *hdev, const struct hid_device_id *id) |
149 | { | 253 | { |
150 | int ret; | 254 | int ret; |
@@ -153,17 +257,26 @@ static int dr_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
153 | 257 | ||
154 | ret = hid_parse(hdev); | 258 | ret = hid_parse(hdev); |
155 | if (ret) { | 259 | if (ret) { |
156 | dev_err(&hdev->dev, "parse failed\n"); | 260 | hid_err(hdev, "parse failed\n"); |
157 | goto err; | 261 | goto err; |
158 | } | 262 | } |
159 | 263 | ||
160 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); | 264 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); |
161 | if (ret) { | 265 | if (ret) { |
162 | dev_err(&hdev->dev, "hw start failed\n"); | 266 | hid_err(hdev, "hw start failed\n"); |
163 | goto err; | 267 | goto err; |
164 | } | 268 | } |
165 | 269 | ||
166 | drff_init(hdev); | 270 | switch (hdev->product) { |
271 | case 0x0006: | ||
272 | ret = drff_init(hdev); | ||
273 | if (ret) { | ||
274 | dev_err(&hdev->dev, "force feedback init failed\n"); | ||
275 | hid_hw_stop(hdev); | ||
276 | goto err; | ||
277 | } | ||
278 | break; | ||
279 | } | ||
167 | 280 | ||
168 | return 0; | 281 | return 0; |
169 | err: | 282 | err: |
@@ -172,6 +285,7 @@ err: | |||
172 | 285 | ||
173 | static const struct hid_device_id dr_devices[] = { | 286 | static const struct hid_device_id dr_devices[] = { |
174 | { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006), }, | 287 | { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006), }, |
288 | { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0011), }, | ||
175 | { } | 289 | { } |
176 | }; | 290 | }; |
177 | MODULE_DEVICE_TABLE(hid, dr_devices); | 291 | MODULE_DEVICE_TABLE(hid, dr_devices); |
@@ -179,6 +293,7 @@ MODULE_DEVICE_TABLE(hid, dr_devices); | |||
179 | static struct hid_driver dr_driver = { | 293 | static struct hid_driver dr_driver = { |
180 | .name = "dragonrise", | 294 | .name = "dragonrise", |
181 | .id_table = dr_devices, | 295 | .id_table = dr_devices, |
296 | .report_fixup = dr_report_fixup, | ||
182 | .probe = dr_probe, | 297 | .probe = dr_probe, |
183 | }; | 298 | }; |
184 | 299 | ||
diff --git a/drivers/hid/hid-egalax.c b/drivers/hid/hid-egalax.c deleted file mode 100644 index 8ca7f65cf2f8..000000000000 --- a/drivers/hid/hid-egalax.c +++ /dev/null | |||
@@ -1,290 +0,0 @@ | |||
1 | /* | ||
2 | * HID driver for eGalax dual-touch panels | ||
3 | * | ||
4 | * Copyright (c) 2010 Stephane Chatty <chatty@enac.fr> | ||
5 | * | ||
6 | */ | ||
7 | |||
8 | /* | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the Free | ||
11 | * Software Foundation; either version 2 of the License, or (at your option) | ||
12 | * any later version. | ||
13 | */ | ||
14 | |||
15 | #include <linux/device.h> | ||
16 | #include <linux/hid.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/usb.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include "usbhid/usbhid.h" | ||
21 | |||
22 | MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>"); | ||
23 | MODULE_DESCRIPTION("eGalax dual-touch panel"); | ||
24 | MODULE_LICENSE("GPL"); | ||
25 | |||
26 | #include "hid-ids.h" | ||
27 | |||
28 | struct egalax_data { | ||
29 | __u16 x, y, z; | ||
30 | __u8 id; | ||
31 | bool first; /* is this the first finger in the frame? */ | ||
32 | bool valid; /* valid finger data, or just placeholder? */ | ||
33 | bool activity; /* at least one active finger previously? */ | ||
34 | __u16 lastx, lasty; /* latest valid (x, y) in the frame */ | ||
35 | }; | ||
36 | |||
37 | static int egalax_input_mapping(struct hid_device *hdev, struct hid_input *hi, | ||
38 | struct hid_field *field, struct hid_usage *usage, | ||
39 | unsigned long **bit, int *max) | ||
40 | { | ||
41 | switch (usage->hid & HID_USAGE_PAGE) { | ||
42 | |||
43 | case HID_UP_GENDESK: | ||
44 | switch (usage->hid) { | ||
45 | case HID_GD_X: | ||
46 | hid_map_usage(hi, usage, bit, max, | ||
47 | EV_ABS, ABS_MT_POSITION_X); | ||
48 | /* touchscreen emulation */ | ||
49 | input_set_abs_params(hi->input, ABS_X, | ||
50 | field->logical_minimum, | ||
51 | field->logical_maximum, 0, 0); | ||
52 | return 1; | ||
53 | case HID_GD_Y: | ||
54 | hid_map_usage(hi, usage, bit, max, | ||
55 | EV_ABS, ABS_MT_POSITION_Y); | ||
56 | /* touchscreen emulation */ | ||
57 | input_set_abs_params(hi->input, ABS_Y, | ||
58 | field->logical_minimum, | ||
59 | field->logical_maximum, 0, 0); | ||
60 | return 1; | ||
61 | } | ||
62 | return 0; | ||
63 | |||
64 | case HID_UP_DIGITIZER: | ||
65 | switch (usage->hid) { | ||
66 | case HID_DG_TIPSWITCH: | ||
67 | /* touchscreen emulation */ | ||
68 | hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); | ||
69 | return 1; | ||
70 | case HID_DG_INRANGE: | ||
71 | case HID_DG_CONFIDENCE: | ||
72 | case HID_DG_CONTACTCOUNT: | ||
73 | case HID_DG_CONTACTMAX: | ||
74 | return -1; | ||
75 | case HID_DG_CONTACTID: | ||
76 | hid_map_usage(hi, usage, bit, max, | ||
77 | EV_ABS, ABS_MT_TRACKING_ID); | ||
78 | return 1; | ||
79 | case HID_DG_TIPPRESSURE: | ||
80 | hid_map_usage(hi, usage, bit, max, | ||
81 | EV_ABS, ABS_MT_PRESSURE); | ||
82 | return 1; | ||
83 | } | ||
84 | return 0; | ||
85 | } | ||
86 | |||
87 | /* ignore others (from other reports we won't get anyway) */ | ||
88 | return -1; | ||
89 | } | ||
90 | |||
91 | static int egalax_input_mapped(struct hid_device *hdev, struct hid_input *hi, | ||
92 | struct hid_field *field, struct hid_usage *usage, | ||
93 | unsigned long **bit, int *max) | ||
94 | { | ||
95 | if (usage->type == EV_KEY || usage->type == EV_ABS) | ||
96 | clear_bit(usage->code, *bit); | ||
97 | |||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | /* | ||
102 | * this function is called when a whole finger has been parsed, | ||
103 | * so that it can decide what to send to the input layer. | ||
104 | */ | ||
105 | static void egalax_filter_event(struct egalax_data *td, struct input_dev *input) | ||
106 | { | ||
107 | td->first = !td->first; /* touchscreen emulation */ | ||
108 | |||
109 | if (td->valid) { | ||
110 | /* emit multitouch events */ | ||
111 | input_event(input, EV_ABS, ABS_MT_TRACKING_ID, td->id); | ||
112 | input_event(input, EV_ABS, ABS_MT_POSITION_X, td->x); | ||
113 | input_event(input, EV_ABS, ABS_MT_POSITION_Y, td->y); | ||
114 | input_event(input, EV_ABS, ABS_MT_PRESSURE, td->z); | ||
115 | |||
116 | input_mt_sync(input); | ||
117 | |||
118 | /* | ||
119 | * touchscreen emulation: store (x, y) as | ||
120 | * the last valid values in this frame | ||
121 | */ | ||
122 | td->lastx = td->x; | ||
123 | td->lasty = td->y; | ||
124 | } | ||
125 | |||
126 | /* | ||
127 | * touchscreen emulation: if this is the second finger and at least | ||
128 | * one in this frame is valid, the latest valid in the frame is | ||
129 | * the oldest on the panel, the one we want for single touch | ||
130 | */ | ||
131 | if (!td->first && td->activity) { | ||
132 | input_event(input, EV_ABS, ABS_X, td->lastx); | ||
133 | input_event(input, EV_ABS, ABS_Y, td->lasty); | ||
134 | } | ||
135 | |||
136 | if (!td->valid) { | ||
137 | /* | ||
138 | * touchscreen emulation: if the first finger is invalid | ||
139 | * and there previously was finger activity, this is a release | ||
140 | */ | ||
141 | if (td->first && td->activity) { | ||
142 | input_event(input, EV_KEY, BTN_TOUCH, 0); | ||
143 | td->activity = false; | ||
144 | } | ||
145 | return; | ||
146 | } | ||
147 | |||
148 | |||
149 | /* touchscreen emulation: if no previous activity, emit touch event */ | ||
150 | if (!td->activity) { | ||
151 | input_event(input, EV_KEY, BTN_TOUCH, 1); | ||
152 | td->activity = true; | ||
153 | } | ||
154 | } | ||
155 | |||
156 | |||
157 | static int egalax_event(struct hid_device *hid, struct hid_field *field, | ||
158 | struct hid_usage *usage, __s32 value) | ||
159 | { | ||
160 | struct egalax_data *td = hid_get_drvdata(hid); | ||
161 | |||
162 | /* Note, eGalax has two product lines: the first is resistive and | ||
163 | * uses a standard parallel multitouch protocol (product ID == | ||
164 | * 48xx). The second is capacitive and uses an unusual "serial" | ||
165 | * protocol with a different message for each multitouch finger | ||
166 | * (product ID == 72xx). We do not yet generate a correct event | ||
167 | * sequence for the capacitive/serial protocol. | ||
168 | */ | ||
169 | if (hid->claimed & HID_CLAIMED_INPUT) { | ||
170 | struct input_dev *input = field->hidinput->input; | ||
171 | |||
172 | switch (usage->hid) { | ||
173 | case HID_DG_INRANGE: | ||
174 | case HID_DG_CONFIDENCE: | ||
175 | /* avoid interference from generic hidinput handling */ | ||
176 | break; | ||
177 | case HID_DG_TIPSWITCH: | ||
178 | td->valid = value; | ||
179 | break; | ||
180 | case HID_DG_TIPPRESSURE: | ||
181 | td->z = value; | ||
182 | break; | ||
183 | case HID_DG_CONTACTID: | ||
184 | td->id = value; | ||
185 | break; | ||
186 | case HID_GD_X: | ||
187 | td->x = value; | ||
188 | break; | ||
189 | case HID_GD_Y: | ||
190 | td->y = value; | ||
191 | /* this is the last field in a finger */ | ||
192 | egalax_filter_event(td, input); | ||
193 | break; | ||
194 | case HID_DG_CONTACTCOUNT: | ||
195 | /* touch emulation: this is the last field in a frame */ | ||
196 | td->first = false; | ||
197 | break; | ||
198 | |||
199 | default: | ||
200 | /* fallback to the generic hidinput handling */ | ||
201 | return 0; | ||
202 | } | ||
203 | } | ||
204 | |||
205 | /* we have handled the hidinput part, now remains hiddev */ | ||
206 | if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event) | ||
207 | hid->hiddev_hid_event(hid, field, usage, value); | ||
208 | |||
209 | return 1; | ||
210 | } | ||
211 | |||
212 | static int egalax_probe(struct hid_device *hdev, const struct hid_device_id *id) | ||
213 | { | ||
214 | int ret; | ||
215 | struct egalax_data *td; | ||
216 | struct hid_report *report; | ||
217 | |||
218 | td = kmalloc(sizeof(struct egalax_data), GFP_KERNEL); | ||
219 | if (!td) { | ||
220 | dev_err(&hdev->dev, "cannot allocate eGalax data\n"); | ||
221 | return -ENOMEM; | ||
222 | } | ||
223 | hid_set_drvdata(hdev, td); | ||
224 | |||
225 | ret = hid_parse(hdev); | ||
226 | if (ret) | ||
227 | goto end; | ||
228 | |||
229 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); | ||
230 | if (ret) | ||
231 | goto end; | ||
232 | |||
233 | report = hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[5]; | ||
234 | if (report) { | ||
235 | report->field[0]->value[0] = 2; | ||
236 | usbhid_submit_report(hdev, report, USB_DIR_OUT); | ||
237 | } | ||
238 | |||
239 | end: | ||
240 | if (ret) | ||
241 | kfree(td); | ||
242 | |||
243 | return ret; | ||
244 | } | ||
245 | |||
246 | static void egalax_remove(struct hid_device *hdev) | ||
247 | { | ||
248 | hid_hw_stop(hdev); | ||
249 | kfree(hid_get_drvdata(hdev)); | ||
250 | hid_set_drvdata(hdev, NULL); | ||
251 | } | ||
252 | |||
253 | static const struct hid_device_id egalax_devices[] = { | ||
254 | { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, | ||
255 | USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH) }, | ||
256 | { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, | ||
257 | USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1) }, | ||
258 | { } | ||
259 | }; | ||
260 | MODULE_DEVICE_TABLE(hid, egalax_devices); | ||
261 | |||
262 | static const struct hid_usage_id egalax_grabbed_usages[] = { | ||
263 | { HID_ANY_ID, HID_ANY_ID, HID_ANY_ID }, | ||
264 | { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1} | ||
265 | }; | ||
266 | |||
267 | static struct hid_driver egalax_driver = { | ||
268 | .name = "egalax-touch", | ||
269 | .id_table = egalax_devices, | ||
270 | .probe = egalax_probe, | ||
271 | .remove = egalax_remove, | ||
272 | .input_mapping = egalax_input_mapping, | ||
273 | .input_mapped = egalax_input_mapped, | ||
274 | .usage_table = egalax_grabbed_usages, | ||
275 | .event = egalax_event, | ||
276 | }; | ||
277 | |||
278 | static int __init egalax_init(void) | ||
279 | { | ||
280 | return hid_register_driver(&egalax_driver); | ||
281 | } | ||
282 | |||
283 | static void __exit egalax_exit(void) | ||
284 | { | ||
285 | hid_unregister_driver(&egalax_driver); | ||
286 | } | ||
287 | |||
288 | module_init(egalax_init); | ||
289 | module_exit(egalax_exit); | ||
290 | |||
diff --git a/drivers/hid/hid-elecom.c b/drivers/hid/hid-elecom.c index 7a40878f46b4..79d0c61e7214 100644 --- a/drivers/hid/hid-elecom.c +++ b/drivers/hid/hid-elecom.c | |||
@@ -20,14 +20,14 @@ | |||
20 | 20 | ||
21 | #include "hid-ids.h" | 21 | #include "hid-ids.h" |
22 | 22 | ||
23 | static void elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc, | 23 | static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc, |
24 | unsigned int rsize) | 24 | unsigned int *rsize) |
25 | { | 25 | { |
26 | if (rsize >= 48 && rdesc[46] == 0x05 && rdesc[47] == 0x0c) { | 26 | if (*rsize >= 48 && rdesc[46] == 0x05 && rdesc[47] == 0x0c) { |
27 | dev_info(&hdev->dev, "Fixing up Elecom BM084 " | 27 | hid_info(hdev, "Fixing up Elecom BM084 report descriptor\n"); |
28 | "report descriptor.\n"); | ||
29 | rdesc[47] = 0x00; | 28 | rdesc[47] = 0x00; |
30 | } | 29 | } |
30 | return rdesc; | ||
31 | } | 31 | } |
32 | 32 | ||
33 | static const struct hid_device_id elecom_devices[] = { | 33 | static const struct hid_device_id elecom_devices[] = { |
diff --git a/drivers/hid/hid-emsff.c b/drivers/hid/hid-emsff.c new file mode 100644 index 000000000000..81877c67caea --- /dev/null +++ b/drivers/hid/hid-emsff.c | |||
@@ -0,0 +1,161 @@ | |||
1 | /* | ||
2 | * Force feedback support for EMS Trio Linker Plus II | ||
3 | * | ||
4 | * Copyright (c) 2010 Ignaz Forster <ignaz.forster@gmx.de> | ||
5 | */ | ||
6 | |||
7 | /* | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | */ | ||
22 | |||
23 | |||
24 | #include <linux/hid.h> | ||
25 | #include <linux/input.h> | ||
26 | #include <linux/usb.h> | ||
27 | |||
28 | #include "hid-ids.h" | ||
29 | #include "usbhid/usbhid.h" | ||
30 | |||
31 | struct emsff_device { | ||
32 | struct hid_report *report; | ||
33 | }; | ||
34 | |||
35 | static int emsff_play(struct input_dev *dev, void *data, | ||
36 | struct ff_effect *effect) | ||
37 | { | ||
38 | struct hid_device *hid = input_get_drvdata(dev); | ||
39 | struct emsff_device *emsff = data; | ||
40 | int weak, strong; | ||
41 | |||
42 | weak = effect->u.rumble.weak_magnitude; | ||
43 | strong = effect->u.rumble.strong_magnitude; | ||
44 | |||
45 | dbg_hid("called with 0x%04x 0x%04x\n", strong, weak); | ||
46 | |||
47 | weak = weak * 0xff / 0xffff; | ||
48 | strong = strong * 0xff / 0xffff; | ||
49 | |||
50 | emsff->report->field[0]->value[1] = weak; | ||
51 | emsff->report->field[0]->value[2] = strong; | ||
52 | |||
53 | dbg_hid("running with 0x%02x 0x%02x\n", strong, weak); | ||
54 | usbhid_submit_report(hid, emsff->report, USB_DIR_OUT); | ||
55 | |||
56 | return 0; | ||
57 | } | ||
58 | |||
59 | static int emsff_init(struct hid_device *hid) | ||
60 | { | ||
61 | struct emsff_device *emsff; | ||
62 | struct hid_report *report; | ||
63 | struct hid_input *hidinput = list_first_entry(&hid->inputs, | ||
64 | struct hid_input, list); | ||
65 | struct list_head *report_list = | ||
66 | &hid->report_enum[HID_OUTPUT_REPORT].report_list; | ||
67 | struct input_dev *dev = hidinput->input; | ||
68 | int error; | ||
69 | |||
70 | if (list_empty(report_list)) { | ||
71 | hid_err(hid, "no output reports found\n"); | ||
72 | return -ENODEV; | ||
73 | } | ||
74 | |||
75 | report = list_first_entry(report_list, struct hid_report, list); | ||
76 | if (report->maxfield < 1) { | ||
77 | hid_err(hid, "no fields in the report\n"); | ||
78 | return -ENODEV; | ||
79 | } | ||
80 | |||
81 | if (report->field[0]->report_count < 7) { | ||
82 | hid_err(hid, "not enough values in the field\n"); | ||
83 | return -ENODEV; | ||
84 | } | ||
85 | |||
86 | emsff = kzalloc(sizeof(struct emsff_device), GFP_KERNEL); | ||
87 | if (!emsff) | ||
88 | return -ENOMEM; | ||
89 | |||
90 | set_bit(FF_RUMBLE, dev->ffbit); | ||
91 | |||
92 | error = input_ff_create_memless(dev, emsff, emsff_play); | ||
93 | if (error) { | ||
94 | kfree(emsff); | ||
95 | return error; | ||
96 | } | ||
97 | |||
98 | emsff->report = report; | ||
99 | emsff->report->field[0]->value[0] = 0x01; | ||
100 | emsff->report->field[0]->value[1] = 0x00; | ||
101 | emsff->report->field[0]->value[2] = 0x00; | ||
102 | emsff->report->field[0]->value[3] = 0x00; | ||
103 | emsff->report->field[0]->value[4] = 0x00; | ||
104 | emsff->report->field[0]->value[5] = 0x00; | ||
105 | emsff->report->field[0]->value[6] = 0x00; | ||
106 | usbhid_submit_report(hid, emsff->report, USB_DIR_OUT); | ||
107 | |||
108 | hid_info(hid, "force feedback for EMS based devices by Ignaz Forster <ignaz.forster@gmx.de>\n"); | ||
109 | |||
110 | return 0; | ||
111 | } | ||
112 | |||
113 | static int ems_probe(struct hid_device *hdev, const struct hid_device_id *id) | ||
114 | { | ||
115 | int ret; | ||
116 | |||
117 | ret = hid_parse(hdev); | ||
118 | if (ret) { | ||
119 | hid_err(hdev, "parse failed\n"); | ||
120 | goto err; | ||
121 | } | ||
122 | |||
123 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); | ||
124 | if (ret) { | ||
125 | hid_err(hdev, "hw start failed\n"); | ||
126 | goto err; | ||
127 | } | ||
128 | |||
129 | emsff_init(hdev); | ||
130 | |||
131 | return 0; | ||
132 | err: | ||
133 | return ret; | ||
134 | } | ||
135 | |||
136 | static const struct hid_device_id ems_devices[] = { | ||
137 | { HID_USB_DEVICE(USB_VENDOR_ID_EMS, 0x118) }, | ||
138 | { } | ||
139 | }; | ||
140 | MODULE_DEVICE_TABLE(hid, ems_devices); | ||
141 | |||
142 | static struct hid_driver ems_driver = { | ||
143 | .name = "hkems", | ||
144 | .id_table = ems_devices, | ||
145 | .probe = ems_probe, | ||
146 | }; | ||
147 | |||
148 | static int ems_init(void) | ||
149 | { | ||
150 | return hid_register_driver(&ems_driver); | ||
151 | } | ||
152 | |||
153 | static void ems_exit(void) | ||
154 | { | ||
155 | hid_unregister_driver(&ems_driver); | ||
156 | } | ||
157 | |||
158 | module_init(ems_init); | ||
159 | module_exit(ems_exit); | ||
160 | MODULE_LICENSE("GPL"); | ||
161 | |||
diff --git a/drivers/hid/hid-gaff.c b/drivers/hid/hid-gaff.c index 88dfcf49a5d7..279ba530003c 100644 --- a/drivers/hid/hid-gaff.c +++ b/drivers/hid/hid-gaff.c | |||
@@ -87,7 +87,7 @@ static int gaff_init(struct hid_device *hid) | |||
87 | int error; | 87 | int error; |
88 | 88 | ||
89 | if (list_empty(report_list)) { | 89 | if (list_empty(report_list)) { |
90 | dev_err(&hid->dev, "no output reports found\n"); | 90 | hid_err(hid, "no output reports found\n"); |
91 | return -ENODEV; | 91 | return -ENODEV; |
92 | } | 92 | } |
93 | 93 | ||
@@ -95,12 +95,12 @@ static int gaff_init(struct hid_device *hid) | |||
95 | 95 | ||
96 | report = list_entry(report_ptr, struct hid_report, list); | 96 | report = list_entry(report_ptr, struct hid_report, list); |
97 | if (report->maxfield < 1) { | 97 | if (report->maxfield < 1) { |
98 | dev_err(&hid->dev, "no fields in the report\n"); | 98 | hid_err(hid, "no fields in the report\n"); |
99 | return -ENODEV; | 99 | return -ENODEV; |
100 | } | 100 | } |
101 | 101 | ||
102 | if (report->field[0]->report_count < 6) { | 102 | if (report->field[0]->report_count < 6) { |
103 | dev_err(&hid->dev, "not enough values in the field\n"); | 103 | hid_err(hid, "not enough values in the field\n"); |
104 | return -ENODEV; | 104 | return -ENODEV; |
105 | } | 105 | } |
106 | 106 | ||
@@ -128,8 +128,7 @@ static int gaff_init(struct hid_device *hid) | |||
128 | 128 | ||
129 | usbhid_submit_report(hid, gaff->report, USB_DIR_OUT); | 129 | usbhid_submit_report(hid, gaff->report, USB_DIR_OUT); |
130 | 130 | ||
131 | dev_info(&hid->dev, "Force Feedback for GreenAsia 0x12" | 131 | hid_info(hid, "Force Feedback for GreenAsia 0x12 devices by Lukasz Lubojanski <lukasz@lubojanski.info>\n"); |
132 | " devices by Lukasz Lubojanski <lukasz@lubojanski.info>\n"); | ||
133 | 132 | ||
134 | return 0; | 133 | return 0; |
135 | } | 134 | } |
@@ -148,13 +147,13 @@ static int ga_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
148 | 147 | ||
149 | ret = hid_parse(hdev); | 148 | ret = hid_parse(hdev); |
150 | if (ret) { | 149 | if (ret) { |
151 | dev_err(&hdev->dev, "parse failed\n"); | 150 | hid_err(hdev, "parse failed\n"); |
152 | goto err; | 151 | goto err; |
153 | } | 152 | } |
154 | 153 | ||
155 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); | 154 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); |
156 | if (ret) { | 155 | if (ret) { |
157 | dev_err(&hdev->dev, "hw start failed\n"); | 156 | hid_err(hdev, "hw start failed\n"); |
158 | goto err; | 157 | goto err; |
159 | } | 158 | } |
160 | 159 | ||
diff --git a/drivers/hid/hid-gyration.c b/drivers/hid/hid-gyration.c index 3975e039c3dd..e88b951cd10d 100644 --- a/drivers/hid/hid-gyration.c +++ b/drivers/hid/hid-gyration.c | |||
@@ -43,6 +43,11 @@ static int gyration_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
43 | case 0x048: gy_map_key_clear(KEY_MEDIA); break; | 43 | case 0x048: gy_map_key_clear(KEY_MEDIA); break; |
44 | case 0x049: gy_map_key_clear(KEY_CAMERA); break; | 44 | case 0x049: gy_map_key_clear(KEY_CAMERA); break; |
45 | case 0x04a: gy_map_key_clear(KEY_VIDEO); break; | 45 | case 0x04a: gy_map_key_clear(KEY_VIDEO); break; |
46 | case 0x05a: gy_map_key_clear(KEY_TEXT); break; | ||
47 | case 0x05b: gy_map_key_clear(KEY_RED); break; | ||
48 | case 0x05c: gy_map_key_clear(KEY_GREEN); break; | ||
49 | case 0x05d: gy_map_key_clear(KEY_YELLOW); break; | ||
50 | case 0x05e: gy_map_key_clear(KEY_BLUE); break; | ||
46 | 51 | ||
47 | default: | 52 | default: |
48 | return 0; | 53 | return 0; |
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index c5ae5f1545bd..a756ee6c7df5 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h | |||
@@ -25,6 +25,7 @@ | |||
25 | #define USB_VENDOR_ID_A4TECH 0x09da | 25 | #define USB_VENDOR_ID_A4TECH 0x09da |
26 | #define USB_DEVICE_ID_A4TECH_WCP32PU 0x0006 | 26 | #define USB_DEVICE_ID_A4TECH_WCP32PU 0x0006 |
27 | #define USB_DEVICE_ID_A4TECH_X5_005D 0x000a | 27 | #define USB_DEVICE_ID_A4TECH_X5_005D 0x000a |
28 | #define USB_DEVICE_ID_A4TECH_RP_649 0x001a | ||
28 | 29 | ||
29 | #define USB_VENDOR_ID_AASHIMA 0x06d6 | 30 | #define USB_VENDOR_ID_AASHIMA 0x06d6 |
30 | #define USB_DEVICE_ID_AASHIMA_GAMEPAD 0x0025 | 31 | #define USB_DEVICE_ID_AASHIMA_GAMEPAD 0x0025 |
@@ -36,6 +37,9 @@ | |||
36 | 37 | ||
37 | #define USB_VENDOR_ID_ACRUX 0x1a34 | 38 | #define USB_VENDOR_ID_ACRUX 0x1a34 |
38 | 39 | ||
40 | #define USB_VENDOR_ID_ACTIONSTAR 0x2101 | ||
41 | #define USB_DEVICE_ID_ACTIONSTAR_1011 0x1011 | ||
42 | |||
39 | #define USB_VENDOR_ID_ADS_TECH 0x06e1 | 43 | #define USB_VENDOR_ID_ADS_TECH 0x06e1 |
40 | #define USB_DEVICE_ID_ADS_TECH_RADIO_SI470X 0xa155 | 44 | #define USB_DEVICE_ID_ADS_TECH_RADIO_SI470X 0xa155 |
41 | 45 | ||
@@ -63,6 +67,7 @@ | |||
63 | #define USB_VENDOR_ID_APPLE 0x05ac | 67 | #define USB_VENDOR_ID_APPLE 0x05ac |
64 | #define USB_DEVICE_ID_APPLE_MIGHTYMOUSE 0x0304 | 68 | #define USB_DEVICE_ID_APPLE_MIGHTYMOUSE 0x0304 |
65 | #define USB_DEVICE_ID_APPLE_MAGICMOUSE 0x030d | 69 | #define USB_DEVICE_ID_APPLE_MAGICMOUSE 0x030d |
70 | #define USB_DEVICE_ID_APPLE_MAGICTRACKPAD 0x030e | ||
66 | #define USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI 0x020e | 71 | #define USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI 0x020e |
67 | #define USB_DEVICE_ID_APPLE_FOUNTAIN_ISO 0x020f | 72 | #define USB_DEVICE_ID_APPLE_FOUNTAIN_ISO 0x020f |
68 | #define USB_DEVICE_ID_APPLE_GEYSER_ANSI 0x0214 | 73 | #define USB_DEVICE_ID_APPLE_GEYSER_ANSI 0x0214 |
@@ -95,6 +100,15 @@ | |||
95 | #define USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI 0x0236 | 100 | #define USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI 0x0236 |
96 | #define USB_DEVICE_ID_APPLE_WELLSPRING3_ISO 0x0237 | 101 | #define USB_DEVICE_ID_APPLE_WELLSPRING3_ISO 0x0237 |
97 | #define USB_DEVICE_ID_APPLE_WELLSPRING3_JIS 0x0238 | 102 | #define USB_DEVICE_ID_APPLE_WELLSPRING3_JIS 0x0238 |
103 | #define USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI 0x023f | ||
104 | #define USB_DEVICE_ID_APPLE_WELLSPRING4_ISO 0x0240 | ||
105 | #define USB_DEVICE_ID_APPLE_WELLSPRING4_JIS 0x0241 | ||
106 | #define USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI 0x0242 | ||
107 | #define USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO 0x0243 | ||
108 | #define USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS 0x0244 | ||
109 | #define USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI 0x0245 | ||
110 | #define USB_DEVICE_ID_APPLE_WELLSPRING5_ISO 0x0246 | ||
111 | #define USB_DEVICE_ID_APPLE_WELLSPRING5_JIS 0x0247 | ||
98 | #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI 0x0239 | 112 | #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI 0x0239 |
99 | #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO 0x023a | 113 | #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO 0x023a |
100 | #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS 0x023b | 114 | #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS 0x023b |
@@ -132,16 +146,20 @@ | |||
132 | #define USB_DEVICE_ID_BTC_EMPREX_REMOTE_2 0x5577 | 146 | #define USB_DEVICE_ID_BTC_EMPREX_REMOTE_2 0x5577 |
133 | 147 | ||
134 | #define USB_VENDOR_ID_CANDO 0x2087 | 148 | #define USB_VENDOR_ID_CANDO 0x2087 |
149 | #define USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH 0x0703 | ||
135 | #define USB_DEVICE_ID_CANDO_MULTI_TOUCH 0x0a01 | 150 | #define USB_DEVICE_ID_CANDO_MULTI_TOUCH 0x0a01 |
151 | #define USB_DEVICE_ID_CANDO_MULTI_TOUCH_10_1 0x0a02 | ||
136 | #define USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6 0x0b03 | 152 | #define USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6 0x0b03 |
137 | #define USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6 0x0f01 | 153 | #define USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6 0x0f01 |
138 | 154 | ||
139 | #define USB_VENDOR_ID_CH 0x068e | 155 | #define USB_VENDOR_ID_CH 0x068e |
156 | #define USB_DEVICE_ID_CH_PRO_THROTTLE 0x00f1 | ||
140 | #define USB_DEVICE_ID_CH_PRO_PEDALS 0x00f2 | 157 | #define USB_DEVICE_ID_CH_PRO_PEDALS 0x00f2 |
141 | #define USB_DEVICE_ID_CH_COMBATSTICK 0x00f4 | 158 | #define USB_DEVICE_ID_CH_COMBATSTICK 0x00f4 |
142 | #define USB_DEVICE_ID_CH_FLIGHT_SIM_ECLIPSE_YOKE 0x0051 | 159 | #define USB_DEVICE_ID_CH_FLIGHT_SIM_ECLIPSE_YOKE 0x0051 |
143 | #define USB_DEVICE_ID_CH_FLIGHT_SIM_YOKE 0x00ff | 160 | #define USB_DEVICE_ID_CH_FLIGHT_SIM_YOKE 0x00ff |
144 | #define USB_DEVICE_ID_CH_3AXIS_5BUTTON_STICK 0x00d3 | 161 | #define USB_DEVICE_ID_CH_3AXIS_5BUTTON_STICK 0x00d3 |
162 | #define USB_DEVICE_ID_CH_AXIS_295 0x001c | ||
145 | 163 | ||
146 | #define USB_VENDOR_ID_CHERRY 0x046a | 164 | #define USB_VENDOR_ID_CHERRY 0x046a |
147 | #define USB_DEVICE_ID_CHERRY_CYMOTION 0x0023 | 165 | #define USB_DEVICE_ID_CHERRY_CYMOTION 0x0023 |
@@ -153,6 +171,10 @@ | |||
153 | #define USB_VENDOR_ID_CHICONY 0x04f2 | 171 | #define USB_VENDOR_ID_CHICONY 0x04f2 |
154 | #define USB_DEVICE_ID_CHICONY_TACTICAL_PAD 0x0418 | 172 | #define USB_DEVICE_ID_CHICONY_TACTICAL_PAD 0x0418 |
155 | #define USB_DEVICE_ID_CHICONY_MULTI_TOUCH 0xb19d | 173 | #define USB_DEVICE_ID_CHICONY_MULTI_TOUCH 0xb19d |
174 | #define USB_DEVICE_ID_CHICONY_WIRELESS 0x0618 | ||
175 | |||
176 | #define USB_VENDOR_ID_CHUNGHWAT 0x2247 | ||
177 | #define USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH 0x0001 | ||
156 | 178 | ||
157 | #define USB_VENDOR_ID_CIDC 0x1677 | 179 | #define USB_VENDOR_ID_CIDC 0x1677 |
158 | 180 | ||
@@ -166,6 +188,9 @@ | |||
166 | #define USB_VENDOR_ID_CREATIVELABS 0x041e | 188 | #define USB_VENDOR_ID_CREATIVELABS 0x041e |
167 | #define USB_DEVICE_ID_PRODIKEYS_PCMIDI 0x2801 | 189 | #define USB_DEVICE_ID_PRODIKEYS_PCMIDI 0x2801 |
168 | 190 | ||
191 | #define USB_VENDOR_ID_CVTOUCH 0x1ff7 | ||
192 | #define USB_DEVICE_ID_CVTOUCH_SCREEN 0x0013 | ||
193 | |||
169 | #define USB_VENDOR_ID_CYGNAL 0x10c4 | 194 | #define USB_VENDOR_ID_CYGNAL 0x10c4 |
170 | #define USB_DEVICE_ID_CYGNAL_RADIO_SI470X 0x818a | 195 | #define USB_DEVICE_ID_CYGNAL_RADIO_SI470X 0x818a |
171 | 196 | ||
@@ -176,6 +201,7 @@ | |||
176 | #define USB_DEVICE_ID_CYPRESS_BARCODE_1 0xde61 | 201 | #define USB_DEVICE_ID_CYPRESS_BARCODE_1 0xde61 |
177 | #define USB_DEVICE_ID_CYPRESS_BARCODE_2 0xde64 | 202 | #define USB_DEVICE_ID_CYPRESS_BARCODE_2 0xde64 |
178 | #define USB_DEVICE_ID_CYPRESS_BARCODE_3 0xbca1 | 203 | #define USB_DEVICE_ID_CYPRESS_BARCODE_3 0xbca1 |
204 | #define USB_DEVICE_ID_CYPRESS_TRUETOUCH 0xc001 | ||
179 | 205 | ||
180 | #define USB_VENDOR_ID_DEALEXTREAME 0x10c5 | 206 | #define USB_VENDOR_ID_DEALEXTREAME 0x10c5 |
181 | #define USB_DEVICE_ID_DEALEXTREAME_RADIO_SI4701 0x819a | 207 | #define USB_DEVICE_ID_DEALEXTREAME_RADIO_SI4701 0x819a |
@@ -193,13 +219,22 @@ | |||
193 | #define USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER 0x0001 | 219 | #define USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER 0x0001 |
194 | #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH 0x480d | 220 | #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH 0x480d |
195 | #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1 0x720c | 221 | #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1 0x720c |
222 | #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH2 0x72a1 | ||
223 | #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH3 0x480e | ||
224 | #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH4 0x726b | ||
196 | 225 | ||
197 | #define USB_VENDOR_ID_ELECOM 0x056e | 226 | #define USB_VENDOR_ID_ELECOM 0x056e |
198 | #define USB_DEVICE_ID_ELECOM_BM084 0x0061 | 227 | #define USB_DEVICE_ID_ELECOM_BM084 0x0061 |
199 | 228 | ||
229 | #define USB_VENDOR_ID_DREAM_CHEEKY 0x1d34 | ||
230 | |||
200 | #define USB_VENDOR_ID_ELO 0x04E7 | 231 | #define USB_VENDOR_ID_ELO 0x04E7 |
232 | #define USB_DEVICE_ID_ELO_TS2515 0x0022 | ||
201 | #define USB_DEVICE_ID_ELO_TS2700 0x0020 | 233 | #define USB_DEVICE_ID_ELO_TS2700 0x0020 |
202 | 234 | ||
235 | #define USB_VENDOR_ID_EMS 0x2006 | ||
236 | #define USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II 0x0118 | ||
237 | |||
203 | #define USB_VENDOR_ID_ESSENTIAL_REALITY 0x0d7f | 238 | #define USB_VENDOR_ID_ESSENTIAL_REALITY 0x0d7f |
204 | #define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100 | 239 | #define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100 |
205 | 240 | ||
@@ -218,6 +253,7 @@ | |||
218 | #define USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR 0x0002 | 253 | #define USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR 0x0002 |
219 | 254 | ||
220 | #define USB_VENDOR_ID_GENERAL_TOUCH 0x0dfc | 255 | #define USB_VENDOR_ID_GENERAL_TOUCH 0x0dfc |
256 | #define USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS 0x0001 | ||
221 | 257 | ||
222 | #define USB_VENDOR_ID_GLAB 0x06c2 | 258 | #define USB_VENDOR_ID_GLAB 0x06c2 |
223 | #define USB_DEVICE_ID_4_PHIDGETSERVO_30 0x0038 | 259 | #define USB_DEVICE_ID_4_PHIDGETSERVO_30 0x0038 |
@@ -229,6 +265,9 @@ | |||
229 | #define USB_DEVICE_ID_0_8_8_IF_KIT 0x0053 | 265 | #define USB_DEVICE_ID_0_8_8_IF_KIT 0x0053 |
230 | #define USB_DEVICE_ID_PHIDGET_MOTORCONTROL 0x0058 | 266 | #define USB_DEVICE_ID_PHIDGET_MOTORCONTROL 0x0058 |
231 | 267 | ||
268 | #define USB_VENDOR_ID_GOODTOUCH 0x1aad | ||
269 | #define USB_DEVICE_ID_GOODTOUCH_000f 0x000f | ||
270 | |||
232 | #define USB_VENDOR_ID_GOTOP 0x08f2 | 271 | #define USB_VENDOR_ID_GOTOP 0x08f2 |
233 | #define USB_DEVICE_ID_SUPER_Q2 0x007f | 272 | #define USB_DEVICE_ID_SUPER_Q2 0x007f |
234 | #define USB_DEVICE_ID_GOGOPEN 0x00ce | 273 | #define USB_DEVICE_ID_GOGOPEN 0x00ce |
@@ -296,14 +335,30 @@ | |||
296 | #define USB_DEVICE_ID_GYRATION_REMOTE_2 0x0003 | 335 | #define USB_DEVICE_ID_GYRATION_REMOTE_2 0x0003 |
297 | #define USB_DEVICE_ID_GYRATION_REMOTE_3 0x0008 | 336 | #define USB_DEVICE_ID_GYRATION_REMOTE_3 0x0008 |
298 | 337 | ||
338 | #define USB_VENDOR_ID_HANWANG 0x0b57 | ||
339 | #define USB_DEVICE_ID_HANWANG_TABLET_FIRST 0x5000 | ||
340 | #define USB_DEVICE_ID_HANWANG_TABLET_LAST 0x8fff | ||
341 | |||
342 | #define USB_VENDOR_ID_HANVON 0x20b3 | ||
343 | #define USB_DEVICE_ID_HANVON_MULTITOUCH 0x0a18 | ||
344 | |||
299 | #define USB_VENDOR_ID_HAPP 0x078b | 345 | #define USB_VENDOR_ID_HAPP 0x078b |
300 | #define USB_DEVICE_ID_UGCI_DRIVING 0x0010 | 346 | #define USB_DEVICE_ID_UGCI_DRIVING 0x0010 |
301 | #define USB_DEVICE_ID_UGCI_FLYING 0x0020 | 347 | #define USB_DEVICE_ID_UGCI_FLYING 0x0020 |
302 | #define USB_DEVICE_ID_UGCI_FIGHTING 0x0030 | 348 | #define USB_DEVICE_ID_UGCI_FIGHTING 0x0030 |
303 | 349 | ||
350 | #define USB_VENDOR_ID_ILITEK 0x222a | ||
351 | #define USB_DEVICE_ID_ILITEK_MULTITOUCH 0x0001 | ||
352 | |||
304 | #define USB_VENDOR_ID_IMATION 0x0718 | 353 | #define USB_VENDOR_ID_IMATION 0x0718 |
305 | #define USB_DEVICE_ID_DISC_STAKKA 0xd000 | 354 | #define USB_DEVICE_ID_DISC_STAKKA 0xd000 |
306 | 355 | ||
356 | #define USB_VENDOR_ID_IRTOUCHSYSTEMS 0x6615 | ||
357 | #define USB_DEVICE_ID_IRTOUCH_INFRARED_USB 0x0070 | ||
358 | |||
359 | #define USB_VENDOR_ID_JESS 0x0c45 | ||
360 | #define USB_DEVICE_ID_JESS_YUREX 0x1010 | ||
361 | |||
307 | #define USB_VENDOR_ID_KBGEAR 0x084e | 362 | #define USB_VENDOR_ID_KBGEAR 0x084e |
308 | #define USB_DEVICE_ID_KBGEAR_JAMSTUDIO 0x1001 | 363 | #define USB_DEVICE_ID_KBGEAR_JAMSTUDIO 0x1001 |
309 | 364 | ||
@@ -313,6 +368,9 @@ | |||
313 | #define USB_VENDOR_ID_KWORLD 0x1b80 | 368 | #define USB_VENDOR_ID_KWORLD 0x1b80 |
314 | #define USB_DEVICE_ID_KWORLD_RADIO_FM700 0xd700 | 369 | #define USB_DEVICE_ID_KWORLD_RADIO_FM700 0xd700 |
315 | 370 | ||
371 | #define USB_VENDOR_ID_KEYTOUCH 0x0926 | ||
372 | #define USB_DEVICE_ID_KEYTOUCH_IEC 0x3333 | ||
373 | |||
316 | #define USB_VENDOR_ID_KYE 0x0458 | 374 | #define USB_VENDOR_ID_KYE 0x0458 |
317 | #define USB_DEVICE_ID_KYE_ERGO_525V 0x0087 | 375 | #define USB_DEVICE_ID_KYE_ERGO_525V 0x0087 |
318 | #define USB_DEVICE_ID_KYE_GPEN_560 0x5003 | 376 | #define USB_DEVICE_ID_KYE_GPEN_560 0x5003 |
@@ -320,26 +378,49 @@ | |||
320 | #define USB_VENDOR_ID_LABTEC 0x1020 | 378 | #define USB_VENDOR_ID_LABTEC 0x1020 |
321 | #define USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD 0x0006 | 379 | #define USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD 0x0006 |
322 | 380 | ||
381 | #define USB_VENDOR_ID_LCPOWER 0x1241 | ||
382 | #define USB_DEVICE_ID_LCPOWER_LC1000 0xf767 | ||
383 | |||
323 | #define USB_VENDOR_ID_LD 0x0f11 | 384 | #define USB_VENDOR_ID_LD 0x0f11 |
324 | #define USB_DEVICE_ID_LD_CASSY 0x1000 | 385 | #define USB_DEVICE_ID_LD_CASSY 0x1000 |
386 | #define USB_DEVICE_ID_LD_CASSY2 0x1001 | ||
325 | #define USB_DEVICE_ID_LD_POCKETCASSY 0x1010 | 387 | #define USB_DEVICE_ID_LD_POCKETCASSY 0x1010 |
388 | #define USB_DEVICE_ID_LD_POCKETCASSY2 0x1011 | ||
326 | #define USB_DEVICE_ID_LD_MOBILECASSY 0x1020 | 389 | #define USB_DEVICE_ID_LD_MOBILECASSY 0x1020 |
390 | #define USB_DEVICE_ID_LD_MOBILECASSY2 0x1021 | ||
391 | #define USB_DEVICE_ID_LD_MICROCASSYVOLTAGE 0x1031 | ||
392 | #define USB_DEVICE_ID_LD_MICROCASSYCURRENT 0x1032 | ||
393 | #define USB_DEVICE_ID_LD_MICROCASSYTIME 0x1033 | ||
394 | #define USB_DEVICE_ID_LD_MICROCASSYTEMPERATURE 0x1035 | ||
395 | #define USB_DEVICE_ID_LD_MICROCASSYPH 0x1038 | ||
327 | #define USB_DEVICE_ID_LD_JWM 0x1080 | 396 | #define USB_DEVICE_ID_LD_JWM 0x1080 |
328 | #define USB_DEVICE_ID_LD_DMMP 0x1081 | 397 | #define USB_DEVICE_ID_LD_DMMP 0x1081 |
329 | #define USB_DEVICE_ID_LD_UMIP 0x1090 | 398 | #define USB_DEVICE_ID_LD_UMIP 0x1090 |
330 | #define USB_DEVICE_ID_LD_XRAY1 0x1100 | 399 | #define USB_DEVICE_ID_LD_UMIC 0x10A0 |
400 | #define USB_DEVICE_ID_LD_UMIB 0x10B0 | ||
401 | #define USB_DEVICE_ID_LD_XRAY 0x1100 | ||
331 | #define USB_DEVICE_ID_LD_XRAY2 0x1101 | 402 | #define USB_DEVICE_ID_LD_XRAY2 0x1101 |
403 | #define USB_DEVICE_ID_LD_XRAYCT 0x1110 | ||
332 | #define USB_DEVICE_ID_LD_VIDEOCOM 0x1200 | 404 | #define USB_DEVICE_ID_LD_VIDEOCOM 0x1200 |
405 | #define USB_DEVICE_ID_LD_MOTOR 0x1210 | ||
333 | #define USB_DEVICE_ID_LD_COM3LAB 0x2000 | 406 | #define USB_DEVICE_ID_LD_COM3LAB 0x2000 |
334 | #define USB_DEVICE_ID_LD_TELEPORT 0x2010 | 407 | #define USB_DEVICE_ID_LD_TELEPORT 0x2010 |
335 | #define USB_DEVICE_ID_LD_NETWORKANALYSER 0x2020 | 408 | #define USB_DEVICE_ID_LD_NETWORKANALYSER 0x2020 |
336 | #define USB_DEVICE_ID_LD_POWERCONTROL 0x2030 | 409 | #define USB_DEVICE_ID_LD_POWERCONTROL 0x2030 |
337 | #define USB_DEVICE_ID_LD_MACHINETEST 0x2040 | 410 | #define USB_DEVICE_ID_LD_MACHINETEST 0x2040 |
411 | #define USB_DEVICE_ID_LD_MOSTANALYSER 0x2050 | ||
412 | #define USB_DEVICE_ID_LD_MOSTANALYSER2 0x2051 | ||
413 | #define USB_DEVICE_ID_LD_ABSESP 0x2060 | ||
414 | #define USB_DEVICE_ID_LD_AUTODATABUS 0x2070 | ||
415 | #define USB_DEVICE_ID_LD_MCT 0x2080 | ||
416 | #define USB_DEVICE_ID_LD_HYBRID 0x2090 | ||
417 | #define USB_DEVICE_ID_LD_HEATCONTROL 0x20A0 | ||
338 | 418 | ||
339 | #define USB_VENDOR_ID_LOGITECH 0x046d | 419 | #define USB_VENDOR_ID_LOGITECH 0x046d |
340 | #define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101 | 420 | #define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101 |
341 | #define USB_DEVICE_ID_LOGITECH_HARMONY_FIRST 0xc110 | 421 | #define USB_DEVICE_ID_LOGITECH_HARMONY_FIRST 0xc110 |
342 | #define USB_DEVICE_ID_LOGITECH_HARMONY_LAST 0xc14f | 422 | #define USB_DEVICE_ID_LOGITECH_HARMONY_LAST 0xc14f |
423 | #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD 0xc20a | ||
343 | #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD 0xc211 | 424 | #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD 0xc211 |
344 | #define USB_DEVICE_ID_LOGITECH_EXTREME_3D 0xc215 | 425 | #define USB_DEVICE_ID_LOGITECH_EXTREME_3D 0xc215 |
345 | #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2 0xc218 | 426 | #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2 0xc218 |
@@ -350,7 +431,10 @@ | |||
350 | #define USB_DEVICE_ID_LOGITECH_WHEEL 0xc294 | 431 | #define USB_DEVICE_ID_LOGITECH_WHEEL 0xc294 |
351 | #define USB_DEVICE_ID_LOGITECH_WINGMAN_FFG 0xc293 | 432 | #define USB_DEVICE_ID_LOGITECH_WINGMAN_FFG 0xc293 |
352 | #define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL 0xc295 | 433 | #define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL 0xc295 |
434 | #define USB_DEVICE_ID_LOGITECH_DFP_WHEEL 0xc298 | ||
353 | #define USB_DEVICE_ID_LOGITECH_G25_WHEEL 0xc299 | 435 | #define USB_DEVICE_ID_LOGITECH_G25_WHEEL 0xc299 |
436 | #define USB_DEVICE_ID_LOGITECH_G27_WHEEL 0xc29b | ||
437 | #define USB_DEVICE_ID_LOGITECH_WII_WHEEL 0xc29c | ||
354 | #define USB_DEVICE_ID_LOGITECH_ELITE_KBD 0xc30a | 438 | #define USB_DEVICE_ID_LOGITECH_ELITE_KBD 0xc30a |
355 | #define USB_DEVICE_ID_S510_RECEIVER 0xc50c | 439 | #define USB_DEVICE_ID_S510_RECEIVER 0xc50c |
356 | #define USB_DEVICE_ID_S510_RECEIVER_2 0xc517 | 440 | #define USB_DEVICE_ID_S510_RECEIVER_2 0xc517 |
@@ -363,6 +447,10 @@ | |||
363 | #define USB_DEVICE_ID_DINOVO_MINI 0xc71f | 447 | #define USB_DEVICE_ID_DINOVO_MINI 0xc71f |
364 | #define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2 0xca03 | 448 | #define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2 0xca03 |
365 | 449 | ||
450 | #define USB_VENDOR_ID_LUMIO 0x202e | ||
451 | #define USB_DEVICE_ID_CRYSTALTOUCH 0x0006 | ||
452 | #define USB_DEVICE_ID_CRYSTALTOUCH_DUAL 0x0007 | ||
453 | |||
366 | #define USB_VENDOR_ID_MCC 0x09db | 454 | #define USB_VENDOR_ID_MCC 0x09db |
367 | #define USB_DEVICE_ID_MCC_PMD1024LS 0x0076 | 455 | #define USB_DEVICE_ID_MCC_PMD1024LS 0x0076 |
368 | #define USB_DEVICE_ID_MCC_PMD1208LS 0x007a | 456 | #define USB_DEVICE_ID_MCC_PMD1208LS 0x007a |
@@ -432,6 +520,7 @@ | |||
432 | #define USB_DEVICE_ID_ONTRAK_ADU100 0x0064 | 520 | #define USB_DEVICE_ID_ONTRAK_ADU100 0x0064 |
433 | 521 | ||
434 | #define USB_VENDOR_ID_ORTEK 0x05a4 | 522 | #define USB_VENDOR_ID_ORTEK 0x05a4 |
523 | #define USB_DEVICE_ID_ORTEK_PKB1700 0x1700 | ||
435 | #define USB_DEVICE_ID_ORTEK_WKB2000 0x2000 | 524 | #define USB_DEVICE_ID_ORTEK_WKB2000 0x2000 |
436 | 525 | ||
437 | #define USB_VENDOR_ID_PANJIT 0x134c | 526 | #define USB_VENDOR_ID_PANJIT 0x134c |
@@ -439,6 +528,9 @@ | |||
439 | #define USB_VENDOR_ID_PANTHERLORD 0x0810 | 528 | #define USB_VENDOR_ID_PANTHERLORD 0x0810 |
440 | #define USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK 0x0001 | 529 | #define USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK 0x0001 |
441 | 530 | ||
531 | #define USB_VENDOR_ID_PENMOUNT 0x14e1 | ||
532 | #define USB_DEVICE_ID_PENMOUNT_PCI 0x3500 | ||
533 | |||
442 | #define USB_VENDOR_ID_PETALYNX 0x18b1 | 534 | #define USB_VENDOR_ID_PETALYNX 0x18b1 |
443 | #define USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE 0x0037 | 535 | #define USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE 0x0037 |
444 | 536 | ||
@@ -462,7 +554,12 @@ | |||
462 | #define USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN 0x3001 | 554 | #define USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN 0x3001 |
463 | 555 | ||
464 | #define USB_VENDOR_ID_ROCCAT 0x1e7d | 556 | #define USB_VENDOR_ID_ROCCAT 0x1e7d |
557 | #define USB_DEVICE_ID_ROCCAT_ARVO 0x30d4 | ||
465 | #define USB_DEVICE_ID_ROCCAT_KONE 0x2ced | 558 | #define USB_DEVICE_ID_ROCCAT_KONE 0x2ced |
559 | #define USB_DEVICE_ID_ROCCAT_KONEPLUS 0x2d51 | ||
560 | #define USB_DEVICE_ID_ROCCAT_KOVAPLUS 0x2d50 | ||
561 | #define USB_DEVICE_ID_ROCCAT_PYRA_WIRED 0x2c24 | ||
562 | #define USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS 0x2cf6 | ||
466 | 563 | ||
467 | #define USB_VENDOR_ID_SAITEK 0x06a3 | 564 | #define USB_VENDOR_ID_SAITEK 0x06a3 |
468 | #define USB_DEVICE_ID_SAITEK_RUMBLEPAD 0xff17 | 565 | #define USB_DEVICE_ID_SAITEK_RUMBLEPAD 0xff17 |
@@ -471,9 +568,13 @@ | |||
471 | #define USB_DEVICE_ID_SAMSUNG_IR_REMOTE 0x0001 | 568 | #define USB_DEVICE_ID_SAMSUNG_IR_REMOTE 0x0001 |
472 | #define USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE 0x0600 | 569 | #define USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE 0x0600 |
473 | 570 | ||
571 | #define USB_VENDOR_ID_SKYCABLE 0x1223 | ||
572 | #define USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER 0x3F07 | ||
573 | |||
474 | #define USB_VENDOR_ID_SONY 0x054c | 574 | #define USB_VENDOR_ID_SONY 0x054c |
475 | #define USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE 0x024b | 575 | #define USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE 0x024b |
476 | #define USB_DEVICE_ID_SONY_PS3_CONTROLLER 0x0268 | 576 | #define USB_DEVICE_ID_SONY_PS3_CONTROLLER 0x0268 |
577 | #define USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER 0x042f | ||
477 | 578 | ||
478 | #define USB_VENDOR_ID_SOUNDGRAPH 0x15c2 | 579 | #define USB_VENDOR_ID_SOUNDGRAPH 0x15c2 |
479 | #define USB_DEVICE_ID_SOUNDGRAPH_IMON_FIRST 0x0034 | 580 | #define USB_DEVICE_ID_SOUNDGRAPH_IMON_FIRST 0x0034 |
@@ -482,12 +583,22 @@ | |||
482 | #define USB_VENDOR_ID_STANTUM 0x1f87 | 583 | #define USB_VENDOR_ID_STANTUM 0x1f87 |
483 | #define USB_DEVICE_ID_MTP 0x0002 | 584 | #define USB_DEVICE_ID_MTP 0x0002 |
484 | 585 | ||
586 | #define USB_VENDOR_ID_STANTUM_STM 0x0483 | ||
587 | #define USB_DEVICE_ID_MTP_STM 0x3261 | ||
588 | |||
589 | #define USB_VENDOR_ID_STANTUM_SITRONIX 0x1403 | ||
590 | #define USB_DEVICE_ID_MTP_SITRONIX 0x5001 | ||
591 | |||
485 | #define USB_VENDOR_ID_SUN 0x0430 | 592 | #define USB_VENDOR_ID_SUN 0x0430 |
486 | #define USB_DEVICE_ID_RARITAN_KVM_DONGLE 0xcdab | 593 | #define USB_DEVICE_ID_RARITAN_KVM_DONGLE 0xcdab |
487 | 594 | ||
488 | #define USB_VENDOR_ID_SUNPLUS 0x04fc | 595 | #define USB_VENDOR_ID_SUNPLUS 0x04fc |
489 | #define USB_DEVICE_ID_SUNPLUS_WDESKTOP 0x05d8 | 596 | #define USB_DEVICE_ID_SUNPLUS_WDESKTOP 0x05d8 |
490 | 597 | ||
598 | #define USB_VENDOR_ID_SYMBOL 0x05e0 | ||
599 | #define USB_DEVICE_ID_SYMBOL_SCANNER_1 0x0800 | ||
600 | #define USB_DEVICE_ID_SYMBOL_SCANNER_2 0x1300 | ||
601 | |||
491 | #define USB_VENDOR_ID_THRUSTMASTER 0x044f | 602 | #define USB_VENDOR_ID_THRUSTMASTER 0x044f |
492 | 603 | ||
493 | #define USB_VENDOR_ID_TOPSEED 0x0766 | 604 | #define USB_VENDOR_ID_TOPSEED 0x0766 |
@@ -499,6 +610,9 @@ | |||
499 | #define USB_VENDOR_ID_TOPMAX 0x0663 | 610 | #define USB_VENDOR_ID_TOPMAX 0x0663 |
500 | #define USB_DEVICE_ID_TOPMAX_COBRAPAD 0x0103 | 611 | #define USB_DEVICE_ID_TOPMAX_COBRAPAD 0x0103 |
501 | 612 | ||
613 | #define USB_VENDOR_ID_TOUCH_INTL 0x1e5e | ||
614 | #define USB_DEVICE_ID_TOUCH_INTL_MULTI_TOUCH 0x0313 | ||
615 | |||
502 | #define USB_VENDOR_ID_TOUCHPACK 0x1bfd | 616 | #define USB_VENDOR_ID_TOUCHPACK 0x1bfd |
503 | #define USB_DEVICE_ID_TOUCHPACK_RTS 0x1688 | 617 | #define USB_DEVICE_ID_TOUCHPACK_RTS 0x1688 |
504 | 618 | ||
@@ -511,8 +625,15 @@ | |||
511 | 625 | ||
512 | #define USB_VENDOR_ID_UCLOGIC 0x5543 | 626 | #define USB_VENDOR_ID_UCLOGIC 0x5543 |
513 | #define USB_DEVICE_ID_UCLOGIC_TABLET_PF1209 0x0042 | 627 | #define USB_DEVICE_ID_UCLOGIC_TABLET_PF1209 0x0042 |
514 | #define USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U 0x0003 | ||
515 | #define USB_DEVICE_ID_UCLOGIC_TABLET_KNA5 0x6001 | 628 | #define USB_DEVICE_ID_UCLOGIC_TABLET_KNA5 0x6001 |
629 | #define USB_DEVICE_ID_UCLOGIC_TABLET_TWA60 0x0064 | ||
630 | #define USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U 0x0003 | ||
631 | #define USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U 0x0004 | ||
632 | #define USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U 0x0005 | ||
633 | |||
634 | #define USB_VENDOR_ID_UNITEC 0x227d | ||
635 | #define USB_DEVICE_ID_UNITEC_USB_TOUCH_0709 0x0709 | ||
636 | #define USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19 0x0a19 | ||
516 | 637 | ||
517 | #define USB_VENDOR_ID_VERNIER 0x08f7 | 638 | #define USB_VENDOR_ID_VERNIER 0x08f7 |
518 | #define USB_DEVICE_ID_VERNIER_LABPRO 0x0001 | 639 | #define USB_DEVICE_ID_VERNIER_LABPRO 0x0001 |
@@ -524,6 +645,12 @@ | |||
524 | #define USB_VENDOR_ID_WACOM 0x056a | 645 | #define USB_VENDOR_ID_WACOM 0x056a |
525 | #define USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH 0x81 | 646 | #define USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH 0x81 |
526 | 647 | ||
648 | #define USB_VENDOR_ID_WALTOP 0x172f | ||
649 | #define USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH 0x0032 | ||
650 | #define USB_DEVICE_ID_WALTOP_SLIM_TABLET_12_1_INCH 0x0034 | ||
651 | #define USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH 0x0501 | ||
652 | #define USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH 0x0500 | ||
653 | |||
527 | #define USB_VENDOR_ID_WISEGROUP 0x0925 | 654 | #define USB_VENDOR_ID_WISEGROUP 0x0925 |
528 | #define USB_DEVICE_ID_SMARTJOY_PLUS 0x0005 | 655 | #define USB_DEVICE_ID_SMARTJOY_PLUS 0x0005 |
529 | #define USB_DEVICE_ID_1_PHIDGETSERVO_20 0x8101 | 656 | #define USB_DEVICE_ID_1_PHIDGETSERVO_20 0x8101 |
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 6c03dcc5760a..6559e2e3364e 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c | |||
@@ -44,11 +44,11 @@ static const unsigned char hid_keyboard[256] = { | |||
44 | 72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190, | 44 | 72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190, |
45 | 191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113, | 45 | 191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113, |
46 | 115,114,unk,unk,unk,121,unk, 89, 93,124, 92, 94, 95,unk,unk,unk, | 46 | 115,114,unk,unk,unk,121,unk, 89, 93,124, 92, 94, 95,unk,unk,unk, |
47 | 122,123, 90, 91, 85,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, | 47 | 122,123, 90, 91, 85,unk,unk,unk,unk,unk,unk,unk,111,unk,unk,unk, |
48 | unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, | 48 | unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, |
49 | unk,unk,unk,unk,unk,unk,179,180,unk,unk,unk,unk,unk,unk,unk,unk, | 49 | unk,unk,unk,unk,unk,unk,179,180,unk,unk,unk,unk,unk,unk,unk,unk, |
50 | unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, | 50 | unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, |
51 | unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk, | 51 | unk,unk,unk,unk,unk,unk,unk,unk,111,unk,unk,unk,unk,unk,unk,unk, |
52 | 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113, | 52 | 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113, |
53 | 150,158,159,128,136,177,178,176,142,152,173,140,unk,unk,unk,unk | 53 | 150,158,159,128,136,177,178,176,142,152,173,140,unk,unk,unk,unk |
54 | }; | 54 | }; |
@@ -68,39 +68,52 @@ static const struct { | |||
68 | #define map_key_clear(c) hid_map_usage_clear(hidinput, usage, &bit, \ | 68 | #define map_key_clear(c) hid_map_usage_clear(hidinput, usage, &bit, \ |
69 | &max, EV_KEY, (c)) | 69 | &max, EV_KEY, (c)) |
70 | 70 | ||
71 | static inline int match_scancode(unsigned int code, unsigned int scancode) | 71 | static bool match_scancode(struct hid_usage *usage, |
72 | unsigned int cur_idx, unsigned int scancode) | ||
72 | { | 73 | { |
73 | if (scancode == 0) | 74 | return (usage->hid & (HID_USAGE_PAGE | HID_USAGE)) == scancode; |
74 | return 1; | ||
75 | |||
76 | return (code & (HID_USAGE_PAGE | HID_USAGE)) == scancode; | ||
77 | } | 75 | } |
78 | 76 | ||
79 | static inline int match_keycode(unsigned int code, unsigned int keycode) | 77 | static bool match_keycode(struct hid_usage *usage, |
78 | unsigned int cur_idx, unsigned int keycode) | ||
80 | { | 79 | { |
81 | if (keycode == 0) | 80 | /* |
82 | return 1; | 81 | * We should exclude unmapped usages when doing lookup by keycode. |
82 | */ | ||
83 | return (usage->type == EV_KEY && usage->code == keycode); | ||
84 | } | ||
83 | 85 | ||
84 | return code == keycode; | 86 | static bool match_index(struct hid_usage *usage, |
87 | unsigned int cur_idx, unsigned int idx) | ||
88 | { | ||
89 | return cur_idx == idx; | ||
85 | } | 90 | } |
86 | 91 | ||
92 | typedef bool (*hid_usage_cmp_t)(struct hid_usage *usage, | ||
93 | unsigned int cur_idx, unsigned int val); | ||
94 | |||
87 | static struct hid_usage *hidinput_find_key(struct hid_device *hid, | 95 | static struct hid_usage *hidinput_find_key(struct hid_device *hid, |
88 | unsigned int scancode, | 96 | hid_usage_cmp_t match, |
89 | unsigned int keycode) | 97 | unsigned int value, |
98 | unsigned int *usage_idx) | ||
90 | { | 99 | { |
91 | int i, j, k; | 100 | unsigned int i, j, k, cur_idx = 0; |
92 | struct hid_report *report; | 101 | struct hid_report *report; |
93 | struct hid_usage *usage; | 102 | struct hid_usage *usage; |
94 | 103 | ||
95 | for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) { | 104 | for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) { |
96 | list_for_each_entry(report, &hid->report_enum[k].report_list, list) { | 105 | list_for_each_entry(report, &hid->report_enum[k].report_list, list) { |
97 | for (i = 0; i < report->maxfield; i++) { | 106 | for (i = 0; i < report->maxfield; i++) { |
98 | for ( j = 0; j < report->field[i]->maxusage; j++) { | 107 | for (j = 0; j < report->field[i]->maxusage; j++) { |
99 | usage = report->field[i]->usage + j; | 108 | usage = report->field[i]->usage + j; |
100 | if (usage->type == EV_KEY && | 109 | if (usage->type == EV_KEY || usage->type == 0) { |
101 | match_scancode(usage->hid, scancode) && | 110 | if (match(usage, cur_idx, value)) { |
102 | match_keycode(usage->code, keycode)) | 111 | if (usage_idx) |
103 | return usage; | 112 | *usage_idx = cur_idx; |
113 | return usage; | ||
114 | } | ||
115 | cur_idx++; | ||
116 | } | ||
104 | } | 117 | } |
105 | } | 118 | } |
106 | } | 119 | } |
@@ -108,39 +121,68 @@ static struct hid_usage *hidinput_find_key(struct hid_device *hid, | |||
108 | return NULL; | 121 | return NULL; |
109 | } | 122 | } |
110 | 123 | ||
124 | static struct hid_usage *hidinput_locate_usage(struct hid_device *hid, | ||
125 | const struct input_keymap_entry *ke, | ||
126 | unsigned int *index) | ||
127 | { | ||
128 | struct hid_usage *usage; | ||
129 | unsigned int scancode; | ||
130 | |||
131 | if (ke->flags & INPUT_KEYMAP_BY_INDEX) | ||
132 | usage = hidinput_find_key(hid, match_index, ke->index, index); | ||
133 | else if (input_scancode_to_scalar(ke, &scancode) == 0) | ||
134 | usage = hidinput_find_key(hid, match_scancode, scancode, index); | ||
135 | else | ||
136 | usage = NULL; | ||
137 | |||
138 | return usage; | ||
139 | } | ||
140 | |||
111 | static int hidinput_getkeycode(struct input_dev *dev, | 141 | static int hidinput_getkeycode(struct input_dev *dev, |
112 | unsigned int scancode, unsigned int *keycode) | 142 | struct input_keymap_entry *ke) |
113 | { | 143 | { |
114 | struct hid_device *hid = input_get_drvdata(dev); | 144 | struct hid_device *hid = input_get_drvdata(dev); |
115 | struct hid_usage *usage; | 145 | struct hid_usage *usage; |
146 | unsigned int scancode, index; | ||
116 | 147 | ||
117 | usage = hidinput_find_key(hid, scancode, 0); | 148 | usage = hidinput_locate_usage(hid, ke, &index); |
118 | if (usage) { | 149 | if (usage) { |
119 | *keycode = usage->code; | 150 | ke->keycode = usage->type == EV_KEY ? |
151 | usage->code : KEY_RESERVED; | ||
152 | ke->index = index; | ||
153 | scancode = usage->hid & (HID_USAGE_PAGE | HID_USAGE); | ||
154 | ke->len = sizeof(scancode); | ||
155 | memcpy(ke->scancode, &scancode, sizeof(scancode)); | ||
120 | return 0; | 156 | return 0; |
121 | } | 157 | } |
158 | |||
122 | return -EINVAL; | 159 | return -EINVAL; |
123 | } | 160 | } |
124 | 161 | ||
125 | static int hidinput_setkeycode(struct input_dev *dev, | 162 | static int hidinput_setkeycode(struct input_dev *dev, |
126 | unsigned int scancode, unsigned int keycode) | 163 | const struct input_keymap_entry *ke, |
164 | unsigned int *old_keycode) | ||
127 | { | 165 | { |
128 | struct hid_device *hid = input_get_drvdata(dev); | 166 | struct hid_device *hid = input_get_drvdata(dev); |
129 | struct hid_usage *usage; | 167 | struct hid_usage *usage; |
130 | int old_keycode; | ||
131 | 168 | ||
132 | usage = hidinput_find_key(hid, scancode, 0); | 169 | usage = hidinput_locate_usage(hid, ke, NULL); |
133 | if (usage) { | 170 | if (usage) { |
134 | old_keycode = usage->code; | 171 | *old_keycode = usage->type == EV_KEY ? |
135 | usage->code = keycode; | 172 | usage->code : KEY_RESERVED; |
173 | usage->code = ke->keycode; | ||
136 | 174 | ||
137 | clear_bit(old_keycode, dev->keybit); | 175 | clear_bit(*old_keycode, dev->keybit); |
138 | set_bit(usage->code, dev->keybit); | 176 | set_bit(usage->code, dev->keybit); |
139 | dbg_hid(KERN_DEBUG "Assigned keycode %d to HID usage code %x\n", keycode, scancode); | 177 | dbg_hid("Assigned keycode %d to HID usage code %x\n", |
140 | /* Set the keybit for the old keycode if the old keycode is used | 178 | usage->code, usage->hid); |
141 | * by another key */ | 179 | |
142 | if (hidinput_find_key (hid, 0, old_keycode)) | 180 | /* |
143 | set_bit(old_keycode, dev->keybit); | 181 | * Set the keybit for the old keycode if the old keycode is used |
182 | * by another key | ||
183 | */ | ||
184 | if (hidinput_find_key(hid, match_keycode, *old_keycode, NULL)) | ||
185 | set_bit(*old_keycode, dev->keybit); | ||
144 | 186 | ||
145 | return 0; | 187 | return 0; |
146 | } | 188 | } |
@@ -149,6 +191,86 @@ static int hidinput_setkeycode(struct input_dev *dev, | |||
149 | } | 191 | } |
150 | 192 | ||
151 | 193 | ||
194 | /** | ||
195 | * hidinput_calc_abs_res - calculate an absolute axis resolution | ||
196 | * @field: the HID report field to calculate resolution for | ||
197 | * @code: axis code | ||
198 | * | ||
199 | * The formula is: | ||
200 | * (logical_maximum - logical_minimum) | ||
201 | * resolution = ---------------------------------------------------------- | ||
202 | * (physical_maximum - physical_minimum) * 10 ^ unit_exponent | ||
203 | * | ||
204 | * as seen in the HID specification v1.11 6.2.2.7 Global Items. | ||
205 | * | ||
206 | * Only exponent 1 length units are processed. Centimeters and inches are | ||
207 | * converted to millimeters. Degrees are converted to radians. | ||
208 | */ | ||
209 | static __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code) | ||
210 | { | ||
211 | __s32 unit_exponent = field->unit_exponent; | ||
212 | __s32 logical_extents = field->logical_maximum - | ||
213 | field->logical_minimum; | ||
214 | __s32 physical_extents = field->physical_maximum - | ||
215 | field->physical_minimum; | ||
216 | __s32 prev; | ||
217 | |||
218 | /* Check if the extents are sane */ | ||
219 | if (logical_extents <= 0 || physical_extents <= 0) | ||
220 | return 0; | ||
221 | |||
222 | /* | ||
223 | * Verify and convert units. | ||
224 | * See HID specification v1.11 6.2.2.7 Global Items for unit decoding | ||
225 | */ | ||
226 | if (code == ABS_X || code == ABS_Y || code == ABS_Z) { | ||
227 | if (field->unit == 0x11) { /* If centimeters */ | ||
228 | /* Convert to millimeters */ | ||
229 | unit_exponent += 1; | ||
230 | } else if (field->unit == 0x13) { /* If inches */ | ||
231 | /* Convert to millimeters */ | ||
232 | prev = physical_extents; | ||
233 | physical_extents *= 254; | ||
234 | if (physical_extents < prev) | ||
235 | return 0; | ||
236 | unit_exponent -= 1; | ||
237 | } else { | ||
238 | return 0; | ||
239 | } | ||
240 | } else if (code == ABS_RX || code == ABS_RY || code == ABS_RZ) { | ||
241 | if (field->unit == 0x14) { /* If degrees */ | ||
242 | /* Convert to radians */ | ||
243 | prev = logical_extents; | ||
244 | logical_extents *= 573; | ||
245 | if (logical_extents < prev) | ||
246 | return 0; | ||
247 | unit_exponent += 1; | ||
248 | } else if (field->unit != 0x12) { /* If not radians */ | ||
249 | return 0; | ||
250 | } | ||
251 | } else { | ||
252 | return 0; | ||
253 | } | ||
254 | |||
255 | /* Apply negative unit exponent */ | ||
256 | for (; unit_exponent < 0; unit_exponent++) { | ||
257 | prev = logical_extents; | ||
258 | logical_extents *= 10; | ||
259 | if (logical_extents < prev) | ||
260 | return 0; | ||
261 | } | ||
262 | /* Apply positive unit exponent */ | ||
263 | for (; unit_exponent > 0; unit_exponent--) { | ||
264 | prev = physical_extents; | ||
265 | physical_extents *= 10; | ||
266 | if (physical_extents < prev) | ||
267 | return 0; | ||
268 | } | ||
269 | |||
270 | /* Calculate resolution */ | ||
271 | return logical_extents / physical_extents; | ||
272 | } | ||
273 | |||
152 | static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field, | 274 | static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field, |
153 | struct hid_usage *usage) | 275 | struct hid_usage *usage) |
154 | { | 276 | { |
@@ -197,21 +319,21 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
197 | 319 | ||
198 | switch (field->application) { | 320 | switch (field->application) { |
199 | case HID_GD_MOUSE: | 321 | case HID_GD_MOUSE: |
200 | case HID_GD_POINTER: code += 0x110; break; | 322 | case HID_GD_POINTER: code += BTN_MOUSE; break; |
201 | case HID_GD_JOYSTICK: | 323 | case HID_GD_JOYSTICK: |
202 | if (code <= 0xf) | 324 | if (code <= 0xf) |
203 | code += BTN_JOYSTICK; | 325 | code += BTN_JOYSTICK; |
204 | else | 326 | else |
205 | code += BTN_TRIGGER_HAPPY; | 327 | code += BTN_TRIGGER_HAPPY; |
206 | break; | 328 | break; |
207 | case HID_GD_GAMEPAD: code += 0x130; break; | 329 | case HID_GD_GAMEPAD: code += BTN_GAMEPAD; break; |
208 | default: | 330 | default: |
209 | switch (field->physical) { | 331 | switch (field->physical) { |
210 | case HID_GD_MOUSE: | 332 | case HID_GD_MOUSE: |
211 | case HID_GD_POINTER: code += 0x110; break; | 333 | case HID_GD_POINTER: code += BTN_MOUSE; break; |
212 | case HID_GD_JOYSTICK: code += 0x120; break; | 334 | case HID_GD_JOYSTICK: code += BTN_JOYSTICK; break; |
213 | case HID_GD_GAMEPAD: code += 0x130; break; | 335 | case HID_GD_GAMEPAD: code += BTN_GAMEPAD; break; |
214 | default: code += 0x100; | 336 | default: code += BTN_MISC; |
215 | } | 337 | } |
216 | } | 338 | } |
217 | 339 | ||
@@ -235,6 +357,18 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
235 | case 0x1: map_key_clear(KEY_POWER); break; | 357 | case 0x1: map_key_clear(KEY_POWER); break; |
236 | case 0x2: map_key_clear(KEY_SLEEP); break; | 358 | case 0x2: map_key_clear(KEY_SLEEP); break; |
237 | case 0x3: map_key_clear(KEY_WAKEUP); break; | 359 | case 0x3: map_key_clear(KEY_WAKEUP); break; |
360 | case 0x4: map_key_clear(KEY_CONTEXT_MENU); break; | ||
361 | case 0x5: map_key_clear(KEY_MENU); break; | ||
362 | case 0x6: map_key_clear(KEY_PROG1); break; | ||
363 | case 0x7: map_key_clear(KEY_HELP); break; | ||
364 | case 0x8: map_key_clear(KEY_EXIT); break; | ||
365 | case 0x9: map_key_clear(KEY_SELECT); break; | ||
366 | case 0xa: map_key_clear(KEY_RIGHT); break; | ||
367 | case 0xb: map_key_clear(KEY_LEFT); break; | ||
368 | case 0xc: map_key_clear(KEY_UP); break; | ||
369 | case 0xd: map_key_clear(KEY_DOWN); break; | ||
370 | case 0xe: map_key_clear(KEY_POWER2); break; | ||
371 | case 0xf: map_key_clear(KEY_RESTART); break; | ||
238 | default: goto unknown; | 372 | default: goto unknown; |
239 | } | 373 | } |
240 | break; | 374 | break; |
@@ -336,20 +470,47 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
336 | map_key_clear(BTN_STYLUS); | 470 | map_key_clear(BTN_STYLUS); |
337 | break; | 471 | break; |
338 | 472 | ||
473 | case 0x46: /* TabletPick */ | ||
474 | map_key_clear(BTN_STYLUS2); | ||
475 | break; | ||
476 | |||
339 | default: goto unknown; | 477 | default: goto unknown; |
340 | } | 478 | } |
341 | break; | 479 | break; |
342 | 480 | ||
343 | case HID_UP_CONSUMER: /* USB HUT v1.1, pages 56-62 */ | 481 | case HID_UP_CONSUMER: /* USB HUT v1.12, pages 75-84 */ |
344 | switch (usage->hid & HID_USAGE) { | 482 | switch (usage->hid & HID_USAGE) { |
345 | case 0x000: goto ignore; | 483 | case 0x000: goto ignore; |
484 | case 0x030: map_key_clear(KEY_POWER); break; | ||
485 | case 0x031: map_key_clear(KEY_RESTART); break; | ||
486 | case 0x032: map_key_clear(KEY_SLEEP); break; | ||
346 | case 0x034: map_key_clear(KEY_SLEEP); break; | 487 | case 0x034: map_key_clear(KEY_SLEEP); break; |
488 | case 0x035: map_key_clear(KEY_KBDILLUMTOGGLE); break; | ||
347 | case 0x036: map_key_clear(BTN_MISC); break; | 489 | case 0x036: map_key_clear(BTN_MISC); break; |
348 | 490 | ||
349 | case 0x040: map_key_clear(KEY_MENU); break; | 491 | case 0x040: map_key_clear(KEY_MENU); break; /* Menu */ |
350 | case 0x045: map_key_clear(KEY_RADIO); break; | 492 | case 0x041: map_key_clear(KEY_SELECT); break; /* Menu Pick */ |
351 | 493 | case 0x042: map_key_clear(KEY_UP); break; /* Menu Up */ | |
494 | case 0x043: map_key_clear(KEY_DOWN); break; /* Menu Down */ | ||
495 | case 0x044: map_key_clear(KEY_LEFT); break; /* Menu Left */ | ||
496 | case 0x045: map_key_clear(KEY_RIGHT); break; /* Menu Right */ | ||
497 | case 0x046: map_key_clear(KEY_ESC); break; /* Menu Escape */ | ||
498 | case 0x047: map_key_clear(KEY_KPPLUS); break; /* Menu Value Increase */ | ||
499 | case 0x048: map_key_clear(KEY_KPMINUS); break; /* Menu Value Decrease */ | ||
500 | |||
501 | case 0x060: map_key_clear(KEY_INFO); break; /* Data On Screen */ | ||
502 | case 0x061: map_key_clear(KEY_SUBTITLE); break; /* Closed Caption */ | ||
503 | case 0x063: map_key_clear(KEY_VCR); break; /* VCR/TV */ | ||
504 | case 0x065: map_key_clear(KEY_CAMERA); break; /* Snapshot */ | ||
505 | case 0x069: map_key_clear(KEY_RED); break; | ||
506 | case 0x06a: map_key_clear(KEY_GREEN); break; | ||
507 | case 0x06b: map_key_clear(KEY_BLUE); break; | ||
508 | case 0x06c: map_key_clear(KEY_YELLOW); break; | ||
509 | case 0x06d: map_key_clear(KEY_ZOOM); break; | ||
510 | |||
511 | case 0x082: map_key_clear(KEY_VIDEO_NEXT); break; | ||
352 | case 0x083: map_key_clear(KEY_LAST); break; | 512 | case 0x083: map_key_clear(KEY_LAST); break; |
513 | case 0x084: map_key_clear(KEY_ENTER); break; | ||
353 | case 0x088: map_key_clear(KEY_PC); break; | 514 | case 0x088: map_key_clear(KEY_PC); break; |
354 | case 0x089: map_key_clear(KEY_TV); break; | 515 | case 0x089: map_key_clear(KEY_TV); break; |
355 | case 0x08a: map_key_clear(KEY_WWW); break; | 516 | case 0x08a: map_key_clear(KEY_WWW); break; |
@@ -383,6 +544,8 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
383 | case 0x0b7: map_key_clear(KEY_STOPCD); break; | 544 | case 0x0b7: map_key_clear(KEY_STOPCD); break; |
384 | case 0x0b8: map_key_clear(KEY_EJECTCD); break; | 545 | case 0x0b8: map_key_clear(KEY_EJECTCD); break; |
385 | case 0x0bc: map_key_clear(KEY_MEDIA_REPEAT); break; | 546 | case 0x0bc: map_key_clear(KEY_MEDIA_REPEAT); break; |
547 | case 0x0b9: map_key_clear(KEY_SHUFFLE); break; | ||
548 | case 0x0bf: map_key_clear(KEY_SLOW); break; | ||
386 | 549 | ||
387 | case 0x0cd: map_key_clear(KEY_PLAYPAUSE); break; | 550 | case 0x0cd: map_key_clear(KEY_PLAYPAUSE); break; |
388 | case 0x0e0: map_abs_clear(ABS_VOLUME); break; | 551 | case 0x0e0: map_abs_clear(ABS_VOLUME); break; |
@@ -390,6 +553,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
390 | case 0x0e5: map_key_clear(KEY_BASSBOOST); break; | 553 | case 0x0e5: map_key_clear(KEY_BASSBOOST); break; |
391 | case 0x0e9: map_key_clear(KEY_VOLUMEUP); break; | 554 | case 0x0e9: map_key_clear(KEY_VOLUMEUP); break; |
392 | case 0x0ea: map_key_clear(KEY_VOLUMEDOWN); break; | 555 | case 0x0ea: map_key_clear(KEY_VOLUMEDOWN); break; |
556 | case 0x0f5: map_key_clear(KEY_SLOW); break; | ||
393 | 557 | ||
394 | case 0x182: map_key_clear(KEY_BOOKMARKS); break; | 558 | case 0x182: map_key_clear(KEY_BOOKMARKS); break; |
395 | case 0x183: map_key_clear(KEY_CONFIG); break; | 559 | case 0x183: map_key_clear(KEY_CONFIG); break; |
@@ -406,6 +570,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
406 | case 0x18e: map_key_clear(KEY_CALENDAR); break; | 570 | case 0x18e: map_key_clear(KEY_CALENDAR); break; |
407 | case 0x191: map_key_clear(KEY_FINANCE); break; | 571 | case 0x191: map_key_clear(KEY_FINANCE); break; |
408 | case 0x192: map_key_clear(KEY_CALC); break; | 572 | case 0x192: map_key_clear(KEY_CALC); break; |
573 | case 0x193: map_key_clear(KEY_PLAYER); break; | ||
409 | case 0x194: map_key_clear(KEY_FILE); break; | 574 | case 0x194: map_key_clear(KEY_FILE); break; |
410 | case 0x196: map_key_clear(KEY_WWW); break; | 575 | case 0x196: map_key_clear(KEY_WWW); break; |
411 | case 0x199: map_key_clear(KEY_CHAT); break; | 576 | case 0x199: map_key_clear(KEY_CHAT); break; |
@@ -414,8 +579,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
414 | case 0x1a6: map_key_clear(KEY_HELP); break; | 579 | case 0x1a6: map_key_clear(KEY_HELP); break; |
415 | case 0x1a7: map_key_clear(KEY_DOCUMENTS); break; | 580 | case 0x1a7: map_key_clear(KEY_DOCUMENTS); break; |
416 | case 0x1ab: map_key_clear(KEY_SPELLCHECK); break; | 581 | case 0x1ab: map_key_clear(KEY_SPELLCHECK); break; |
417 | case 0x1b6: map_key_clear(KEY_MEDIA); break; | 582 | case 0x1ae: map_key_clear(KEY_KEYBOARD); break; |
418 | case 0x1b7: map_key_clear(KEY_SOUND); break; | 583 | case 0x1b6: map_key_clear(KEY_IMAGES); break; |
584 | case 0x1b7: map_key_clear(KEY_AUDIO); break; | ||
585 | case 0x1b8: map_key_clear(KEY_VIDEO); break; | ||
419 | case 0x1bc: map_key_clear(KEY_MESSENGER); break; | 586 | case 0x1bc: map_key_clear(KEY_MESSENGER); break; |
420 | case 0x1bd: map_key_clear(KEY_INFO); break; | 587 | case 0x1bd: map_key_clear(KEY_INFO); break; |
421 | case 0x201: map_key_clear(KEY_NEW); break; | 588 | case 0x201: map_key_clear(KEY_NEW); break; |
@@ -444,7 +611,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
444 | case 0x233: map_key_clear(KEY_SCROLLUP); break; | 611 | case 0x233: map_key_clear(KEY_SCROLLUP); break; |
445 | case 0x234: map_key_clear(KEY_SCROLLDOWN); break; | 612 | case 0x234: map_key_clear(KEY_SCROLLDOWN); break; |
446 | case 0x238: map_rel(REL_HWHEEL); break; | 613 | case 0x238: map_rel(REL_HWHEEL); break; |
614 | case 0x23d: map_key_clear(KEY_EDIT); break; | ||
447 | case 0x25f: map_key_clear(KEY_CANCEL); break; | 615 | case 0x25f: map_key_clear(KEY_CANCEL); break; |
616 | case 0x269: map_key_clear(KEY_INSERT); break; | ||
617 | case 0x26a: map_key_clear(KEY_DELETE); break; | ||
448 | case 0x279: map_key_clear(KEY_REDO); break; | 618 | case 0x279: map_key_clear(KEY_REDO); break; |
449 | 619 | ||
450 | case 0x289: map_key_clear(KEY_REPLY); break; | 620 | case 0x289: map_key_clear(KEY_REPLY); break; |
@@ -537,6 +707,9 @@ mapped: | |||
537 | input_set_abs_params(input, usage->code, a, b, (b - a) >> 8, (b - a) >> 4); | 707 | input_set_abs_params(input, usage->code, a, b, (b - a) >> 8, (b - a) >> 4); |
538 | else input_set_abs_params(input, usage->code, a, b, 0, 0); | 708 | else input_set_abs_params(input, usage->code, a, b, 0, 0); |
539 | 709 | ||
710 | input_abs_set_res(input, usage->code, | ||
711 | hidinput_calc_abs_res(field, usage->code)); | ||
712 | |||
540 | /* use a larger default input buffer for MT devices */ | 713 | /* use a larger default input buffer for MT devices */ |
541 | if (usage->code == ABS_MT_POSITION_X && input->hint_events_per_packet == 0) | 714 | if (usage->code == ABS_MT_POSITION_X && input->hint_events_per_packet == 0) |
542 | input_set_events_per_packet(input, 60); | 715 | input_set_events_per_packet(input, 60); |
@@ -659,6 +832,9 @@ void hidinput_report_event(struct hid_device *hid, struct hid_report *report) | |||
659 | { | 832 | { |
660 | struct hid_input *hidinput; | 833 | struct hid_input *hidinput; |
661 | 834 | ||
835 | if (hid->quirks & HID_QUIRK_NO_INPUT_SYNC) | ||
836 | return; | ||
837 | |||
662 | list_for_each_entry(hidinput, &hid->inputs, list) | 838 | list_for_each_entry(hidinput, &hid->inputs, list) |
663 | input_sync(hidinput->input); | 839 | input_sync(hidinput->input); |
664 | } | 840 | } |
@@ -685,14 +861,32 @@ static int hidinput_open(struct input_dev *dev) | |||
685 | { | 861 | { |
686 | struct hid_device *hid = input_get_drvdata(dev); | 862 | struct hid_device *hid = input_get_drvdata(dev); |
687 | 863 | ||
688 | return hid->ll_driver->open(hid); | 864 | return hid_hw_open(hid); |
689 | } | 865 | } |
690 | 866 | ||
691 | static void hidinput_close(struct input_dev *dev) | 867 | static void hidinput_close(struct input_dev *dev) |
692 | { | 868 | { |
693 | struct hid_device *hid = input_get_drvdata(dev); | 869 | struct hid_device *hid = input_get_drvdata(dev); |
694 | 870 | ||
695 | hid->ll_driver->close(hid); | 871 | hid_hw_close(hid); |
872 | } | ||
873 | |||
874 | static void report_features(struct hid_device *hid) | ||
875 | { | ||
876 | struct hid_driver *drv = hid->driver; | ||
877 | struct hid_report_enum *rep_enum; | ||
878 | struct hid_report *rep; | ||
879 | int i, j; | ||
880 | |||
881 | if (!drv->feature_mapping) | ||
882 | return; | ||
883 | |||
884 | rep_enum = &hid->report_enum[HID_FEATURE_REPORT]; | ||
885 | list_for_each_entry(rep, &rep_enum->report_list, list) | ||
886 | for (i = 0; i < rep->maxfield; i++) | ||
887 | for (j = 0; j < rep->field[i]->maxusage; j++) | ||
888 | drv->feature_mapping(hid, rep->field[i], | ||
889 | rep->field[i]->usage + j); | ||
696 | } | 890 | } |
697 | 891 | ||
698 | /* | 892 | /* |
@@ -707,7 +901,6 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) | |||
707 | struct hid_input *hidinput = NULL; | 901 | struct hid_input *hidinput = NULL; |
708 | struct input_dev *input_dev; | 902 | struct input_dev *input_dev; |
709 | int i, j, k; | 903 | int i, j, k; |
710 | int max_report_type = HID_OUTPUT_REPORT; | ||
711 | 904 | ||
712 | INIT_LIST_HEAD(&hid->inputs); | 905 | INIT_LIST_HEAD(&hid->inputs); |
713 | 906 | ||
@@ -724,10 +917,13 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) | |||
724 | return -1; | 917 | return -1; |
725 | } | 918 | } |
726 | 919 | ||
727 | if (hid->quirks & HID_QUIRK_SKIP_OUTPUT_REPORTS) | 920 | report_features(hid); |
728 | max_report_type = HID_INPUT_REPORT; | 921 | |
922 | for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) { | ||
923 | if (k == HID_OUTPUT_REPORT && | ||
924 | hid->quirks & HID_QUIRK_SKIP_OUTPUT_REPORTS) | ||
925 | continue; | ||
729 | 926 | ||
730 | for (k = HID_INPUT_REPORT; k <= max_report_type; k++) | ||
731 | list_for_each_entry(report, &hid->report_enum[k].report_list, list) { | 927 | list_for_each_entry(report, &hid->report_enum[k].report_list, list) { |
732 | 928 | ||
733 | if (!report->maxfield) | 929 | if (!report->maxfield) |
@@ -739,7 +935,7 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) | |||
739 | if (!hidinput || !input_dev) { | 935 | if (!hidinput || !input_dev) { |
740 | kfree(hidinput); | 936 | kfree(hidinput); |
741 | input_free_device(input_dev); | 937 | input_free_device(input_dev); |
742 | err_hid("Out of memory during hid input probe"); | 938 | hid_err(hid, "Out of memory during hid input probe\n"); |
743 | goto out_unwind; | 939 | goto out_unwind; |
744 | } | 940 | } |
745 | 941 | ||
@@ -780,6 +976,7 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) | |||
780 | hidinput = NULL; | 976 | hidinput = NULL; |
781 | } | 977 | } |
782 | } | 978 | } |
979 | } | ||
783 | 980 | ||
784 | if (hidinput && input_register_device(hidinput->input)) | 981 | if (hidinput && input_register_device(hidinput->input)) |
785 | goto out_cleanup; | 982 | goto out_cleanup; |
@@ -787,6 +984,7 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) | |||
787 | return 0; | 984 | return 0; |
788 | 985 | ||
789 | out_cleanup: | 986 | out_cleanup: |
987 | list_del(&hidinput->list); | ||
790 | input_free_device(hidinput->input); | 988 | input_free_device(hidinput->input); |
791 | kfree(hidinput); | 989 | kfree(hidinput); |
792 | out_unwind: | 990 | out_unwind: |
diff --git a/drivers/hid/hid-keytouch.c b/drivers/hid/hid-keytouch.c new file mode 100644 index 000000000000..07cd825f6f01 --- /dev/null +++ b/drivers/hid/hid-keytouch.c | |||
@@ -0,0 +1,66 @@ | |||
1 | /* | ||
2 | * HID driver for Keytouch devices not fully compliant with HID standard | ||
3 | * | ||
4 | * Copyright (c) 2011 Jiri Kosina | ||
5 | */ | ||
6 | |||
7 | /* | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the Free | ||
10 | * Software Foundation; either version 2 of the License, or (at your option) | ||
11 | * any later version. | ||
12 | */ | ||
13 | |||
14 | #include <linux/device.h> | ||
15 | #include <linux/hid.h> | ||
16 | #include <linux/module.h> | ||
17 | |||
18 | #include "hid-ids.h" | ||
19 | |||
20 | /* Replace the broken report descriptor of this device with rather | ||
21 | * a default one */ | ||
22 | static __u8 keytouch_fixed_rdesc[] = { | ||
23 | 0x05, 0x01, 0x09, 0x06, 0xa1, 0x01, 0x05, 0x07, 0x19, 0xe0, 0x29, 0xe7, 0x15, | ||
24 | 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x08, 0x81, 0x02, 0x95, 0x01, 0x75, 0x08, | ||
25 | 0x81, 0x01, 0x95, 0x03, 0x75, 0x01, 0x05, 0x08, 0x19, 0x01, 0x29, 0x03, 0x91, | ||
26 | 0x02, 0x95, 0x05, 0x75, 0x01, 0x91, 0x01, 0x95, 0x06, 0x75, 0x08, 0x15, 0x00, | ||
27 | 0x26, 0xff, 0x00, 0x05, 0x07, 0x19, 0x00, 0x2a, 0xff, 0x00, 0x81, 0x00, 0xc0 | ||
28 | }; | ||
29 | |||
30 | static __u8 *keytouch_report_fixup(struct hid_device *hdev, __u8 *rdesc, | ||
31 | unsigned int *rsize) | ||
32 | { | ||
33 | hid_info(hdev, "fixing up Keytouch IEC report descriptor\n"); | ||
34 | |||
35 | rdesc = keytouch_fixed_rdesc; | ||
36 | *rsize = sizeof(keytouch_fixed_rdesc); | ||
37 | |||
38 | return rdesc; | ||
39 | } | ||
40 | |||
41 | static const struct hid_device_id keytouch_devices[] = { | ||
42 | { HID_USB_DEVICE(USB_VENDOR_ID_KEYTOUCH, USB_DEVICE_ID_KEYTOUCH_IEC) }, | ||
43 | { } | ||
44 | }; | ||
45 | MODULE_DEVICE_TABLE(hid, keytouch_devices); | ||
46 | |||
47 | static struct hid_driver keytouch_driver = { | ||
48 | .name = "keytouch", | ||
49 | .id_table = keytouch_devices, | ||
50 | .report_fixup = keytouch_report_fixup, | ||
51 | }; | ||
52 | |||
53 | static int __init keytouch_init(void) | ||
54 | { | ||
55 | return hid_register_driver(&keytouch_driver); | ||
56 | } | ||
57 | |||
58 | static void __exit keytouch_exit(void) | ||
59 | { | ||
60 | hid_unregister_driver(&keytouch_driver); | ||
61 | } | ||
62 | |||
63 | module_init(keytouch_init); | ||
64 | module_exit(keytouch_exit); | ||
65 | MODULE_LICENSE("GPL"); | ||
66 | MODULE_AUTHOR("Jiri Kosina"); | ||
diff --git a/drivers/hid/hid-kye.c b/drivers/hid/hid-kye.c index f8871712b7b5..f2ba9efc3a53 100644 --- a/drivers/hid/hid-kye.c +++ b/drivers/hid/hid-kye.c | |||
@@ -23,23 +23,24 @@ | |||
23 | * - report size 8 count 1 must be size 1 count 8 for button bitfield | 23 | * - report size 8 count 1 must be size 1 count 8 for button bitfield |
24 | * - change the button usage range to 4-7 for the extra buttons | 24 | * - change the button usage range to 4-7 for the extra buttons |
25 | */ | 25 | */ |
26 | static void kye_report_fixup(struct hid_device *hdev, __u8 *rdesc, | 26 | static __u8 *kye_report_fixup(struct hid_device *hdev, __u8 *rdesc, |
27 | unsigned int rsize) | 27 | unsigned int *rsize) |
28 | { | 28 | { |
29 | if (rsize >= 74 && | 29 | if (*rsize >= 74 && |
30 | rdesc[61] == 0x05 && rdesc[62] == 0x08 && | 30 | rdesc[61] == 0x05 && rdesc[62] == 0x08 && |
31 | rdesc[63] == 0x19 && rdesc[64] == 0x08 && | 31 | rdesc[63] == 0x19 && rdesc[64] == 0x08 && |
32 | rdesc[65] == 0x29 && rdesc[66] == 0x0f && | 32 | rdesc[65] == 0x29 && rdesc[66] == 0x0f && |
33 | rdesc[71] == 0x75 && rdesc[72] == 0x08 && | 33 | rdesc[71] == 0x75 && rdesc[72] == 0x08 && |
34 | rdesc[73] == 0x95 && rdesc[74] == 0x01) { | 34 | rdesc[73] == 0x95 && rdesc[74] == 0x01) { |
35 | dev_info(&hdev->dev, "fixing up Kye/Genius Ergo Mouse report " | 35 | hid_info(hdev, |
36 | "descriptor\n"); | 36 | "fixing up Kye/Genius Ergo Mouse report descriptor\n"); |
37 | rdesc[62] = 0x09; | 37 | rdesc[62] = 0x09; |
38 | rdesc[64] = 0x04; | 38 | rdesc[64] = 0x04; |
39 | rdesc[66] = 0x07; | 39 | rdesc[66] = 0x07; |
40 | rdesc[72] = 0x01; | 40 | rdesc[72] = 0x01; |
41 | rdesc[74] = 0x08; | 41 | rdesc[74] = 0x08; |
42 | } | 42 | } |
43 | return rdesc; | ||
43 | } | 44 | } |
44 | 45 | ||
45 | static const struct hid_device_id kye_devices[] = { | 46 | static const struct hid_device_id kye_devices[] = { |
diff --git a/drivers/hid/hid-lcpower.c b/drivers/hid/hid-lcpower.c new file mode 100644 index 000000000000..c4fe9bd095b7 --- /dev/null +++ b/drivers/hid/hid-lcpower.c | |||
@@ -0,0 +1,70 @@ | |||
1 | /* | ||
2 | * HID driver for LC Power Model RC1000MCE | ||
3 | * | ||
4 | * Copyright (c) 2011 Chris Schlund | ||
5 | * based on hid-topseed module | ||
6 | */ | ||
7 | |||
8 | /* | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the Free | ||
11 | * Software Foundation; either version 2 of the License, or (at your option) | ||
12 | * any later version. | ||
13 | */ | ||
14 | |||
15 | #include <linux/device.h> | ||
16 | #include <linux/hid.h> | ||
17 | #include <linux/module.h> | ||
18 | |||
19 | #include "hid-ids.h" | ||
20 | |||
21 | #define ts_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ | ||
22 | EV_KEY, (c)) | ||
23 | static int ts_input_mapping(struct hid_device *hdev, struct hid_input *hi, | ||
24 | struct hid_field *field, struct hid_usage *usage, | ||
25 | unsigned long **bit, int *max) | ||
26 | { | ||
27 | if ((usage->hid & HID_USAGE_PAGE) != 0x0ffbc0000) | ||
28 | return 0; | ||
29 | |||
30 | switch (usage->hid & HID_USAGE) { | ||
31 | case 0x046: ts_map_key_clear(KEY_YELLOW); break; | ||
32 | case 0x047: ts_map_key_clear(KEY_GREEN); break; | ||
33 | case 0x049: ts_map_key_clear(KEY_BLUE); break; | ||
34 | case 0x04a: ts_map_key_clear(KEY_RED); break; | ||
35 | case 0x00d: ts_map_key_clear(KEY_HOME); break; | ||
36 | case 0x025: ts_map_key_clear(KEY_TV); break; | ||
37 | case 0x048: ts_map_key_clear(KEY_VCR); break; | ||
38 | case 0x024: ts_map_key_clear(KEY_MENU); break; | ||
39 | default: | ||
40 | return 0; | ||
41 | } | ||
42 | |||
43 | return 1; | ||
44 | } | ||
45 | |||
46 | static const struct hid_device_id ts_devices[] = { | ||
47 | { HID_USB_DEVICE( USB_VENDOR_ID_LCPOWER, USB_DEVICE_ID_LCPOWER_LC1000) }, | ||
48 | { } | ||
49 | }; | ||
50 | MODULE_DEVICE_TABLE(hid, ts_devices); | ||
51 | |||
52 | static struct hid_driver ts_driver = { | ||
53 | .name = "LC RC1000MCE", | ||
54 | .id_table = ts_devices, | ||
55 | .input_mapping = ts_input_mapping, | ||
56 | }; | ||
57 | |||
58 | static int __init ts_init(void) | ||
59 | { | ||
60 | return hid_register_driver(&ts_driver); | ||
61 | } | ||
62 | |||
63 | static void __exit ts_exit(void) | ||
64 | { | ||
65 | hid_unregister_driver(&ts_driver); | ||
66 | } | ||
67 | |||
68 | module_init(ts_init); | ||
69 | module_exit(ts_exit); | ||
70 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c index f6433d8050a9..21f205f09250 100644 --- a/drivers/hid/hid-lg.c +++ b/drivers/hid/hid-lg.c | |||
@@ -7,6 +7,7 @@ | |||
7 | * Copyright (c) 2006-2007 Jiri Kosina | 7 | * Copyright (c) 2006-2007 Jiri Kosina |
8 | * Copyright (c) 2007 Paul Walmsley | 8 | * Copyright (c) 2007 Paul Walmsley |
9 | * Copyright (c) 2008 Jiri Slaby | 9 | * Copyright (c) 2008 Jiri Slaby |
10 | * Copyright (c) 2010 Hendrik Iben | ||
10 | */ | 11 | */ |
11 | 12 | ||
12 | /* | 13 | /* |
@@ -19,6 +20,9 @@ | |||
19 | #include <linux/device.h> | 20 | #include <linux/device.h> |
20 | #include <linux/hid.h> | 21 | #include <linux/hid.h> |
21 | #include <linux/module.h> | 22 | #include <linux/module.h> |
23 | #include <linux/random.h> | ||
24 | #include <linux/sched.h> | ||
25 | #include <linux/wait.h> | ||
22 | 26 | ||
23 | #include "hid-ids.h" | 27 | #include "hid-ids.h" |
24 | #include "hid-lg.h" | 28 | #include "hid-lg.h" |
@@ -35,31 +39,42 @@ | |||
35 | #define LG_FF2 0x400 | 39 | #define LG_FF2 0x400 |
36 | #define LG_RDESC_REL_ABS 0x800 | 40 | #define LG_RDESC_REL_ABS 0x800 |
37 | #define LG_FF3 0x1000 | 41 | #define LG_FF3 0x1000 |
42 | #define LG_FF4 0x2000 | ||
38 | 43 | ||
39 | /* | 44 | /* |
40 | * Certain Logitech keyboards send in report #3 keys which are far | 45 | * Certain Logitech keyboards send in report #3 keys which are far |
41 | * above the logical maximum described in descriptor. This extends | 46 | * above the logical maximum described in descriptor. This extends |
42 | * the original value of 0x28c of logical maximum to 0x104d | 47 | * the original value of 0x28c of logical maximum to 0x104d |
43 | */ | 48 | */ |
44 | static void lg_report_fixup(struct hid_device *hdev, __u8 *rdesc, | 49 | static __u8 *lg_report_fixup(struct hid_device *hdev, __u8 *rdesc, |
45 | unsigned int rsize) | 50 | unsigned int *rsize) |
46 | { | 51 | { |
47 | unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); | 52 | unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); |
48 | 53 | ||
49 | if ((quirks & LG_RDESC) && rsize >= 90 && rdesc[83] == 0x26 && | 54 | if ((quirks & LG_RDESC) && *rsize >= 90 && rdesc[83] == 0x26 && |
50 | rdesc[84] == 0x8c && rdesc[85] == 0x02) { | 55 | rdesc[84] == 0x8c && rdesc[85] == 0x02) { |
51 | dev_info(&hdev->dev, "fixing up Logitech keyboard report " | 56 | hid_info(hdev, |
52 | "descriptor\n"); | 57 | "fixing up Logitech keyboard report descriptor\n"); |
53 | rdesc[84] = rdesc[89] = 0x4d; | 58 | rdesc[84] = rdesc[89] = 0x4d; |
54 | rdesc[85] = rdesc[90] = 0x10; | 59 | rdesc[85] = rdesc[90] = 0x10; |
55 | } | 60 | } |
56 | if ((quirks & LG_RDESC_REL_ABS) && rsize >= 50 && | 61 | if ((quirks & LG_RDESC_REL_ABS) && *rsize >= 50 && |
57 | rdesc[32] == 0x81 && rdesc[33] == 0x06 && | 62 | rdesc[32] == 0x81 && rdesc[33] == 0x06 && |
58 | rdesc[49] == 0x81 && rdesc[50] == 0x06) { | 63 | rdesc[49] == 0x81 && rdesc[50] == 0x06) { |
59 | dev_info(&hdev->dev, "fixing up rel/abs in Logitech " | 64 | hid_info(hdev, |
60 | "report descriptor\n"); | 65 | "fixing up rel/abs in Logitech report descriptor\n"); |
61 | rdesc[33] = rdesc[50] = 0x02; | 66 | rdesc[33] = rdesc[50] = 0x02; |
62 | } | 67 | } |
68 | if ((quirks & LG_FF4) && *rsize >= 101 && | ||
69 | rdesc[41] == 0x95 && rdesc[42] == 0x0B && | ||
70 | rdesc[47] == 0x05 && rdesc[48] == 0x09) { | ||
71 | hid_info(hdev, "fixing up Logitech Speed Force Wireless button descriptor\n"); | ||
72 | rdesc[41] = 0x05; | ||
73 | rdesc[42] = 0x09; | ||
74 | rdesc[47] = 0x95; | ||
75 | rdesc[48] = 0x0B; | ||
76 | } | ||
77 | return rdesc; | ||
63 | } | 78 | } |
64 | 79 | ||
65 | #define lg_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ | 80 | #define lg_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ |
@@ -272,7 +287,7 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
272 | 287 | ||
273 | ret = hid_parse(hdev); | 288 | ret = hid_parse(hdev); |
274 | if (ret) { | 289 | if (ret) { |
275 | dev_err(&hdev->dev, "parse failed\n"); | 290 | hid_err(hdev, "parse failed\n"); |
276 | goto err_free; | 291 | goto err_free; |
277 | } | 292 | } |
278 | 293 | ||
@@ -281,16 +296,37 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
281 | 296 | ||
282 | ret = hid_hw_start(hdev, connect_mask); | 297 | ret = hid_hw_start(hdev, connect_mask); |
283 | if (ret) { | 298 | if (ret) { |
284 | dev_err(&hdev->dev, "hw start failed\n"); | 299 | hid_err(hdev, "hw start failed\n"); |
285 | goto err_free; | 300 | goto err_free; |
286 | } | 301 | } |
287 | 302 | ||
303 | if (quirks & LG_FF4) { | ||
304 | unsigned char buf[] = { 0x00, 0xAF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; | ||
305 | |||
306 | ret = hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT); | ||
307 | |||
308 | if (ret >= 0) { | ||
309 | /* insert a little delay of 10 jiffies ~ 40ms */ | ||
310 | wait_queue_head_t wait; | ||
311 | init_waitqueue_head (&wait); | ||
312 | wait_event_interruptible_timeout(wait, 0, 10); | ||
313 | |||
314 | /* Select random Address */ | ||
315 | buf[1] = 0xB2; | ||
316 | get_random_bytes(&buf[2], 2); | ||
317 | |||
318 | ret = hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT); | ||
319 | } | ||
320 | } | ||
321 | |||
288 | if (quirks & LG_FF) | 322 | if (quirks & LG_FF) |
289 | lgff_init(hdev); | 323 | lgff_init(hdev); |
290 | if (quirks & LG_FF2) | 324 | if (quirks & LG_FF2) |
291 | lg2ff_init(hdev); | 325 | lg2ff_init(hdev); |
292 | if (quirks & LG_FF3) | 326 | if (quirks & LG_FF3) |
293 | lg3ff_init(hdev); | 327 | lg3ff_init(hdev); |
328 | if (quirks & LG_FF4) | ||
329 | lg4ff_init(hdev); | ||
294 | 330 | ||
295 | return 0; | 331 | return 0; |
296 | err_free: | 332 | err_free: |
@@ -325,6 +361,8 @@ static const struct hid_device_id lg_devices[] = { | |||
325 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL), | 361 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL), |
326 | .driver_data = LG_NOGET | LG_FF }, | 362 | .driver_data = LG_NOGET | LG_FF }, |
327 | 363 | ||
364 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD), | ||
365 | .driver_data = LG_FF2 }, | ||
328 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD), | 366 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD), |
329 | .driver_data = LG_FF }, | 367 | .driver_data = LG_FF }, |
330 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2), | 368 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2), |
@@ -339,6 +377,12 @@ static const struct hid_device_id lg_devices[] = { | |||
339 | .driver_data = LG_FF }, | 377 | .driver_data = LG_FF }, |
340 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL), | 378 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL), |
341 | .driver_data = LG_FF }, | 379 | .driver_data = LG_FF }, |
380 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G27_WHEEL), | ||
381 | .driver_data = LG_FF }, | ||
382 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFP_WHEEL), | ||
383 | .driver_data = LG_FF }, | ||
384 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WII_WHEEL), | ||
385 | .driver_data = LG_FF4 }, | ||
342 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ), | 386 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ), |
343 | .driver_data = LG_FF }, | 387 | .driver_data = LG_FF }, |
344 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2), | 388 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2), |
diff --git a/drivers/hid/hid-lg.h b/drivers/hid/hid-lg.h index ce2ac8672624..b0100ba2ae0b 100644 --- a/drivers/hid/hid-lg.h +++ b/drivers/hid/hid-lg.h | |||
@@ -19,4 +19,10 @@ int lg3ff_init(struct hid_device *hdev); | |||
19 | static inline int lg3ff_init(struct hid_device *hdev) { return -1; } | 19 | static inline int lg3ff_init(struct hid_device *hdev) { return -1; } |
20 | #endif | 20 | #endif |
21 | 21 | ||
22 | #ifdef CONFIG_LOGIWII_FF | ||
23 | int lg4ff_init(struct hid_device *hdev); | ||
24 | #else | ||
25 | static inline int lg4ff_init(struct hid_device *hdev) { return -1; } | ||
26 | #endif | ||
27 | |||
22 | #endif | 28 | #endif |
diff --git a/drivers/hid/hid-lg2ff.c b/drivers/hid/hid-lg2ff.c index d888f1e6794f..3c31bc650e5d 100644 --- a/drivers/hid/hid-lg2ff.c +++ b/drivers/hid/hid-lg2ff.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Force feedback support for Logitech Rumblepad 2 | 2 | * Force feedback support for Logitech RumblePad and Rumblepad 2 |
3 | * | 3 | * |
4 | * Copyright (c) 2008 Anssi Hannula <anssi.hannula@gmail.com> | 4 | * Copyright (c) 2008 Anssi Hannula <anssi.hannula@gmail.com> |
5 | */ | 5 | */ |
@@ -72,18 +72,18 @@ int lg2ff_init(struct hid_device *hid) | |||
72 | int error; | 72 | int error; |
73 | 73 | ||
74 | if (list_empty(report_list)) { | 74 | if (list_empty(report_list)) { |
75 | dev_err(&hid->dev, "no output report found\n"); | 75 | hid_err(hid, "no output report found\n"); |
76 | return -ENODEV; | 76 | return -ENODEV; |
77 | } | 77 | } |
78 | 78 | ||
79 | report = list_entry(report_list->next, struct hid_report, list); | 79 | report = list_entry(report_list->next, struct hid_report, list); |
80 | 80 | ||
81 | if (report->maxfield < 1) { | 81 | if (report->maxfield < 1) { |
82 | dev_err(&hid->dev, "output report is empty\n"); | 82 | hid_err(hid, "output report is empty\n"); |
83 | return -ENODEV; | 83 | return -ENODEV; |
84 | } | 84 | } |
85 | if (report->field[0]->report_count < 7) { | 85 | if (report->field[0]->report_count < 7) { |
86 | dev_err(&hid->dev, "not enough values in the field\n"); | 86 | hid_err(hid, "not enough values in the field\n"); |
87 | return -ENODEV; | 87 | return -ENODEV; |
88 | } | 88 | } |
89 | 89 | ||
@@ -110,8 +110,7 @@ int lg2ff_init(struct hid_device *hid) | |||
110 | 110 | ||
111 | usbhid_submit_report(hid, report, USB_DIR_OUT); | 111 | usbhid_submit_report(hid, report, USB_DIR_OUT); |
112 | 112 | ||
113 | dev_info(&hid->dev, "Force feedback for Logitech Rumblepad 2 by " | 113 | hid_info(hid, "Force feedback for Logitech RumblePad/Rumblepad 2 by Anssi Hannula <anssi.hannula@gmail.com>\n"); |
114 | "Anssi Hannula <anssi.hannula@gmail.com>\n"); | ||
115 | 114 | ||
116 | return 0; | 115 | return 0; |
117 | } | 116 | } |
diff --git a/drivers/hid/hid-lg3ff.c b/drivers/hid/hid-lg3ff.c index 4002832ee4af..f98644c26c1d 100644 --- a/drivers/hid/hid-lg3ff.c +++ b/drivers/hid/hid-lg3ff.c | |||
@@ -141,20 +141,20 @@ int lg3ff_init(struct hid_device *hid) | |||
141 | 141 | ||
142 | /* Find the report to use */ | 142 | /* Find the report to use */ |
143 | if (list_empty(report_list)) { | 143 | if (list_empty(report_list)) { |
144 | err_hid("No output report found"); | 144 | hid_err(hid, "No output report found\n"); |
145 | return -1; | 145 | return -1; |
146 | } | 146 | } |
147 | 147 | ||
148 | /* Check that the report looks ok */ | 148 | /* Check that the report looks ok */ |
149 | report = list_entry(report_list->next, struct hid_report, list); | 149 | report = list_entry(report_list->next, struct hid_report, list); |
150 | if (!report) { | 150 | if (!report) { |
151 | err_hid("NULL output report"); | 151 | hid_err(hid, "NULL output report\n"); |
152 | return -1; | 152 | return -1; |
153 | } | 153 | } |
154 | 154 | ||
155 | field = report->field[0]; | 155 | field = report->field[0]; |
156 | if (!field) { | 156 | if (!field) { |
157 | err_hid("NULL field"); | 157 | hid_err(hid, "NULL field\n"); |
158 | return -1; | 158 | return -1; |
159 | } | 159 | } |
160 | 160 | ||
@@ -169,8 +169,7 @@ int lg3ff_init(struct hid_device *hid) | |||
169 | if (test_bit(FF_AUTOCENTER, dev->ffbit)) | 169 | if (test_bit(FF_AUTOCENTER, dev->ffbit)) |
170 | dev->ff->set_autocenter = hid_lg3ff_set_autocenter; | 170 | dev->ff->set_autocenter = hid_lg3ff_set_autocenter; |
171 | 171 | ||
172 | dev_info(&hid->dev, "Force feedback for Logitech Flight System G940 by " | 172 | hid_info(hid, "Force feedback for Logitech Flight System G940 by Gary Stein <LordCnidarian@gmail.com>\n"); |
173 | "Gary Stein <LordCnidarian@gmail.com>\n"); | ||
174 | return 0; | 173 | return 0; |
175 | } | 174 | } |
176 | 175 | ||
diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c new file mode 100644 index 000000000000..fa550c8e1d1b --- /dev/null +++ b/drivers/hid/hid-lg4ff.c | |||
@@ -0,0 +1,135 @@ | |||
1 | /* | ||
2 | * Force feedback support for Logitech Speed Force Wireless | ||
3 | * | ||
4 | * http://wiibrew.org/wiki/Logitech_USB_steering_wheel | ||
5 | * | ||
6 | * Copyright (c) 2010 Simon Wood <simon@mungewell.org> | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
23 | */ | ||
24 | |||
25 | |||
26 | #include <linux/input.h> | ||
27 | #include <linux/usb.h> | ||
28 | #include <linux/hid.h> | ||
29 | |||
30 | #include "usbhid/usbhid.h" | ||
31 | #include "hid-lg.h" | ||
32 | |||
33 | struct lg4ff_device { | ||
34 | struct hid_report *report; | ||
35 | }; | ||
36 | |||
37 | static const signed short ff4_wheel_ac[] = { | ||
38 | FF_CONSTANT, | ||
39 | FF_AUTOCENTER, | ||
40 | -1 | ||
41 | }; | ||
42 | |||
43 | static int hid_lg4ff_play(struct input_dev *dev, void *data, | ||
44 | struct ff_effect *effect) | ||
45 | { | ||
46 | struct hid_device *hid = input_get_drvdata(dev); | ||
47 | struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; | ||
48 | struct hid_report *report = list_entry(report_list->next, struct hid_report, list); | ||
49 | int x; | ||
50 | |||
51 | #define CLAMP(x) if (x < 0) x = 0; if (x > 0xff) x = 0xff | ||
52 | |||
53 | switch (effect->type) { | ||
54 | case FF_CONSTANT: | ||
55 | x = effect->u.ramp.start_level + 0x80; /* 0x80 is no force */ | ||
56 | CLAMP(x); | ||
57 | report->field[0]->value[0] = 0x11; /* Slot 1 */ | ||
58 | report->field[0]->value[1] = 0x10; | ||
59 | report->field[0]->value[2] = x; | ||
60 | report->field[0]->value[3] = 0x00; | ||
61 | report->field[0]->value[4] = 0x00; | ||
62 | report->field[0]->value[5] = 0x08; | ||
63 | report->field[0]->value[6] = 0x00; | ||
64 | dbg_hid("Autocenter, x=0x%02X\n", x); | ||
65 | |||
66 | usbhid_submit_report(hid, report, USB_DIR_OUT); | ||
67 | break; | ||
68 | } | ||
69 | return 0; | ||
70 | } | ||
71 | |||
72 | static void hid_lg4ff_set_autocenter(struct input_dev *dev, u16 magnitude) | ||
73 | { | ||
74 | struct hid_device *hid = input_get_drvdata(dev); | ||
75 | struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; | ||
76 | struct hid_report *report = list_entry(report_list->next, struct hid_report, list); | ||
77 | __s32 *value = report->field[0]->value; | ||
78 | |||
79 | *value++ = 0xfe; | ||
80 | *value++ = 0x0d; | ||
81 | *value++ = 0x07; | ||
82 | *value++ = 0x07; | ||
83 | *value++ = (magnitude >> 8) & 0xff; | ||
84 | *value++ = 0x00; | ||
85 | *value = 0x00; | ||
86 | |||
87 | usbhid_submit_report(hid, report, USB_DIR_OUT); | ||
88 | } | ||
89 | |||
90 | |||
91 | int lg4ff_init(struct hid_device *hid) | ||
92 | { | ||
93 | struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); | ||
94 | struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; | ||
95 | struct input_dev *dev = hidinput->input; | ||
96 | struct hid_report *report; | ||
97 | struct hid_field *field; | ||
98 | const signed short *ff_bits = ff4_wheel_ac; | ||
99 | int error; | ||
100 | int i; | ||
101 | |||
102 | /* Find the report to use */ | ||
103 | if (list_empty(report_list)) { | ||
104 | hid_err(hid, "No output report found\n"); | ||
105 | return -1; | ||
106 | } | ||
107 | |||
108 | /* Check that the report looks ok */ | ||
109 | report = list_entry(report_list->next, struct hid_report, list); | ||
110 | if (!report) { | ||
111 | hid_err(hid, "NULL output report\n"); | ||
112 | return -1; | ||
113 | } | ||
114 | |||
115 | field = report->field[0]; | ||
116 | if (!field) { | ||
117 | hid_err(hid, "NULL field\n"); | ||
118 | return -1; | ||
119 | } | ||
120 | |||
121 | for (i = 0; ff_bits[i] >= 0; i++) | ||
122 | set_bit(ff_bits[i], dev->ffbit); | ||
123 | |||
124 | error = input_ff_create_memless(dev, NULL, hid_lg4ff_play); | ||
125 | |||
126 | if (error) | ||
127 | return error; | ||
128 | |||
129 | if (test_bit(FF_AUTOCENTER, dev->ffbit)) | ||
130 | dev->ff->set_autocenter = hid_lg4ff_set_autocenter; | ||
131 | |||
132 | hid_info(hid, "Force feedback for Logitech Speed Force Wireless by Simon Wood <simon@mungewell.org>\n"); | ||
133 | return 0; | ||
134 | } | ||
135 | |||
diff --git a/drivers/hid/hid-lgff.c b/drivers/hid/hid-lgff.c index 61142b76a9b1..088f85049290 100644 --- a/drivers/hid/hid-lgff.c +++ b/drivers/hid/hid-lgff.c | |||
@@ -27,6 +27,8 @@ | |||
27 | * e-mail - mail your message to <johann.deneux@it.uu.se> | 27 | * e-mail - mail your message to <johann.deneux@it.uu.se> |
28 | */ | 28 | */ |
29 | 29 | ||
30 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
31 | |||
30 | #include <linux/input.h> | 32 | #include <linux/input.h> |
31 | #include <linux/usb.h> | 33 | #include <linux/usb.h> |
32 | #include <linux/hid.h> | 34 | #include <linux/hid.h> |
@@ -70,7 +72,12 @@ static const struct dev_type devices[] = { | |||
70 | { 0x046d, 0xc287, ff_joystick_ac }, | 72 | { 0x046d, 0xc287, ff_joystick_ac }, |
71 | { 0x046d, 0xc293, ff_joystick }, | 73 | { 0x046d, 0xc293, ff_joystick }, |
72 | { 0x046d, 0xc294, ff_wheel }, | 74 | { 0x046d, 0xc294, ff_wheel }, |
75 | { 0x046d, 0xc298, ff_wheel }, | ||
76 | { 0x046d, 0xc299, ff_wheel }, | ||
77 | { 0x046d, 0xc29b, ff_wheel }, | ||
73 | { 0x046d, 0xc295, ff_joystick }, | 78 | { 0x046d, 0xc295, ff_joystick }, |
79 | { 0x046d, 0xc298, ff_wheel }, | ||
80 | { 0x046d, 0xc299, ff_wheel }, | ||
74 | { 0x046d, 0xca03, ff_wheel }, | 81 | { 0x046d, 0xca03, ff_wheel }, |
75 | }; | 82 | }; |
76 | 83 | ||
@@ -146,7 +153,7 @@ int lgff_init(struct hid_device* hid) | |||
146 | 153 | ||
147 | /* Find the report to use */ | 154 | /* Find the report to use */ |
148 | if (list_empty(report_list)) { | 155 | if (list_empty(report_list)) { |
149 | err_hid("No output report found"); | 156 | hid_err(hid, "No output report found\n"); |
150 | return -1; | 157 | return -1; |
151 | } | 158 | } |
152 | 159 | ||
@@ -154,7 +161,7 @@ int lgff_init(struct hid_device* hid) | |||
154 | report = list_entry(report_list->next, struct hid_report, list); | 161 | report = list_entry(report_list->next, struct hid_report, list); |
155 | field = report->field[0]; | 162 | field = report->field[0]; |
156 | if (!field) { | 163 | if (!field) { |
157 | err_hid("NULL field"); | 164 | hid_err(hid, "NULL field\n"); |
158 | return -1; | 165 | return -1; |
159 | } | 166 | } |
160 | 167 | ||
@@ -176,7 +183,7 @@ int lgff_init(struct hid_device* hid) | |||
176 | if ( test_bit(FF_AUTOCENTER, dev->ffbit) ) | 183 | if ( test_bit(FF_AUTOCENTER, dev->ffbit) ) |
177 | dev->ff->set_autocenter = hid_lgff_set_autocenter; | 184 | dev->ff->set_autocenter = hid_lgff_set_autocenter; |
178 | 185 | ||
179 | printk(KERN_INFO "Force feedback for Logitech force feedback devices by Johann Deneux <johann.deneux@it.uu.se>\n"); | 186 | pr_info("Force feedback for Logitech force feedback devices by Johann Deneux <johann.deneux@it.uu.se>\n"); |
180 | 187 | ||
181 | return 0; | 188 | return 0; |
182 | } | 189 | } |
diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c index 319b0e57ee41..0ec91c18a421 100644 --- a/drivers/hid/hid-magicmouse.c +++ b/drivers/hid/hid-magicmouse.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * Apple "Magic" Wireless Mouse driver | 2 | * Apple "Magic" Wireless Mouse driver |
3 | * | 3 | * |
4 | * Copyright (c) 2010 Michael Poole <mdpoole@troilus.org> | 4 | * Copyright (c) 2010 Michael Poole <mdpoole@troilus.org> |
5 | * Copyright (c) 2010 Chase Douglas <chase.douglas@canonical.com> | ||
5 | */ | 6 | */ |
6 | 7 | ||
7 | /* | 8 | /* |
@@ -11,6 +12,8 @@ | |||
11 | * any later version. | 12 | * any later version. |
12 | */ | 13 | */ |
13 | 14 | ||
15 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
16 | |||
14 | #include <linux/device.h> | 17 | #include <linux/device.h> |
15 | #include <linux/hid.h> | 18 | #include <linux/hid.h> |
16 | #include <linux/module.h> | 19 | #include <linux/module.h> |
@@ -53,7 +56,9 @@ static bool report_undeciphered; | |||
53 | module_param(report_undeciphered, bool, 0644); | 56 | module_param(report_undeciphered, bool, 0644); |
54 | MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state field using a MSC_RAW event"); | 57 | MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state field using a MSC_RAW event"); |
55 | 58 | ||
56 | #define TOUCH_REPORT_ID 0x29 | 59 | #define TRACKPAD_REPORT_ID 0x28 |
60 | #define MOUSE_REPORT_ID 0x29 | ||
61 | #define DOUBLE_REPORT_ID 0xf7 | ||
57 | /* These definitions are not precise, but they're close enough. (Bits | 62 | /* These definitions are not precise, but they're close enough. (Bits |
58 | * 0x03 seem to indicate the aspect ratio of the touch, bits 0x70 seem | 63 | * 0x03 seem to indicate the aspect ratio of the touch, bits 0x70 seem |
59 | * to be some kind of bit mask -- 0x20 may be a near-field reading, | 64 | * to be some kind of bit mask -- 0x20 may be a near-field reading, |
@@ -67,15 +72,19 @@ MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state fie | |||
67 | 72 | ||
68 | #define SCROLL_ACCEL_DEFAULT 7 | 73 | #define SCROLL_ACCEL_DEFAULT 7 |
69 | 74 | ||
75 | /* Single touch emulation should only begin when no touches are currently down. | ||
76 | * This is true when single_touch_id is equal to NO_TOUCHES. If multiple touches | ||
77 | * are down and the touch providing for single touch emulation is lifted, | ||
78 | * single_touch_id is equal to SINGLE_TOUCH_UP. While single touch emulation is | ||
79 | * occurring, single_touch_id corresponds with the tracking id of the touch used. | ||
80 | */ | ||
81 | #define NO_TOUCHES -1 | ||
82 | #define SINGLE_TOUCH_UP -2 | ||
83 | |||
70 | /** | 84 | /** |
71 | * struct magicmouse_sc - Tracks Magic Mouse-specific data. | 85 | * struct magicmouse_sc - Tracks Magic Mouse-specific data. |
72 | * @input: Input device through which we report events. | 86 | * @input: Input device through which we report events. |
73 | * @quirks: Currently unused. | 87 | * @quirks: Currently unused. |
74 | * @last_timestamp: Timestamp from most recent (18-bit) touch report | ||
75 | * (units of milliseconds over short windows, but seems to | ||
76 | * increase faster when there are no touches). | ||
77 | * @delta_time: 18-bit difference between the two most recent touch | ||
78 | * reports from the mouse. | ||
79 | * @ntouches: Number of touches in most recent touch report. | 88 | * @ntouches: Number of touches in most recent touch report. |
80 | * @scroll_accel: Number of consecutive scroll motions. | 89 | * @scroll_accel: Number of consecutive scroll motions. |
81 | * @scroll_jiffies: Time of last scroll motion. | 90 | * @scroll_jiffies: Time of last scroll motion. |
@@ -86,8 +95,6 @@ struct magicmouse_sc { | |||
86 | struct input_dev *input; | 95 | struct input_dev *input; |
87 | unsigned long quirks; | 96 | unsigned long quirks; |
88 | 97 | ||
89 | int last_timestamp; | ||
90 | int delta_time; | ||
91 | int ntouches; | 98 | int ntouches; |
92 | int scroll_accel; | 99 | int scroll_accel; |
93 | unsigned long scroll_jiffies; | 100 | unsigned long scroll_jiffies; |
@@ -98,9 +105,9 @@ struct magicmouse_sc { | |||
98 | short scroll_x; | 105 | short scroll_x; |
99 | short scroll_y; | 106 | short scroll_y; |
100 | u8 size; | 107 | u8 size; |
101 | u8 down; | ||
102 | } touches[16]; | 108 | } touches[16]; |
103 | int tracking_ids[16]; | 109 | int tracking_ids[16]; |
110 | int single_touch_id; | ||
104 | }; | 111 | }; |
105 | 112 | ||
106 | static int magicmouse_firm_touch(struct magicmouse_sc *msc) | 113 | static int magicmouse_firm_touch(struct magicmouse_sc *msc) |
@@ -166,18 +173,35 @@ static void magicmouse_emit_buttons(struct magicmouse_sc *msc, int state) | |||
166 | static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tdata) | 173 | static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tdata) |
167 | { | 174 | { |
168 | struct input_dev *input = msc->input; | 175 | struct input_dev *input = msc->input; |
169 | __s32 x_y = tdata[0] << 8 | tdata[1] << 16 | tdata[2] << 24; | 176 | int id, x, y, size, orientation, touch_major, touch_minor, state, down; |
170 | int misc = tdata[5] | tdata[6] << 8; | 177 | |
171 | int id = (misc >> 6) & 15; | 178 | if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE) { |
172 | int x = x_y << 12 >> 20; | 179 | id = (tdata[6] << 2 | tdata[5] >> 6) & 0xf; |
173 | int y = -(x_y >> 20); | 180 | x = (tdata[1] << 28 | tdata[0] << 20) >> 20; |
174 | int down = (tdata[7] & TOUCH_STATE_MASK) != TOUCH_STATE_NONE; | 181 | y = -((tdata[2] << 24 | tdata[1] << 16) >> 20); |
182 | size = tdata[5] & 0x3f; | ||
183 | orientation = (tdata[6] >> 2) - 32; | ||
184 | touch_major = tdata[3]; | ||
185 | touch_minor = tdata[4]; | ||
186 | state = tdata[7] & TOUCH_STATE_MASK; | ||
187 | down = state != TOUCH_STATE_NONE; | ||
188 | } else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */ | ||
189 | id = (tdata[7] << 2 | tdata[6] >> 6) & 0xf; | ||
190 | x = (tdata[1] << 27 | tdata[0] << 19) >> 19; | ||
191 | y = -((tdata[3] << 30 | tdata[2] << 22 | tdata[1] << 14) >> 19); | ||
192 | size = tdata[6] & 0x3f; | ||
193 | orientation = (tdata[7] >> 2) - 32; | ||
194 | touch_major = tdata[4]; | ||
195 | touch_minor = tdata[5]; | ||
196 | state = tdata[8] & TOUCH_STATE_MASK; | ||
197 | down = state != TOUCH_STATE_NONE; | ||
198 | } | ||
175 | 199 | ||
176 | /* Store tracking ID and other fields. */ | 200 | /* Store tracking ID and other fields. */ |
177 | msc->tracking_ids[raw_id] = id; | 201 | msc->tracking_ids[raw_id] = id; |
178 | msc->touches[id].x = x; | 202 | msc->touches[id].x = x; |
179 | msc->touches[id].y = y; | 203 | msc->touches[id].y = y; |
180 | msc->touches[id].size = misc & 63; | 204 | msc->touches[id].size = size; |
181 | 205 | ||
182 | /* If requested, emulate a scroll wheel by detecting small | 206 | /* If requested, emulate a scroll wheel by detecting small |
183 | * vertical touch motions. | 207 | * vertical touch motions. |
@@ -188,7 +212,7 @@ static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tda | |||
188 | int step_y = msc->touches[id].scroll_y - y; | 212 | int step_y = msc->touches[id].scroll_y - y; |
189 | 213 | ||
190 | /* Calculate and apply the scroll motion. */ | 214 | /* Calculate and apply the scroll motion. */ |
191 | switch (tdata[7] & TOUCH_STATE_MASK) { | 215 | switch (state) { |
192 | case TOUCH_STATE_START: | 216 | case TOUCH_STATE_START: |
193 | msc->touches[id].scroll_x = x; | 217 | msc->touches[id].scroll_x = x; |
194 | msc->touches[id].scroll_y = y; | 218 | msc->touches[id].scroll_y = y; |
@@ -222,21 +246,28 @@ static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tda | |||
222 | } | 246 | } |
223 | } | 247 | } |
224 | 248 | ||
249 | if (down) { | ||
250 | msc->ntouches++; | ||
251 | if (msc->single_touch_id == NO_TOUCHES) | ||
252 | msc->single_touch_id = id; | ||
253 | } else if (msc->single_touch_id == id) | ||
254 | msc->single_touch_id = SINGLE_TOUCH_UP; | ||
255 | |||
225 | /* Generate the input events for this touch. */ | 256 | /* Generate the input events for this touch. */ |
226 | if (report_touches && down) { | 257 | if (report_touches && down) { |
227 | int orientation = (misc >> 10) - 32; | ||
228 | |||
229 | msc->touches[id].down = 1; | ||
230 | |||
231 | input_report_abs(input, ABS_MT_TRACKING_ID, id); | 258 | input_report_abs(input, ABS_MT_TRACKING_ID, id); |
232 | input_report_abs(input, ABS_MT_TOUCH_MAJOR, tdata[3]); | 259 | input_report_abs(input, ABS_MT_TOUCH_MAJOR, touch_major << 2); |
233 | input_report_abs(input, ABS_MT_TOUCH_MINOR, tdata[4]); | 260 | input_report_abs(input, ABS_MT_TOUCH_MINOR, touch_minor << 2); |
234 | input_report_abs(input, ABS_MT_ORIENTATION, orientation); | 261 | input_report_abs(input, ABS_MT_ORIENTATION, -orientation); |
235 | input_report_abs(input, ABS_MT_POSITION_X, x); | 262 | input_report_abs(input, ABS_MT_POSITION_X, x); |
236 | input_report_abs(input, ABS_MT_POSITION_Y, y); | 263 | input_report_abs(input, ABS_MT_POSITION_Y, y); |
237 | 264 | ||
238 | if (report_undeciphered) | 265 | if (report_undeciphered) { |
239 | input_event(input, EV_MSC, MSC_RAW, tdata[7]); | 266 | if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE) |
267 | input_event(input, EV_MSC, MSC_RAW, tdata[7]); | ||
268 | else /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */ | ||
269 | input_event(input, EV_MSC, MSC_RAW, tdata[8]); | ||
270 | } | ||
240 | 271 | ||
241 | input_mt_sync(input); | 272 | input_mt_sync(input); |
242 | } | 273 | } |
@@ -247,39 +278,43 @@ static int magicmouse_raw_event(struct hid_device *hdev, | |||
247 | { | 278 | { |
248 | struct magicmouse_sc *msc = hid_get_drvdata(hdev); | 279 | struct magicmouse_sc *msc = hid_get_drvdata(hdev); |
249 | struct input_dev *input = msc->input; | 280 | struct input_dev *input = msc->input; |
250 | int x, y, ts, ii, clicks, last_up; | 281 | int x = 0, y = 0, ii, clicks = 0, npoints; |
251 | 282 | ||
252 | switch (data[0]) { | 283 | switch (data[0]) { |
253 | case 0x10: | 284 | case TRACKPAD_REPORT_ID: |
254 | if (size != 6) | 285 | /* Expect four bytes of prefix, and N*9 bytes of touch data. */ |
286 | if (size < 4 || ((size - 4) % 9) != 0) | ||
255 | return 0; | 287 | return 0; |
256 | x = (__s16)(data[2] | data[3] << 8); | 288 | npoints = (size - 4) / 9; |
257 | y = (__s16)(data[4] | data[5] << 8); | 289 | msc->ntouches = 0; |
290 | for (ii = 0; ii < npoints; ii++) | ||
291 | magicmouse_emit_touch(msc, ii, data + ii * 9 + 4); | ||
292 | |||
293 | /* We don't need an MT sync here because trackpad emits a | ||
294 | * BTN_TOUCH event in a new frame when all touches are released. | ||
295 | */ | ||
296 | if (msc->ntouches == 0) | ||
297 | msc->single_touch_id = NO_TOUCHES; | ||
298 | |||
258 | clicks = data[1]; | 299 | clicks = data[1]; |
300 | |||
301 | /* The following bits provide a device specific timestamp. They | ||
302 | * are unused here. | ||
303 | * | ||
304 | * ts = data[1] >> 6 | data[2] << 2 | data[3] << 10; | ||
305 | */ | ||
259 | break; | 306 | break; |
260 | case TOUCH_REPORT_ID: | 307 | case MOUSE_REPORT_ID: |
261 | /* Expect six bytes of prefix, and N*8 bytes of touch data. */ | 308 | /* Expect six bytes of prefix, and N*8 bytes of touch data. */ |
262 | if (size < 6 || ((size - 6) % 8) != 0) | 309 | if (size < 6 || ((size - 6) % 8) != 0) |
263 | return 0; | 310 | return 0; |
264 | ts = data[3] >> 6 | data[4] << 2 | data[5] << 10; | 311 | npoints = (size - 6) / 8; |
265 | msc->delta_time = (ts - msc->last_timestamp) & 0x3ffff; | 312 | msc->ntouches = 0; |
266 | msc->last_timestamp = ts; | 313 | for (ii = 0; ii < npoints; ii++) |
267 | msc->ntouches = (size - 6) / 8; | ||
268 | for (ii = 0; ii < msc->ntouches; ii++) | ||
269 | magicmouse_emit_touch(msc, ii, data + ii * 8 + 6); | 314 | magicmouse_emit_touch(msc, ii, data + ii * 8 + 6); |
270 | 315 | ||
271 | if (report_touches) { | 316 | if (report_touches && msc->ntouches == 0) |
272 | last_up = 1; | 317 | input_mt_sync(input); |
273 | for (ii = 0; ii < ARRAY_SIZE(msc->touches); ii++) { | ||
274 | if (msc->touches[ii].down) { | ||
275 | last_up = 0; | ||
276 | msc->touches[ii].down = 0; | ||
277 | } | ||
278 | } | ||
279 | if (last_up) { | ||
280 | input_mt_sync(input); | ||
281 | } | ||
282 | } | ||
283 | 318 | ||
284 | /* When emulating three-button mode, it is important | 319 | /* When emulating three-button mode, it is important |
285 | * to have the current touch information before | 320 | * to have the current touch information before |
@@ -288,68 +323,72 @@ static int magicmouse_raw_event(struct hid_device *hdev, | |||
288 | x = (int)(((data[3] & 0x0c) << 28) | (data[1] << 22)) >> 22; | 323 | x = (int)(((data[3] & 0x0c) << 28) | (data[1] << 22)) >> 22; |
289 | y = (int)(((data[3] & 0x30) << 26) | (data[2] << 22)) >> 22; | 324 | y = (int)(((data[3] & 0x30) << 26) | (data[2] << 22)) >> 22; |
290 | clicks = data[3]; | 325 | clicks = data[3]; |
326 | |||
327 | /* The following bits provide a device specific timestamp. They | ||
328 | * are unused here. | ||
329 | * | ||
330 | * ts = data[3] >> 6 | data[4] << 2 | data[5] << 10; | ||
331 | */ | ||
332 | break; | ||
333 | case DOUBLE_REPORT_ID: | ||
334 | /* Sometimes the trackpad sends two touch reports in one | ||
335 | * packet. | ||
336 | */ | ||
337 | magicmouse_raw_event(hdev, report, data + 2, data[1]); | ||
338 | magicmouse_raw_event(hdev, report, data + 2 + data[1], | ||
339 | size - 2 - data[1]); | ||
291 | break; | 340 | break; |
292 | case 0x20: /* Theoretically battery status (0-100), but I have | ||
293 | * never seen it -- maybe it is only upon request. | ||
294 | */ | ||
295 | case 0x60: /* Unknown, maybe laser on/off. */ | ||
296 | case 0x61: /* Laser reflection status change. | ||
297 | * data[1]: 0 = spotted, 1 = lost | ||
298 | */ | ||
299 | default: | 341 | default: |
300 | return 0; | 342 | return 0; |
301 | } | 343 | } |
302 | 344 | ||
303 | magicmouse_emit_buttons(msc, clicks & 3); | 345 | if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE) { |
304 | input_report_rel(input, REL_X, x); | 346 | magicmouse_emit_buttons(msc, clicks & 3); |
305 | input_report_rel(input, REL_Y, y); | 347 | input_report_rel(input, REL_X, x); |
348 | input_report_rel(input, REL_Y, y); | ||
349 | } else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */ | ||
350 | input_report_key(input, BTN_MOUSE, clicks & 1); | ||
351 | input_report_key(input, BTN_TOUCH, msc->ntouches > 0); | ||
352 | input_report_key(input, BTN_TOOL_FINGER, msc->ntouches == 1); | ||
353 | input_report_key(input, BTN_TOOL_DOUBLETAP, msc->ntouches == 2); | ||
354 | input_report_key(input, BTN_TOOL_TRIPLETAP, msc->ntouches == 3); | ||
355 | input_report_key(input, BTN_TOOL_QUADTAP, msc->ntouches == 4); | ||
356 | if (msc->single_touch_id >= 0) { | ||
357 | input_report_abs(input, ABS_X, | ||
358 | msc->touches[msc->single_touch_id].x); | ||
359 | input_report_abs(input, ABS_Y, | ||
360 | msc->touches[msc->single_touch_id].y); | ||
361 | } | ||
362 | } | ||
363 | |||
306 | input_sync(input); | 364 | input_sync(input); |
307 | return 1; | 365 | return 1; |
308 | } | 366 | } |
309 | 367 | ||
310 | static int magicmouse_input_open(struct input_dev *dev) | ||
311 | { | ||
312 | struct hid_device *hid = input_get_drvdata(dev); | ||
313 | |||
314 | return hid->ll_driver->open(hid); | ||
315 | } | ||
316 | |||
317 | static void magicmouse_input_close(struct input_dev *dev) | ||
318 | { | ||
319 | struct hid_device *hid = input_get_drvdata(dev); | ||
320 | |||
321 | hid->ll_driver->close(hid); | ||
322 | } | ||
323 | |||
324 | static void magicmouse_setup_input(struct input_dev *input, struct hid_device *hdev) | 368 | static void magicmouse_setup_input(struct input_dev *input, struct hid_device *hdev) |
325 | { | 369 | { |
326 | input_set_drvdata(input, hdev); | ||
327 | input->event = hdev->ll_driver->hidinput_input_event; | ||
328 | input->open = magicmouse_input_open; | ||
329 | input->close = magicmouse_input_close; | ||
330 | |||
331 | input->name = hdev->name; | ||
332 | input->phys = hdev->phys; | ||
333 | input->uniq = hdev->uniq; | ||
334 | input->id.bustype = hdev->bus; | ||
335 | input->id.vendor = hdev->vendor; | ||
336 | input->id.product = hdev->product; | ||
337 | input->id.version = hdev->version; | ||
338 | input->dev.parent = hdev->dev.parent; | ||
339 | |||
340 | __set_bit(EV_KEY, input->evbit); | 370 | __set_bit(EV_KEY, input->evbit); |
341 | __set_bit(BTN_LEFT, input->keybit); | 371 | |
342 | __set_bit(BTN_RIGHT, input->keybit); | 372 | if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE) { |
343 | if (emulate_3button) | 373 | __set_bit(BTN_LEFT, input->keybit); |
344 | __set_bit(BTN_MIDDLE, input->keybit); | 374 | __set_bit(BTN_RIGHT, input->keybit); |
345 | __set_bit(BTN_TOOL_FINGER, input->keybit); | 375 | if (emulate_3button) |
346 | 376 | __set_bit(BTN_MIDDLE, input->keybit); | |
347 | __set_bit(EV_REL, input->evbit); | 377 | |
348 | __set_bit(REL_X, input->relbit); | 378 | __set_bit(EV_REL, input->evbit); |
349 | __set_bit(REL_Y, input->relbit); | 379 | __set_bit(REL_X, input->relbit); |
350 | if (emulate_scroll_wheel) { | 380 | __set_bit(REL_Y, input->relbit); |
351 | __set_bit(REL_WHEEL, input->relbit); | 381 | if (emulate_scroll_wheel) { |
352 | __set_bit(REL_HWHEEL, input->relbit); | 382 | __set_bit(REL_WHEEL, input->relbit); |
383 | __set_bit(REL_HWHEEL, input->relbit); | ||
384 | } | ||
385 | } else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */ | ||
386 | __set_bit(BTN_MOUSE, input->keybit); | ||
387 | __set_bit(BTN_TOOL_FINGER, input->keybit); | ||
388 | __set_bit(BTN_TOOL_DOUBLETAP, input->keybit); | ||
389 | __set_bit(BTN_TOOL_TRIPLETAP, input->keybit); | ||
390 | __set_bit(BTN_TOOL_QUADTAP, input->keybit); | ||
391 | __set_bit(BTN_TOUCH, input->keybit); | ||
353 | } | 392 | } |
354 | 393 | ||
355 | if (report_touches) { | 394 | if (report_touches) { |
@@ -358,17 +397,29 @@ static void magicmouse_setup_input(struct input_dev *input, struct hid_device *h | |||
358 | input_set_abs_params(input, ABS_MT_TRACKING_ID, 0, 15, 0, 0); | 397 | input_set_abs_params(input, ABS_MT_TRACKING_ID, 0, 15, 0, 0); |
359 | input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, 255, 4, 0); | 398 | input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, 255, 4, 0); |
360 | input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0, 255, 4, 0); | 399 | input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0, 255, 4, 0); |
361 | input_set_abs_params(input, ABS_MT_ORIENTATION, -32, 31, 1, 0); | 400 | input_set_abs_params(input, ABS_MT_ORIENTATION, -31, 32, 1, 0); |
362 | input_set_abs_params(input, ABS_MT_POSITION_X, -1100, 1358, | 401 | |
363 | 4, 0); | ||
364 | /* Note: Touch Y position from the device is inverted relative | 402 | /* Note: Touch Y position from the device is inverted relative |
365 | * to how pointer motion is reported (and relative to how USB | 403 | * to how pointer motion is reported (and relative to how USB |
366 | * HID recommends the coordinates work). This driver keeps | 404 | * HID recommends the coordinates work). This driver keeps |
367 | * the origin at the same position, and just uses the additive | 405 | * the origin at the same position, and just uses the additive |
368 | * inverse of the reported Y. | 406 | * inverse of the reported Y. |
369 | */ | 407 | */ |
370 | input_set_abs_params(input, ABS_MT_POSITION_Y, -1589, 2047, | 408 | if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE) { |
371 | 4, 0); | 409 | input_set_abs_params(input, ABS_MT_POSITION_X, -1100, |
410 | 1358, 4, 0); | ||
411 | input_set_abs_params(input, ABS_MT_POSITION_Y, -1589, | ||
412 | 2047, 4, 0); | ||
413 | } else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */ | ||
414 | input_set_abs_params(input, ABS_X, -2909, 3167, 4, 0); | ||
415 | input_set_abs_params(input, ABS_Y, -2456, 2565, 4, 0); | ||
416 | input_set_abs_params(input, ABS_MT_POSITION_X, -2909, | ||
417 | 3167, 4, 0); | ||
418 | input_set_abs_params(input, ABS_MT_POSITION_Y, -2456, | ||
419 | 2565, 4, 0); | ||
420 | } | ||
421 | |||
422 | input_set_events_per_packet(input, 60); | ||
372 | } | 423 | } |
373 | 424 | ||
374 | if (report_undeciphered) { | 425 | if (report_undeciphered) { |
@@ -377,19 +428,34 @@ static void magicmouse_setup_input(struct input_dev *input, struct hid_device *h | |||
377 | } | 428 | } |
378 | } | 429 | } |
379 | 430 | ||
431 | static int magicmouse_input_mapping(struct hid_device *hdev, | ||
432 | struct hid_input *hi, struct hid_field *field, | ||
433 | struct hid_usage *usage, unsigned long **bit, int *max) | ||
434 | { | ||
435 | struct magicmouse_sc *msc = hid_get_drvdata(hdev); | ||
436 | |||
437 | if (!msc->input) | ||
438 | msc->input = hi->input; | ||
439 | |||
440 | /* Magic Trackpad does not give relative data after switching to MT */ | ||
441 | if (hi->input->id.product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD && | ||
442 | field->flags & HID_MAIN_ITEM_RELATIVE) | ||
443 | return -1; | ||
444 | |||
445 | return 0; | ||
446 | } | ||
447 | |||
380 | static int magicmouse_probe(struct hid_device *hdev, | 448 | static int magicmouse_probe(struct hid_device *hdev, |
381 | const struct hid_device_id *id) | 449 | const struct hid_device_id *id) |
382 | { | 450 | { |
383 | __u8 feature_1[] = { 0xd7, 0x01 }; | 451 | __u8 feature[] = { 0xd7, 0x01 }; |
384 | __u8 feature_2[] = { 0xf8, 0x01, 0x32 }; | ||
385 | struct input_dev *input; | ||
386 | struct magicmouse_sc *msc; | 452 | struct magicmouse_sc *msc; |
387 | struct hid_report *report; | 453 | struct hid_report *report; |
388 | int ret; | 454 | int ret; |
389 | 455 | ||
390 | msc = kzalloc(sizeof(*msc), GFP_KERNEL); | 456 | msc = kzalloc(sizeof(*msc), GFP_KERNEL); |
391 | if (msc == NULL) { | 457 | if (msc == NULL) { |
392 | dev_err(&hdev->dev, "can't alloc magicmouse descriptor\n"); | 458 | hid_err(hdev, "can't alloc magicmouse descriptor\n"); |
393 | return -ENOMEM; | 459 | return -ENOMEM; |
394 | } | 460 | } |
395 | 461 | ||
@@ -398,62 +464,51 @@ static int magicmouse_probe(struct hid_device *hdev, | |||
398 | msc->quirks = id->driver_data; | 464 | msc->quirks = id->driver_data; |
399 | hid_set_drvdata(hdev, msc); | 465 | hid_set_drvdata(hdev, msc); |
400 | 466 | ||
467 | msc->single_touch_id = NO_TOUCHES; | ||
468 | |||
401 | ret = hid_parse(hdev); | 469 | ret = hid_parse(hdev); |
402 | if (ret) { | 470 | if (ret) { |
403 | dev_err(&hdev->dev, "magicmouse hid parse failed\n"); | 471 | hid_err(hdev, "magicmouse hid parse failed\n"); |
404 | goto err_free; | 472 | goto err_free; |
405 | } | 473 | } |
406 | 474 | ||
407 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); | 475 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); |
408 | if (ret) { | 476 | if (ret) { |
409 | dev_err(&hdev->dev, "magicmouse hw start failed\n"); | 477 | hid_err(hdev, "magicmouse hw start failed\n"); |
410 | goto err_free; | 478 | goto err_free; |
411 | } | 479 | } |
412 | 480 | ||
413 | /* we are handling the input ourselves */ | 481 | /* We do this after hid-input is done parsing reports so that |
414 | hidinput_disconnect(hdev); | 482 | * hid-input uses the most natural button and axis IDs. |
483 | */ | ||
484 | if (msc->input) | ||
485 | magicmouse_setup_input(msc->input, hdev); | ||
486 | |||
487 | if (id->product == USB_DEVICE_ID_APPLE_MAGICMOUSE) | ||
488 | report = hid_register_report(hdev, HID_INPUT_REPORT, | ||
489 | MOUSE_REPORT_ID); | ||
490 | else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */ | ||
491 | report = hid_register_report(hdev, HID_INPUT_REPORT, | ||
492 | TRACKPAD_REPORT_ID); | ||
493 | report = hid_register_report(hdev, HID_INPUT_REPORT, | ||
494 | DOUBLE_REPORT_ID); | ||
495 | } | ||
415 | 496 | ||
416 | report = hid_register_report(hdev, HID_INPUT_REPORT, TOUCH_REPORT_ID); | ||
417 | if (!report) { | 497 | if (!report) { |
418 | dev_err(&hdev->dev, "unable to register touch report\n"); | 498 | hid_err(hdev, "unable to register touch report\n"); |
419 | ret = -ENOMEM; | 499 | ret = -ENOMEM; |
420 | goto err_stop_hw; | 500 | goto err_stop_hw; |
421 | } | 501 | } |
422 | report->size = 6; | 502 | report->size = 6; |
423 | 503 | ||
424 | ret = hdev->hid_output_raw_report(hdev, feature_1, sizeof(feature_1), | 504 | ret = hdev->hid_output_raw_report(hdev, feature, sizeof(feature), |
425 | HID_FEATURE_REPORT); | 505 | HID_FEATURE_REPORT); |
426 | if (ret != sizeof(feature_1)) { | 506 | if (ret != sizeof(feature)) { |
427 | dev_err(&hdev->dev, "unable to request touch data (1:%d)\n", | 507 | hid_err(hdev, "unable to request touch data (%d)\n", ret); |
428 | ret); | ||
429 | goto err_stop_hw; | ||
430 | } | ||
431 | ret = hdev->hid_output_raw_report(hdev, feature_2, | ||
432 | sizeof(feature_2), HID_FEATURE_REPORT); | ||
433 | if (ret != sizeof(feature_2)) { | ||
434 | dev_err(&hdev->dev, "unable to request touch data (2:%d)\n", | ||
435 | ret); | ||
436 | goto err_stop_hw; | 508 | goto err_stop_hw; |
437 | } | 509 | } |
438 | 510 | ||
439 | input = input_allocate_device(); | ||
440 | if (!input) { | ||
441 | dev_err(&hdev->dev, "can't alloc input device\n"); | ||
442 | ret = -ENOMEM; | ||
443 | goto err_stop_hw; | ||
444 | } | ||
445 | magicmouse_setup_input(input, hdev); | ||
446 | |||
447 | ret = input_register_device(input); | ||
448 | if (ret) { | ||
449 | dev_err(&hdev->dev, "input device registration failed\n"); | ||
450 | goto err_input; | ||
451 | } | ||
452 | msc->input = input; | ||
453 | |||
454 | return 0; | 511 | return 0; |
455 | err_input: | ||
456 | input_free_device(input); | ||
457 | err_stop_hw: | 512 | err_stop_hw: |
458 | hid_hw_stop(hdev); | 513 | hid_hw_stop(hdev); |
459 | err_free: | 514 | err_free: |
@@ -466,13 +521,14 @@ static void magicmouse_remove(struct hid_device *hdev) | |||
466 | struct magicmouse_sc *msc = hid_get_drvdata(hdev); | 521 | struct magicmouse_sc *msc = hid_get_drvdata(hdev); |
467 | 522 | ||
468 | hid_hw_stop(hdev); | 523 | hid_hw_stop(hdev); |
469 | input_unregister_device(msc->input); | ||
470 | kfree(msc); | 524 | kfree(msc); |
471 | } | 525 | } |
472 | 526 | ||
473 | static const struct hid_device_id magic_mice[] = { | 527 | static const struct hid_device_id magic_mice[] = { |
474 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICMOUSE), | 528 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, |
475 | .driver_data = 0 }, | 529 | USB_DEVICE_ID_APPLE_MAGICMOUSE), .driver_data = 0 }, |
530 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, | ||
531 | USB_DEVICE_ID_APPLE_MAGICTRACKPAD), .driver_data = 0 }, | ||
476 | { } | 532 | { } |
477 | }; | 533 | }; |
478 | MODULE_DEVICE_TABLE(hid, magic_mice); | 534 | MODULE_DEVICE_TABLE(hid, magic_mice); |
@@ -483,6 +539,7 @@ static struct hid_driver magicmouse_driver = { | |||
483 | .probe = magicmouse_probe, | 539 | .probe = magicmouse_probe, |
484 | .remove = magicmouse_remove, | 540 | .remove = magicmouse_remove, |
485 | .raw_event = magicmouse_raw_event, | 541 | .raw_event = magicmouse_raw_event, |
542 | .input_mapping = magicmouse_input_mapping, | ||
486 | }; | 543 | }; |
487 | 544 | ||
488 | static int __init magicmouse_init(void) | 545 | static int __init magicmouse_init(void) |
@@ -491,7 +548,7 @@ static int __init magicmouse_init(void) | |||
491 | 548 | ||
492 | ret = hid_register_driver(&magicmouse_driver); | 549 | ret = hid_register_driver(&magicmouse_driver); |
493 | if (ret) | 550 | if (ret) |
494 | printk(KERN_ERR "can't register magicmouse driver\n"); | 551 | pr_err("can't register magicmouse driver\n"); |
495 | 552 | ||
496 | return ret; | 553 | return ret; |
497 | } | 554 | } |
diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c index 359cc447c6c6..0f6fc54dc196 100644 --- a/drivers/hid/hid-microsoft.c +++ b/drivers/hid/hid-microsoft.c | |||
@@ -33,18 +33,18 @@ | |||
33 | * Microsoft Wireless Desktop Receiver (Model 1028) has | 33 | * Microsoft Wireless Desktop Receiver (Model 1028) has |
34 | * 'Usage Min/Max' where it ought to have 'Physical Min/Max' | 34 | * 'Usage Min/Max' where it ought to have 'Physical Min/Max' |
35 | */ | 35 | */ |
36 | static void ms_report_fixup(struct hid_device *hdev, __u8 *rdesc, | 36 | static __u8 *ms_report_fixup(struct hid_device *hdev, __u8 *rdesc, |
37 | unsigned int rsize) | 37 | unsigned int *rsize) |
38 | { | 38 | { |
39 | unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); | 39 | unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); |
40 | 40 | ||
41 | if ((quirks & MS_RDESC) && rsize == 571 && rdesc[557] == 0x19 && | 41 | if ((quirks & MS_RDESC) && *rsize == 571 && rdesc[557] == 0x19 && |
42 | rdesc[559] == 0x29) { | 42 | rdesc[559] == 0x29) { |
43 | dev_info(&hdev->dev, "fixing up Microsoft Wireless Receiver " | 43 | hid_info(hdev, "fixing up Microsoft Wireless Receiver Model 1028 report descriptor\n"); |
44 | "Model 1028 report descriptor\n"); | ||
45 | rdesc[557] = 0x35; | 44 | rdesc[557] = 0x35; |
46 | rdesc[559] = 0x45; | 45 | rdesc[559] = 0x45; |
47 | } | 46 | } |
47 | return rdesc; | ||
48 | } | 48 | } |
49 | 49 | ||
50 | #define ms_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ | 50 | #define ms_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ |
@@ -154,14 +154,14 @@ static int ms_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
154 | 154 | ||
155 | ret = hid_parse(hdev); | 155 | ret = hid_parse(hdev); |
156 | if (ret) { | 156 | if (ret) { |
157 | dev_err(&hdev->dev, "parse failed\n"); | 157 | hid_err(hdev, "parse failed\n"); |
158 | goto err_free; | 158 | goto err_free; |
159 | } | 159 | } |
160 | 160 | ||
161 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT | ((quirks & MS_HIDINPUT) ? | 161 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT | ((quirks & MS_HIDINPUT) ? |
162 | HID_CONNECT_HIDINPUT_FORCE : 0)); | 162 | HID_CONNECT_HIDINPUT_FORCE : 0)); |
163 | if (ret) { | 163 | if (ret) { |
164 | dev_err(&hdev->dev, "hw start failed\n"); | 164 | hid_err(hdev, "hw start failed\n"); |
165 | goto err_free; | 165 | goto err_free; |
166 | } | 166 | } |
167 | 167 | ||
diff --git a/drivers/hid/hid-monterey.c b/drivers/hid/hid-monterey.c index 2cd05aa244b9..dedf757781ae 100644 --- a/drivers/hid/hid-monterey.c +++ b/drivers/hid/hid-monterey.c | |||
@@ -22,14 +22,14 @@ | |||
22 | 22 | ||
23 | #include "hid-ids.h" | 23 | #include "hid-ids.h" |
24 | 24 | ||
25 | static void mr_report_fixup(struct hid_device *hdev, __u8 *rdesc, | 25 | static __u8 *mr_report_fixup(struct hid_device *hdev, __u8 *rdesc, |
26 | unsigned int rsize) | 26 | unsigned int *rsize) |
27 | { | 27 | { |
28 | if (rsize >= 30 && rdesc[29] == 0x05 && rdesc[30] == 0x09) { | 28 | if (*rsize >= 30 && rdesc[29] == 0x05 && rdesc[30] == 0x09) { |
29 | dev_info(&hdev->dev, "fixing up button/consumer in HID report " | 29 | hid_info(hdev, "fixing up button/consumer in HID report descriptor\n"); |
30 | "descriptor\n"); | ||
31 | rdesc[30] = 0x0c; | 30 | rdesc[30] = 0x0c; |
32 | } | 31 | } |
32 | return rdesc; | ||
33 | } | 33 | } |
34 | 34 | ||
35 | #define mr_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ | 35 | #define mr_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ |
diff --git a/drivers/hid/hid-mosart.c b/drivers/hid/hid-mosart.c deleted file mode 100644 index ac5421d568f1..000000000000 --- a/drivers/hid/hid-mosart.c +++ /dev/null | |||
@@ -1,275 +0,0 @@ | |||
1 | /* | ||
2 | * HID driver for the multitouch panel on the ASUS EeePC T91MT | ||
3 | * | ||
4 | * Copyright (c) 2009-2010 Stephane Chatty <chatty@enac.fr> | ||
5 | * Copyright (c) 2010 Teemu Tuominen <teemu.tuominen@cybercom.com> | ||
6 | * | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the Free | ||
12 | * Software Foundation; either version 2 of the License, or (at your option) | ||
13 | * any later version. | ||
14 | */ | ||
15 | |||
16 | #include <linux/device.h> | ||
17 | #include <linux/hid.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/usb.h> | ||
21 | #include "usbhid/usbhid.h" | ||
22 | |||
23 | MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>"); | ||
24 | MODULE_DESCRIPTION("MosArt dual-touch panel"); | ||
25 | MODULE_LICENSE("GPL"); | ||
26 | |||
27 | #include "hid-ids.h" | ||
28 | |||
29 | struct mosart_data { | ||
30 | __u16 x, y; | ||
31 | __u8 id; | ||
32 | bool valid; /* valid finger data, or just placeholder? */ | ||
33 | bool first; /* is this the first finger in this frame? */ | ||
34 | bool activity_now; /* at least one active finger in this frame? */ | ||
35 | bool activity; /* at least one active finger previously? */ | ||
36 | }; | ||
37 | |||
38 | static int mosart_input_mapping(struct hid_device *hdev, struct hid_input *hi, | ||
39 | struct hid_field *field, struct hid_usage *usage, | ||
40 | unsigned long **bit, int *max) | ||
41 | { | ||
42 | switch (usage->hid & HID_USAGE_PAGE) { | ||
43 | |||
44 | case HID_UP_GENDESK: | ||
45 | switch (usage->hid) { | ||
46 | case HID_GD_X: | ||
47 | hid_map_usage(hi, usage, bit, max, | ||
48 | EV_ABS, ABS_MT_POSITION_X); | ||
49 | /* touchscreen emulation */ | ||
50 | input_set_abs_params(hi->input, ABS_X, | ||
51 | field->logical_minimum, | ||
52 | field->logical_maximum, 0, 0); | ||
53 | return 1; | ||
54 | case HID_GD_Y: | ||
55 | hid_map_usage(hi, usage, bit, max, | ||
56 | EV_ABS, ABS_MT_POSITION_Y); | ||
57 | /* touchscreen emulation */ | ||
58 | input_set_abs_params(hi->input, ABS_Y, | ||
59 | field->logical_minimum, | ||
60 | field->logical_maximum, 0, 0); | ||
61 | return 1; | ||
62 | } | ||
63 | return 0; | ||
64 | |||
65 | case HID_UP_DIGITIZER: | ||
66 | switch (usage->hid) { | ||
67 | case HID_DG_CONFIDENCE: | ||
68 | case HID_DG_TIPSWITCH: | ||
69 | case HID_DG_INPUTMODE: | ||
70 | case HID_DG_DEVICEINDEX: | ||
71 | case HID_DG_CONTACTCOUNT: | ||
72 | case HID_DG_CONTACTMAX: | ||
73 | case HID_DG_TIPPRESSURE: | ||
74 | case HID_DG_WIDTH: | ||
75 | case HID_DG_HEIGHT: | ||
76 | return -1; | ||
77 | case HID_DG_INRANGE: | ||
78 | /* touchscreen emulation */ | ||
79 | hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); | ||
80 | return 1; | ||
81 | |||
82 | case HID_DG_CONTACTID: | ||
83 | hid_map_usage(hi, usage, bit, max, | ||
84 | EV_ABS, ABS_MT_TRACKING_ID); | ||
85 | return 1; | ||
86 | |||
87 | } | ||
88 | return 0; | ||
89 | |||
90 | case 0xff000000: | ||
91 | /* ignore HID features */ | ||
92 | return -1; | ||
93 | } | ||
94 | |||
95 | return 0; | ||
96 | } | ||
97 | |||
98 | static int mosart_input_mapped(struct hid_device *hdev, struct hid_input *hi, | ||
99 | struct hid_field *field, struct hid_usage *usage, | ||
100 | unsigned long **bit, int *max) | ||
101 | { | ||
102 | if (usage->type == EV_KEY || usage->type == EV_ABS) | ||
103 | clear_bit(usage->code, *bit); | ||
104 | |||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | /* | ||
109 | * this function is called when a whole finger has been parsed, | ||
110 | * so that it can decide what to send to the input layer. | ||
111 | */ | ||
112 | static void mosart_filter_event(struct mosart_data *td, struct input_dev *input) | ||
113 | { | ||
114 | td->first = !td->first; /* touchscreen emulation */ | ||
115 | |||
116 | if (!td->valid) { | ||
117 | /* | ||
118 | * touchscreen emulation: if no finger in this frame is valid | ||
119 | * and there previously was finger activity, this is a release | ||
120 | */ | ||
121 | if (!td->first && !td->activity_now && td->activity) { | ||
122 | input_event(input, EV_KEY, BTN_TOUCH, 0); | ||
123 | td->activity = false; | ||
124 | } | ||
125 | return; | ||
126 | } | ||
127 | |||
128 | input_event(input, EV_ABS, ABS_MT_TRACKING_ID, td->id); | ||
129 | input_event(input, EV_ABS, ABS_MT_POSITION_X, td->x); | ||
130 | input_event(input, EV_ABS, ABS_MT_POSITION_Y, td->y); | ||
131 | |||
132 | input_mt_sync(input); | ||
133 | td->valid = false; | ||
134 | |||
135 | /* touchscreen emulation: if first active finger in this frame... */ | ||
136 | if (!td->activity_now) { | ||
137 | /* if there was no previous activity, emit touch event */ | ||
138 | if (!td->activity) { | ||
139 | input_event(input, EV_KEY, BTN_TOUCH, 1); | ||
140 | td->activity = true; | ||
141 | } | ||
142 | td->activity_now = true; | ||
143 | /* and in any case this is our preferred finger */ | ||
144 | input_event(input, EV_ABS, ABS_X, td->x); | ||
145 | input_event(input, EV_ABS, ABS_Y, td->y); | ||
146 | } | ||
147 | } | ||
148 | |||
149 | |||
150 | static int mosart_event(struct hid_device *hid, struct hid_field *field, | ||
151 | struct hid_usage *usage, __s32 value) | ||
152 | { | ||
153 | struct mosart_data *td = hid_get_drvdata(hid); | ||
154 | |||
155 | if (hid->claimed & HID_CLAIMED_INPUT) { | ||
156 | struct input_dev *input = field->hidinput->input; | ||
157 | switch (usage->hid) { | ||
158 | case HID_DG_INRANGE: | ||
159 | td->valid = !!value; | ||
160 | break; | ||
161 | case HID_GD_X: | ||
162 | td->x = value; | ||
163 | break; | ||
164 | case HID_GD_Y: | ||
165 | td->y = value; | ||
166 | mosart_filter_event(td, input); | ||
167 | break; | ||
168 | case HID_DG_CONTACTID: | ||
169 | td->id = value; | ||
170 | break; | ||
171 | case HID_DG_CONTACTCOUNT: | ||
172 | /* touch emulation: this is the last field in a frame */ | ||
173 | td->first = false; | ||
174 | td->activity_now = false; | ||
175 | break; | ||
176 | case HID_DG_CONFIDENCE: | ||
177 | case HID_DG_TIPSWITCH: | ||
178 | /* avoid interference from generic hidinput handling */ | ||
179 | break; | ||
180 | |||
181 | default: | ||
182 | /* fallback to the generic hidinput handling */ | ||
183 | return 0; | ||
184 | } | ||
185 | } | ||
186 | |||
187 | /* we have handled the hidinput part, now remains hiddev */ | ||
188 | if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event) | ||
189 | hid->hiddev_hid_event(hid, field, usage, value); | ||
190 | |||
191 | return 1; | ||
192 | } | ||
193 | |||
194 | static int mosart_probe(struct hid_device *hdev, const struct hid_device_id *id) | ||
195 | { | ||
196 | int ret; | ||
197 | struct mosart_data *td; | ||
198 | |||
199 | |||
200 | td = kmalloc(sizeof(struct mosart_data), GFP_KERNEL); | ||
201 | if (!td) { | ||
202 | dev_err(&hdev->dev, "cannot allocate MosArt data\n"); | ||
203 | return -ENOMEM; | ||
204 | } | ||
205 | td->valid = false; | ||
206 | td->activity = false; | ||
207 | td->activity_now = false; | ||
208 | td->first = false; | ||
209 | hid_set_drvdata(hdev, td); | ||
210 | |||
211 | /* currently, it's better to have one evdev device only */ | ||
212 | #if 0 | ||
213 | hdev->quirks |= HID_QUIRK_MULTI_INPUT; | ||
214 | #endif | ||
215 | |||
216 | ret = hid_parse(hdev); | ||
217 | if (ret == 0) | ||
218 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); | ||
219 | |||
220 | if (ret == 0) { | ||
221 | struct hid_report_enum *re = hdev->report_enum | ||
222 | + HID_FEATURE_REPORT; | ||
223 | struct hid_report *r = re->report_id_hash[7]; | ||
224 | |||
225 | r->field[0]->value[0] = 0x02; | ||
226 | usbhid_submit_report(hdev, r, USB_DIR_OUT); | ||
227 | } else | ||
228 | kfree(td); | ||
229 | |||
230 | return ret; | ||
231 | } | ||
232 | |||
233 | static void mosart_remove(struct hid_device *hdev) | ||
234 | { | ||
235 | hid_hw_stop(hdev); | ||
236 | kfree(hid_get_drvdata(hdev)); | ||
237 | hid_set_drvdata(hdev, NULL); | ||
238 | } | ||
239 | |||
240 | static const struct hid_device_id mosart_devices[] = { | ||
241 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_T91MT) }, | ||
242 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO) }, | ||
243 | { } | ||
244 | }; | ||
245 | MODULE_DEVICE_TABLE(hid, mosart_devices); | ||
246 | |||
247 | static const struct hid_usage_id mosart_grabbed_usages[] = { | ||
248 | { HID_ANY_ID, HID_ANY_ID, HID_ANY_ID }, | ||
249 | { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1} | ||
250 | }; | ||
251 | |||
252 | static struct hid_driver mosart_driver = { | ||
253 | .name = "mosart", | ||
254 | .id_table = mosart_devices, | ||
255 | .probe = mosart_probe, | ||
256 | .remove = mosart_remove, | ||
257 | .input_mapping = mosart_input_mapping, | ||
258 | .input_mapped = mosart_input_mapped, | ||
259 | .usage_table = mosart_grabbed_usages, | ||
260 | .event = mosart_event, | ||
261 | }; | ||
262 | |||
263 | static int __init mosart_init(void) | ||
264 | { | ||
265 | return hid_register_driver(&mosart_driver); | ||
266 | } | ||
267 | |||
268 | static void __exit mosart_exit(void) | ||
269 | { | ||
270 | hid_unregister_driver(&mosart_driver); | ||
271 | } | ||
272 | |||
273 | module_init(mosart_init); | ||
274 | module_exit(mosart_exit); | ||
275 | |||
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c new file mode 100644 index 000000000000..62cac4dc3b62 --- /dev/null +++ b/drivers/hid/hid-multitouch.c | |||
@@ -0,0 +1,766 @@ | |||
1 | /* | ||
2 | * HID driver for multitouch panels | ||
3 | * | ||
4 | * Copyright (c) 2010-2011 Stephane Chatty <chatty@enac.fr> | ||
5 | * Copyright (c) 2010-2011 Benjamin Tissoires <benjamin.tissoires@gmail.com> | ||
6 | * Copyright (c) 2010-2011 Ecole Nationale de l'Aviation Civile, France | ||
7 | * | ||
8 | * This code is partly based on hid-egalax.c: | ||
9 | * | ||
10 | * Copyright (c) 2010 Stephane Chatty <chatty@enac.fr> | ||
11 | * Copyright (c) 2010 Henrik Rydberg <rydberg@euromail.se> | ||
12 | * Copyright (c) 2010 Canonical, Ltd. | ||
13 | * | ||
14 | * This code is partly based on hid-3m-pct.c: | ||
15 | * | ||
16 | * Copyright (c) 2009-2010 Stephane Chatty <chatty@enac.fr> | ||
17 | * Copyright (c) 2010 Henrik Rydberg <rydberg@euromail.se> | ||
18 | * Copyright (c) 2010 Canonical, Ltd. | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | /* | ||
23 | * This program is free software; you can redistribute it and/or modify it | ||
24 | * under the terms of the GNU General Public License as published by the Free | ||
25 | * Software Foundation; either version 2 of the License, or (at your option) | ||
26 | * any later version. | ||
27 | */ | ||
28 | |||
29 | #include <linux/device.h> | ||
30 | #include <linux/hid.h> | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/slab.h> | ||
33 | #include <linux/usb.h> | ||
34 | #include <linux/input/mt.h> | ||
35 | #include "usbhid/usbhid.h" | ||
36 | |||
37 | |||
38 | MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>"); | ||
39 | MODULE_AUTHOR("Benjamin Tissoires <benjamin.tissoires@gmail.com>"); | ||
40 | MODULE_DESCRIPTION("HID multitouch panels"); | ||
41 | MODULE_LICENSE("GPL"); | ||
42 | |||
43 | #include "hid-ids.h" | ||
44 | |||
45 | /* quirks to control the device */ | ||
46 | #define MT_QUIRK_NOT_SEEN_MEANS_UP (1 << 0) | ||
47 | #define MT_QUIRK_SLOT_IS_CONTACTID (1 << 1) | ||
48 | #define MT_QUIRK_CYPRESS (1 << 2) | ||
49 | #define MT_QUIRK_SLOT_IS_CONTACTNUMBER (1 << 3) | ||
50 | #define MT_QUIRK_VALID_IS_INRANGE (1 << 4) | ||
51 | #define MT_QUIRK_VALID_IS_CONFIDENCE (1 << 5) | ||
52 | #define MT_QUIRK_EGALAX_XYZ_FIXUP (1 << 6) | ||
53 | #define MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE (1 << 7) | ||
54 | |||
55 | struct mt_slot { | ||
56 | __s32 x, y, p, w, h; | ||
57 | __s32 contactid; /* the device ContactID assigned to this slot */ | ||
58 | bool touch_state; /* is the touch valid? */ | ||
59 | bool seen_in_this_frame;/* has this slot been updated */ | ||
60 | }; | ||
61 | |||
62 | struct mt_device { | ||
63 | struct mt_slot curdata; /* placeholder of incoming data */ | ||
64 | struct mt_class *mtclass; /* our mt device class */ | ||
65 | unsigned last_field_index; /* last field index of the report */ | ||
66 | unsigned last_slot_field; /* the last field of a slot */ | ||
67 | int last_mt_collection; /* last known mt-related collection */ | ||
68 | __s8 inputmode; /* InputMode HID feature, -1 if non-existent */ | ||
69 | __u8 num_received; /* how many contacts we received */ | ||
70 | __u8 num_expected; /* expected last contact index */ | ||
71 | __u8 maxcontacts; | ||
72 | bool curvalid; /* is the current contact valid? */ | ||
73 | struct mt_slot *slots; | ||
74 | }; | ||
75 | |||
76 | struct mt_class { | ||
77 | __s32 name; /* MT_CLS */ | ||
78 | __s32 quirks; | ||
79 | __s32 sn_move; /* Signal/noise ratio for move events */ | ||
80 | __s32 sn_width; /* Signal/noise ratio for width events */ | ||
81 | __s32 sn_height; /* Signal/noise ratio for height events */ | ||
82 | __s32 sn_pressure; /* Signal/noise ratio for pressure events */ | ||
83 | __u8 maxcontacts; | ||
84 | }; | ||
85 | |||
86 | /* classes of device behavior */ | ||
87 | #define MT_CLS_DEFAULT 0x0001 | ||
88 | |||
89 | #define MT_CLS_CONFIDENCE 0x0002 | ||
90 | #define MT_CLS_CONFIDENCE_MINUS_ONE 0x0003 | ||
91 | #define MT_CLS_DUAL_INRANGE_CONTACTID 0x0004 | ||
92 | #define MT_CLS_DUAL_INRANGE_CONTACTNUMBER 0x0005 | ||
93 | #define MT_CLS_DUAL_NSMU_CONTACTID 0x0006 | ||
94 | |||
95 | /* vendor specific classes */ | ||
96 | #define MT_CLS_3M 0x0101 | ||
97 | #define MT_CLS_CYPRESS 0x0102 | ||
98 | #define MT_CLS_EGALAX 0x0103 | ||
99 | |||
100 | #define MT_DEFAULT_MAXCONTACT 10 | ||
101 | |||
102 | /* | ||
103 | * these device-dependent functions determine what slot corresponds | ||
104 | * to a valid contact that was just read. | ||
105 | */ | ||
106 | |||
107 | static int cypress_compute_slot(struct mt_device *td) | ||
108 | { | ||
109 | if (td->curdata.contactid != 0 || td->num_received == 0) | ||
110 | return td->curdata.contactid; | ||
111 | else | ||
112 | return -1; | ||
113 | } | ||
114 | |||
115 | static int find_slot_from_contactid(struct mt_device *td) | ||
116 | { | ||
117 | int i; | ||
118 | for (i = 0; i < td->maxcontacts; ++i) { | ||
119 | if (td->slots[i].contactid == td->curdata.contactid && | ||
120 | td->slots[i].touch_state) | ||
121 | return i; | ||
122 | } | ||
123 | for (i = 0; i < td->maxcontacts; ++i) { | ||
124 | if (!td->slots[i].seen_in_this_frame && | ||
125 | !td->slots[i].touch_state) | ||
126 | return i; | ||
127 | } | ||
128 | /* should not occurs. If this happens that means | ||
129 | * that the device sent more touches that it says | ||
130 | * in the report descriptor. It is ignored then. */ | ||
131 | return -1; | ||
132 | } | ||
133 | |||
134 | struct mt_class mt_classes[] = { | ||
135 | { .name = MT_CLS_DEFAULT, | ||
136 | .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP }, | ||
137 | { .name = MT_CLS_CONFIDENCE, | ||
138 | .quirks = MT_QUIRK_VALID_IS_CONFIDENCE }, | ||
139 | { .name = MT_CLS_CONFIDENCE_MINUS_ONE, | ||
140 | .quirks = MT_QUIRK_VALID_IS_CONFIDENCE | | ||
141 | MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE }, | ||
142 | { .name = MT_CLS_DUAL_INRANGE_CONTACTID, | ||
143 | .quirks = MT_QUIRK_VALID_IS_INRANGE | | ||
144 | MT_QUIRK_SLOT_IS_CONTACTID, | ||
145 | .maxcontacts = 2 }, | ||
146 | { .name = MT_CLS_DUAL_INRANGE_CONTACTNUMBER, | ||
147 | .quirks = MT_QUIRK_VALID_IS_INRANGE | | ||
148 | MT_QUIRK_SLOT_IS_CONTACTNUMBER, | ||
149 | .maxcontacts = 2 }, | ||
150 | { .name = MT_CLS_DUAL_NSMU_CONTACTID, | ||
151 | .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP | | ||
152 | MT_QUIRK_SLOT_IS_CONTACTID, | ||
153 | .maxcontacts = 2 }, | ||
154 | |||
155 | /* | ||
156 | * vendor specific classes | ||
157 | */ | ||
158 | { .name = MT_CLS_3M, | ||
159 | .quirks = MT_QUIRK_VALID_IS_CONFIDENCE | | ||
160 | MT_QUIRK_SLOT_IS_CONTACTID, | ||
161 | .sn_move = 2048, | ||
162 | .sn_width = 128, | ||
163 | .sn_height = 128 }, | ||
164 | { .name = MT_CLS_CYPRESS, | ||
165 | .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP | | ||
166 | MT_QUIRK_CYPRESS, | ||
167 | .maxcontacts = 10 }, | ||
168 | { .name = MT_CLS_EGALAX, | ||
169 | .quirks = MT_QUIRK_SLOT_IS_CONTACTID | | ||
170 | MT_QUIRK_VALID_IS_INRANGE | | ||
171 | MT_QUIRK_EGALAX_XYZ_FIXUP, | ||
172 | .maxcontacts = 2, | ||
173 | .sn_move = 4096, | ||
174 | .sn_pressure = 32, | ||
175 | }, | ||
176 | |||
177 | { } | ||
178 | }; | ||
179 | |||
180 | static void mt_feature_mapping(struct hid_device *hdev, | ||
181 | struct hid_field *field, struct hid_usage *usage) | ||
182 | { | ||
183 | struct mt_device *td = hid_get_drvdata(hdev); | ||
184 | |||
185 | switch (usage->hid) { | ||
186 | case HID_DG_INPUTMODE: | ||
187 | td->inputmode = field->report->id; | ||
188 | break; | ||
189 | case HID_DG_CONTACTMAX: | ||
190 | td->maxcontacts = field->value[0]; | ||
191 | if (td->mtclass->maxcontacts) | ||
192 | /* check if the maxcontacts is given by the class */ | ||
193 | td->maxcontacts = td->mtclass->maxcontacts; | ||
194 | |||
195 | break; | ||
196 | } | ||
197 | } | ||
198 | |||
199 | static void set_abs(struct input_dev *input, unsigned int code, | ||
200 | struct hid_field *field, int snratio) | ||
201 | { | ||
202 | int fmin = field->logical_minimum; | ||
203 | int fmax = field->logical_maximum; | ||
204 | int fuzz = snratio ? (fmax - fmin) / snratio : 0; | ||
205 | input_set_abs_params(input, code, fmin, fmax, fuzz, 0); | ||
206 | } | ||
207 | |||
208 | static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, | ||
209 | struct hid_field *field, struct hid_usage *usage, | ||
210 | unsigned long **bit, int *max) | ||
211 | { | ||
212 | struct mt_device *td = hid_get_drvdata(hdev); | ||
213 | struct mt_class *cls = td->mtclass; | ||
214 | __s32 quirks = cls->quirks; | ||
215 | |||
216 | switch (usage->hid & HID_USAGE_PAGE) { | ||
217 | |||
218 | case HID_UP_GENDESK: | ||
219 | switch (usage->hid) { | ||
220 | case HID_GD_X: | ||
221 | if (quirks & MT_QUIRK_EGALAX_XYZ_FIXUP) | ||
222 | field->logical_maximum = 32760; | ||
223 | hid_map_usage(hi, usage, bit, max, | ||
224 | EV_ABS, ABS_MT_POSITION_X); | ||
225 | set_abs(hi->input, ABS_MT_POSITION_X, field, | ||
226 | cls->sn_move); | ||
227 | /* touchscreen emulation */ | ||
228 | set_abs(hi->input, ABS_X, field, cls->sn_move); | ||
229 | if (td->last_mt_collection == usage->collection_index) { | ||
230 | td->last_slot_field = usage->hid; | ||
231 | td->last_field_index = field->index; | ||
232 | } | ||
233 | return 1; | ||
234 | case HID_GD_Y: | ||
235 | if (quirks & MT_QUIRK_EGALAX_XYZ_FIXUP) | ||
236 | field->logical_maximum = 32760; | ||
237 | hid_map_usage(hi, usage, bit, max, | ||
238 | EV_ABS, ABS_MT_POSITION_Y); | ||
239 | set_abs(hi->input, ABS_MT_POSITION_Y, field, | ||
240 | cls->sn_move); | ||
241 | /* touchscreen emulation */ | ||
242 | set_abs(hi->input, ABS_Y, field, cls->sn_move); | ||
243 | if (td->last_mt_collection == usage->collection_index) { | ||
244 | td->last_slot_field = usage->hid; | ||
245 | td->last_field_index = field->index; | ||
246 | } | ||
247 | return 1; | ||
248 | } | ||
249 | return 0; | ||
250 | |||
251 | case HID_UP_DIGITIZER: | ||
252 | switch (usage->hid) { | ||
253 | case HID_DG_INRANGE: | ||
254 | if (td->last_mt_collection == usage->collection_index) { | ||
255 | td->last_slot_field = usage->hid; | ||
256 | td->last_field_index = field->index; | ||
257 | } | ||
258 | return 1; | ||
259 | case HID_DG_CONFIDENCE: | ||
260 | if (td->last_mt_collection == usage->collection_index) { | ||
261 | td->last_slot_field = usage->hid; | ||
262 | td->last_field_index = field->index; | ||
263 | } | ||
264 | return 1; | ||
265 | case HID_DG_TIPSWITCH: | ||
266 | hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); | ||
267 | input_set_capability(hi->input, EV_KEY, BTN_TOUCH); | ||
268 | if (td->last_mt_collection == usage->collection_index) { | ||
269 | td->last_slot_field = usage->hid; | ||
270 | td->last_field_index = field->index; | ||
271 | } | ||
272 | return 1; | ||
273 | case HID_DG_CONTACTID: | ||
274 | if (!td->maxcontacts) | ||
275 | td->maxcontacts = MT_DEFAULT_MAXCONTACT; | ||
276 | input_mt_init_slots(hi->input, td->maxcontacts); | ||
277 | td->last_slot_field = usage->hid; | ||
278 | td->last_field_index = field->index; | ||
279 | td->last_mt_collection = usage->collection_index; | ||
280 | return 1; | ||
281 | case HID_DG_WIDTH: | ||
282 | hid_map_usage(hi, usage, bit, max, | ||
283 | EV_ABS, ABS_MT_TOUCH_MAJOR); | ||
284 | set_abs(hi->input, ABS_MT_TOUCH_MAJOR, field, | ||
285 | cls->sn_width); | ||
286 | if (td->last_mt_collection == usage->collection_index) { | ||
287 | td->last_slot_field = usage->hid; | ||
288 | td->last_field_index = field->index; | ||
289 | } | ||
290 | return 1; | ||
291 | case HID_DG_HEIGHT: | ||
292 | hid_map_usage(hi, usage, bit, max, | ||
293 | EV_ABS, ABS_MT_TOUCH_MINOR); | ||
294 | set_abs(hi->input, ABS_MT_TOUCH_MINOR, field, | ||
295 | cls->sn_height); | ||
296 | input_set_abs_params(hi->input, | ||
297 | ABS_MT_ORIENTATION, 0, 1, 0, 0); | ||
298 | if (td->last_mt_collection == usage->collection_index) { | ||
299 | td->last_slot_field = usage->hid; | ||
300 | td->last_field_index = field->index; | ||
301 | } | ||
302 | return 1; | ||
303 | case HID_DG_TIPPRESSURE: | ||
304 | if (quirks & MT_QUIRK_EGALAX_XYZ_FIXUP) | ||
305 | field->logical_minimum = 0; | ||
306 | hid_map_usage(hi, usage, bit, max, | ||
307 | EV_ABS, ABS_MT_PRESSURE); | ||
308 | set_abs(hi->input, ABS_MT_PRESSURE, field, | ||
309 | cls->sn_pressure); | ||
310 | /* touchscreen emulation */ | ||
311 | set_abs(hi->input, ABS_PRESSURE, field, | ||
312 | cls->sn_pressure); | ||
313 | if (td->last_mt_collection == usage->collection_index) { | ||
314 | td->last_slot_field = usage->hid; | ||
315 | td->last_field_index = field->index; | ||
316 | } | ||
317 | return 1; | ||
318 | case HID_DG_CONTACTCOUNT: | ||
319 | if (td->last_mt_collection == usage->collection_index) | ||
320 | td->last_field_index = field->index; | ||
321 | return 1; | ||
322 | case HID_DG_CONTACTMAX: | ||
323 | /* we don't set td->last_slot_field as contactcount and | ||
324 | * contact max are global to the report */ | ||
325 | if (td->last_mt_collection == usage->collection_index) | ||
326 | td->last_field_index = field->index; | ||
327 | return -1; | ||
328 | } | ||
329 | /* let hid-input decide for the others */ | ||
330 | return 0; | ||
331 | |||
332 | case 0xff000000: | ||
333 | /* we do not want to map these: no input-oriented meaning */ | ||
334 | return -1; | ||
335 | } | ||
336 | |||
337 | return 0; | ||
338 | } | ||
339 | |||
340 | static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi, | ||
341 | struct hid_field *field, struct hid_usage *usage, | ||
342 | unsigned long **bit, int *max) | ||
343 | { | ||
344 | if (usage->type == EV_KEY || usage->type == EV_ABS) | ||
345 | set_bit(usage->type, hi->input->evbit); | ||
346 | |||
347 | return -1; | ||
348 | } | ||
349 | |||
350 | static int mt_compute_slot(struct mt_device *td) | ||
351 | { | ||
352 | __s32 quirks = td->mtclass->quirks; | ||
353 | |||
354 | if (quirks & MT_QUIRK_SLOT_IS_CONTACTID) | ||
355 | return td->curdata.contactid; | ||
356 | |||
357 | if (quirks & MT_QUIRK_CYPRESS) | ||
358 | return cypress_compute_slot(td); | ||
359 | |||
360 | if (quirks & MT_QUIRK_SLOT_IS_CONTACTNUMBER) | ||
361 | return td->num_received; | ||
362 | |||
363 | if (quirks & MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE) | ||
364 | return td->curdata.contactid - 1; | ||
365 | |||
366 | return find_slot_from_contactid(td); | ||
367 | } | ||
368 | |||
369 | /* | ||
370 | * this function is called when a whole contact has been processed, | ||
371 | * so that it can assign it to a slot and store the data there | ||
372 | */ | ||
373 | static void mt_complete_slot(struct mt_device *td) | ||
374 | { | ||
375 | td->curdata.seen_in_this_frame = true; | ||
376 | if (td->curvalid) { | ||
377 | int slotnum = mt_compute_slot(td); | ||
378 | |||
379 | if (slotnum >= 0 && slotnum < td->maxcontacts) | ||
380 | td->slots[slotnum] = td->curdata; | ||
381 | } | ||
382 | td->num_received++; | ||
383 | } | ||
384 | |||
385 | |||
386 | /* | ||
387 | * this function is called when a whole packet has been received and processed, | ||
388 | * so that it can decide what to send to the input layer. | ||
389 | */ | ||
390 | static void mt_emit_event(struct mt_device *td, struct input_dev *input) | ||
391 | { | ||
392 | int i; | ||
393 | |||
394 | for (i = 0; i < td->maxcontacts; ++i) { | ||
395 | struct mt_slot *s = &(td->slots[i]); | ||
396 | if ((td->mtclass->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP) && | ||
397 | !s->seen_in_this_frame) { | ||
398 | s->touch_state = false; | ||
399 | } | ||
400 | |||
401 | input_mt_slot(input, i); | ||
402 | input_mt_report_slot_state(input, MT_TOOL_FINGER, | ||
403 | s->touch_state); | ||
404 | if (s->touch_state) { | ||
405 | /* this finger is on the screen */ | ||
406 | int wide = (s->w > s->h); | ||
407 | /* divided by two to match visual scale of touch */ | ||
408 | int major = max(s->w, s->h) >> 1; | ||
409 | int minor = min(s->w, s->h) >> 1; | ||
410 | |||
411 | input_event(input, EV_ABS, ABS_MT_POSITION_X, s->x); | ||
412 | input_event(input, EV_ABS, ABS_MT_POSITION_Y, s->y); | ||
413 | input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide); | ||
414 | input_event(input, EV_ABS, ABS_MT_PRESSURE, s->p); | ||
415 | input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major); | ||
416 | input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, minor); | ||
417 | } | ||
418 | s->seen_in_this_frame = false; | ||
419 | |||
420 | } | ||
421 | |||
422 | input_mt_report_pointer_emulation(input, true); | ||
423 | input_sync(input); | ||
424 | td->num_received = 0; | ||
425 | } | ||
426 | |||
427 | |||
428 | |||
429 | static int mt_event(struct hid_device *hid, struct hid_field *field, | ||
430 | struct hid_usage *usage, __s32 value) | ||
431 | { | ||
432 | struct mt_device *td = hid_get_drvdata(hid); | ||
433 | __s32 quirks = td->mtclass->quirks; | ||
434 | |||
435 | if (hid->claimed & HID_CLAIMED_INPUT && td->slots) { | ||
436 | switch (usage->hid) { | ||
437 | case HID_DG_INRANGE: | ||
438 | if (quirks & MT_QUIRK_VALID_IS_INRANGE) | ||
439 | td->curvalid = value; | ||
440 | break; | ||
441 | case HID_DG_TIPSWITCH: | ||
442 | if (quirks & MT_QUIRK_NOT_SEEN_MEANS_UP) | ||
443 | td->curvalid = value; | ||
444 | td->curdata.touch_state = value; | ||
445 | break; | ||
446 | case HID_DG_CONFIDENCE: | ||
447 | if (quirks & MT_QUIRK_VALID_IS_CONFIDENCE) | ||
448 | td->curvalid = value; | ||
449 | break; | ||
450 | case HID_DG_CONTACTID: | ||
451 | td->curdata.contactid = value; | ||
452 | break; | ||
453 | case HID_DG_TIPPRESSURE: | ||
454 | td->curdata.p = value; | ||
455 | break; | ||
456 | case HID_GD_X: | ||
457 | td->curdata.x = value; | ||
458 | break; | ||
459 | case HID_GD_Y: | ||
460 | td->curdata.y = value; | ||
461 | break; | ||
462 | case HID_DG_WIDTH: | ||
463 | td->curdata.w = value; | ||
464 | break; | ||
465 | case HID_DG_HEIGHT: | ||
466 | td->curdata.h = value; | ||
467 | break; | ||
468 | case HID_DG_CONTACTCOUNT: | ||
469 | /* | ||
470 | * Includes multi-packet support where subsequent | ||
471 | * packets are sent with zero contactcount. | ||
472 | */ | ||
473 | if (value) | ||
474 | td->num_expected = value; | ||
475 | break; | ||
476 | |||
477 | default: | ||
478 | /* fallback to the generic hidinput handling */ | ||
479 | return 0; | ||
480 | } | ||
481 | |||
482 | if (usage->hid == td->last_slot_field) { | ||
483 | mt_complete_slot(td); | ||
484 | } | ||
485 | |||
486 | if (field->index == td->last_field_index | ||
487 | && td->num_received >= td->num_expected) | ||
488 | mt_emit_event(td, field->hidinput->input); | ||
489 | |||
490 | } | ||
491 | |||
492 | /* we have handled the hidinput part, now remains hiddev */ | ||
493 | if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event) | ||
494 | hid->hiddev_hid_event(hid, field, usage, value); | ||
495 | |||
496 | return 1; | ||
497 | } | ||
498 | |||
499 | static void mt_set_input_mode(struct hid_device *hdev) | ||
500 | { | ||
501 | struct mt_device *td = hid_get_drvdata(hdev); | ||
502 | struct hid_report *r; | ||
503 | struct hid_report_enum *re; | ||
504 | |||
505 | if (td->inputmode < 0) | ||
506 | return; | ||
507 | |||
508 | re = &(hdev->report_enum[HID_FEATURE_REPORT]); | ||
509 | r = re->report_id_hash[td->inputmode]; | ||
510 | if (r) { | ||
511 | r->field[0]->value[0] = 0x02; | ||
512 | usbhid_submit_report(hdev, r, USB_DIR_OUT); | ||
513 | } | ||
514 | } | ||
515 | |||
516 | static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) | ||
517 | { | ||
518 | int ret, i; | ||
519 | struct mt_device *td; | ||
520 | struct mt_class *mtclass = mt_classes; /* MT_CLS_DEFAULT */ | ||
521 | |||
522 | for (i = 0; mt_classes[i].name ; i++) { | ||
523 | if (id->driver_data == mt_classes[i].name) { | ||
524 | mtclass = &(mt_classes[i]); | ||
525 | break; | ||
526 | } | ||
527 | } | ||
528 | |||
529 | /* This allows the driver to correctly support devices | ||
530 | * that emit events over several HID messages. | ||
531 | */ | ||
532 | hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC; | ||
533 | |||
534 | td = kzalloc(sizeof(struct mt_device), GFP_KERNEL); | ||
535 | if (!td) { | ||
536 | dev_err(&hdev->dev, "cannot allocate multitouch data\n"); | ||
537 | return -ENOMEM; | ||
538 | } | ||
539 | td->mtclass = mtclass; | ||
540 | td->inputmode = -1; | ||
541 | td->last_mt_collection = -1; | ||
542 | hid_set_drvdata(hdev, td); | ||
543 | |||
544 | ret = hid_parse(hdev); | ||
545 | if (ret != 0) | ||
546 | goto fail; | ||
547 | |||
548 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); | ||
549 | if (ret) | ||
550 | goto fail; | ||
551 | |||
552 | td->slots = kzalloc(td->maxcontacts * sizeof(struct mt_slot), | ||
553 | GFP_KERNEL); | ||
554 | if (!td->slots) { | ||
555 | dev_err(&hdev->dev, "cannot allocate multitouch slots\n"); | ||
556 | hid_hw_stop(hdev); | ||
557 | ret = -ENOMEM; | ||
558 | goto fail; | ||
559 | } | ||
560 | |||
561 | mt_set_input_mode(hdev); | ||
562 | |||
563 | return 0; | ||
564 | |||
565 | fail: | ||
566 | kfree(td); | ||
567 | return ret; | ||
568 | } | ||
569 | |||
570 | #ifdef CONFIG_PM | ||
571 | static int mt_reset_resume(struct hid_device *hdev) | ||
572 | { | ||
573 | mt_set_input_mode(hdev); | ||
574 | return 0; | ||
575 | } | ||
576 | #endif | ||
577 | |||
578 | static void mt_remove(struct hid_device *hdev) | ||
579 | { | ||
580 | struct mt_device *td = hid_get_drvdata(hdev); | ||
581 | hid_hw_stop(hdev); | ||
582 | kfree(td->slots); | ||
583 | kfree(td); | ||
584 | hid_set_drvdata(hdev, NULL); | ||
585 | } | ||
586 | |||
587 | static const struct hid_device_id mt_devices[] = { | ||
588 | |||
589 | /* 3M panels */ | ||
590 | { .driver_data = MT_CLS_3M, | ||
591 | HID_USB_DEVICE(USB_VENDOR_ID_3M, | ||
592 | USB_DEVICE_ID_3M1968) }, | ||
593 | { .driver_data = MT_CLS_3M, | ||
594 | HID_USB_DEVICE(USB_VENDOR_ID_3M, | ||
595 | USB_DEVICE_ID_3M2256) }, | ||
596 | |||
597 | /* ActionStar panels */ | ||
598 | { .driver_data = MT_CLS_DEFAULT, | ||
599 | HID_USB_DEVICE(USB_VENDOR_ID_ACTIONSTAR, | ||
600 | USB_DEVICE_ID_ACTIONSTAR_1011) }, | ||
601 | |||
602 | /* Cando panels */ | ||
603 | { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER, | ||
604 | HID_USB_DEVICE(USB_VENDOR_ID_CANDO, | ||
605 | USB_DEVICE_ID_CANDO_MULTI_TOUCH) }, | ||
606 | { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER, | ||
607 | HID_USB_DEVICE(USB_VENDOR_ID_CANDO, | ||
608 | USB_DEVICE_ID_CANDO_MULTI_TOUCH_10_1) }, | ||
609 | { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER, | ||
610 | HID_USB_DEVICE(USB_VENDOR_ID_CANDO, | ||
611 | USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) }, | ||
612 | { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER, | ||
613 | HID_USB_DEVICE(USB_VENDOR_ID_CANDO, | ||
614 | USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) }, | ||
615 | |||
616 | /* Chunghwa Telecom touch panels */ | ||
617 | { .driver_data = MT_CLS_DEFAULT, | ||
618 | HID_USB_DEVICE(USB_VENDOR_ID_CHUNGHWAT, | ||
619 | USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH) }, | ||
620 | |||
621 | /* CVTouch panels */ | ||
622 | { .driver_data = MT_CLS_DEFAULT, | ||
623 | HID_USB_DEVICE(USB_VENDOR_ID_CVTOUCH, | ||
624 | USB_DEVICE_ID_CVTOUCH_SCREEN) }, | ||
625 | |||
626 | /* Cypress panel */ | ||
627 | { .driver_data = MT_CLS_CYPRESS, | ||
628 | HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, | ||
629 | USB_DEVICE_ID_CYPRESS_TRUETOUCH) }, | ||
630 | |||
631 | /* eGalax devices (resistive) */ | ||
632 | { .driver_data = MT_CLS_EGALAX, | ||
633 | HID_USB_DEVICE(USB_VENDOR_ID_DWAV, | ||
634 | USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH) }, | ||
635 | { .driver_data = MT_CLS_EGALAX, | ||
636 | HID_USB_DEVICE(USB_VENDOR_ID_DWAV, | ||
637 | USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH3) }, | ||
638 | |||
639 | /* eGalax devices (capacitive) */ | ||
640 | { .driver_data = MT_CLS_EGALAX, | ||
641 | HID_USB_DEVICE(USB_VENDOR_ID_DWAV, | ||
642 | USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1) }, | ||
643 | { .driver_data = MT_CLS_EGALAX, | ||
644 | HID_USB_DEVICE(USB_VENDOR_ID_DWAV, | ||
645 | USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH2) }, | ||
646 | { .driver_data = MT_CLS_EGALAX, | ||
647 | HID_USB_DEVICE(USB_VENDOR_ID_DWAV, | ||
648 | USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH4) }, | ||
649 | |||
650 | /* Elo TouchSystems IntelliTouch Plus panel */ | ||
651 | { .driver_data = MT_CLS_DUAL_NSMU_CONTACTID, | ||
652 | HID_USB_DEVICE(USB_VENDOR_ID_ELO, | ||
653 | USB_DEVICE_ID_ELO_TS2515) }, | ||
654 | |||
655 | /* GeneralTouch panel */ | ||
656 | { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER, | ||
657 | HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, | ||
658 | USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS) }, | ||
659 | |||
660 | /* GoodTouch panels */ | ||
661 | { .driver_data = MT_CLS_DEFAULT, | ||
662 | HID_USB_DEVICE(USB_VENDOR_ID_GOODTOUCH, | ||
663 | USB_DEVICE_ID_GOODTOUCH_000f) }, | ||
664 | |||
665 | /* Ilitek dual touch panel */ | ||
666 | { .driver_data = MT_CLS_DEFAULT, | ||
667 | HID_USB_DEVICE(USB_VENDOR_ID_ILITEK, | ||
668 | USB_DEVICE_ID_ILITEK_MULTITOUCH) }, | ||
669 | |||
670 | /* IRTOUCH panels */ | ||
671 | { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID, | ||
672 | HID_USB_DEVICE(USB_VENDOR_ID_IRTOUCHSYSTEMS, | ||
673 | USB_DEVICE_ID_IRTOUCH_INFRARED_USB) }, | ||
674 | |||
675 | /* Lumio panels */ | ||
676 | { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE, | ||
677 | HID_USB_DEVICE(USB_VENDOR_ID_LUMIO, | ||
678 | USB_DEVICE_ID_CRYSTALTOUCH) }, | ||
679 | { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE, | ||
680 | HID_USB_DEVICE(USB_VENDOR_ID_LUMIO, | ||
681 | USB_DEVICE_ID_CRYSTALTOUCH_DUAL) }, | ||
682 | |||
683 | /* MosArt panels */ | ||
684 | { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE, | ||
685 | HID_USB_DEVICE(USB_VENDOR_ID_ASUS, | ||
686 | USB_DEVICE_ID_ASUS_T91MT)}, | ||
687 | { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE, | ||
688 | HID_USB_DEVICE(USB_VENDOR_ID_ASUS, | ||
689 | USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO) }, | ||
690 | { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE, | ||
691 | HID_USB_DEVICE(USB_VENDOR_ID_TURBOX, | ||
692 | USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART) }, | ||
693 | |||
694 | /* PenMount panels */ | ||
695 | { .driver_data = MT_CLS_CONFIDENCE, | ||
696 | HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, | ||
697 | USB_DEVICE_ID_PENMOUNT_PCI) }, | ||
698 | |||
699 | /* PixCir-based panels */ | ||
700 | { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID, | ||
701 | HID_USB_DEVICE(USB_VENDOR_ID_HANVON, | ||
702 | USB_DEVICE_ID_HANVON_MULTITOUCH) }, | ||
703 | { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID, | ||
704 | HID_USB_DEVICE(USB_VENDOR_ID_CANDO, | ||
705 | USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) }, | ||
706 | |||
707 | /* Stantum panels */ | ||
708 | { .driver_data = MT_CLS_CONFIDENCE, | ||
709 | HID_USB_DEVICE(USB_VENDOR_ID_STANTUM, | ||
710 | USB_DEVICE_ID_MTP)}, | ||
711 | { .driver_data = MT_CLS_CONFIDENCE, | ||
712 | HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_STM, | ||
713 | USB_DEVICE_ID_MTP_STM)}, | ||
714 | { .driver_data = MT_CLS_CONFIDENCE, | ||
715 | HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_SITRONIX, | ||
716 | USB_DEVICE_ID_MTP_SITRONIX)}, | ||
717 | |||
718 | /* Touch International panels */ | ||
719 | { .driver_data = MT_CLS_DEFAULT, | ||
720 | HID_USB_DEVICE(USB_VENDOR_ID_TOUCH_INTL, | ||
721 | USB_DEVICE_ID_TOUCH_INTL_MULTI_TOUCH) }, | ||
722 | |||
723 | /* Unitec panels */ | ||
724 | { .driver_data = MT_CLS_DEFAULT, | ||
725 | HID_USB_DEVICE(USB_VENDOR_ID_UNITEC, | ||
726 | USB_DEVICE_ID_UNITEC_USB_TOUCH_0709) }, | ||
727 | { .driver_data = MT_CLS_DEFAULT, | ||
728 | HID_USB_DEVICE(USB_VENDOR_ID_UNITEC, | ||
729 | USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19) }, | ||
730 | |||
731 | { } | ||
732 | }; | ||
733 | MODULE_DEVICE_TABLE(hid, mt_devices); | ||
734 | |||
735 | static const struct hid_usage_id mt_grabbed_usages[] = { | ||
736 | { HID_ANY_ID, HID_ANY_ID, HID_ANY_ID }, | ||
737 | { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1} | ||
738 | }; | ||
739 | |||
740 | static struct hid_driver mt_driver = { | ||
741 | .name = "hid-multitouch", | ||
742 | .id_table = mt_devices, | ||
743 | .probe = mt_probe, | ||
744 | .remove = mt_remove, | ||
745 | .input_mapping = mt_input_mapping, | ||
746 | .input_mapped = mt_input_mapped, | ||
747 | .feature_mapping = mt_feature_mapping, | ||
748 | .usage_table = mt_grabbed_usages, | ||
749 | .event = mt_event, | ||
750 | #ifdef CONFIG_PM | ||
751 | .reset_resume = mt_reset_resume, | ||
752 | #endif | ||
753 | }; | ||
754 | |||
755 | static int __init mt_init(void) | ||
756 | { | ||
757 | return hid_register_driver(&mt_driver); | ||
758 | } | ||
759 | |||
760 | static void __exit mt_exit(void) | ||
761 | { | ||
762 | hid_unregister_driver(&mt_driver); | ||
763 | } | ||
764 | |||
765 | module_init(mt_init); | ||
766 | module_exit(mt_exit); | ||
diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c index fb69b8c4953f..9fae2ebdd758 100644 --- a/drivers/hid/hid-ntrig.c +++ b/drivers/hid/hid-ntrig.c | |||
@@ -90,6 +90,84 @@ struct ntrig_data { | |||
90 | }; | 90 | }; |
91 | 91 | ||
92 | 92 | ||
93 | /* | ||
94 | * This function converts the 4 byte raw firmware code into | ||
95 | * a string containing 5 comma separated numbers. | ||
96 | */ | ||
97 | static int ntrig_version_string(unsigned char *raw, char *buf) | ||
98 | { | ||
99 | __u8 a = (raw[1] & 0x0e) >> 1; | ||
100 | __u8 b = (raw[0] & 0x3c) >> 2; | ||
101 | __u8 c = ((raw[0] & 0x03) << 3) | ((raw[3] & 0xe0) >> 5); | ||
102 | __u8 d = ((raw[3] & 0x07) << 3) | ((raw[2] & 0xe0) >> 5); | ||
103 | __u8 e = raw[2] & 0x07; | ||
104 | |||
105 | /* | ||
106 | * As yet unmapped bits: | ||
107 | * 0b11000000 0b11110001 0b00011000 0b00011000 | ||
108 | */ | ||
109 | |||
110 | return sprintf(buf, "%u.%u.%u.%u.%u", a, b, c, d, e); | ||
111 | } | ||
112 | |||
113 | static inline int ntrig_get_mode(struct hid_device *hdev) | ||
114 | { | ||
115 | struct hid_report *report = hdev->report_enum[HID_FEATURE_REPORT]. | ||
116 | report_id_hash[0x0d]; | ||
117 | |||
118 | if (!report) | ||
119 | return -EINVAL; | ||
120 | |||
121 | usbhid_submit_report(hdev, report, USB_DIR_IN); | ||
122 | usbhid_wait_io(hdev); | ||
123 | return (int)report->field[0]->value[0]; | ||
124 | } | ||
125 | |||
126 | static inline void ntrig_set_mode(struct hid_device *hdev, const int mode) | ||
127 | { | ||
128 | struct hid_report *report; | ||
129 | __u8 mode_commands[4] = { 0xe, 0xf, 0x1b, 0x10 }; | ||
130 | |||
131 | if (mode < 0 || mode > 3) | ||
132 | return; | ||
133 | |||
134 | report = hdev->report_enum[HID_FEATURE_REPORT]. | ||
135 | report_id_hash[mode_commands[mode]]; | ||
136 | |||
137 | if (!report) | ||
138 | return; | ||
139 | |||
140 | usbhid_submit_report(hdev, report, USB_DIR_IN); | ||
141 | } | ||
142 | |||
143 | static void ntrig_report_version(struct hid_device *hdev) | ||
144 | { | ||
145 | int ret; | ||
146 | char buf[20]; | ||
147 | struct usb_device *usb_dev = hid_to_usb_dev(hdev); | ||
148 | unsigned char *data = kmalloc(8, GFP_KERNEL); | ||
149 | |||
150 | if (!data) | ||
151 | goto err_free; | ||
152 | |||
153 | ret = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), | ||
154 | USB_REQ_CLEAR_FEATURE, | ||
155 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | | ||
156 | USB_DIR_IN, | ||
157 | 0x30c, 1, data, 8, | ||
158 | USB_CTRL_SET_TIMEOUT); | ||
159 | |||
160 | if (ret == 8) { | ||
161 | ret = ntrig_version_string(&data[2], buf); | ||
162 | |||
163 | hid_info(hdev, "Firmware version: %s (%02x%02x %02x%02x)\n", | ||
164 | buf, data[2], data[3], data[4], data[5]); | ||
165 | } | ||
166 | |||
167 | err_free: | ||
168 | kfree(data); | ||
169 | } | ||
170 | |||
93 | static ssize_t show_phys_width(struct device *dev, | 171 | static ssize_t show_phys_width(struct device *dev, |
94 | struct device_attribute *attr, | 172 | struct device_attribute *attr, |
95 | char *buf) | 173 | char *buf) |
@@ -377,8 +455,8 @@ static struct attribute_group ntrig_attribute_group = { | |||
377 | */ | 455 | */ |
378 | 456 | ||
379 | static int ntrig_input_mapping(struct hid_device *hdev, struct hid_input *hi, | 457 | static int ntrig_input_mapping(struct hid_device *hdev, struct hid_input *hi, |
380 | struct hid_field *field, struct hid_usage *usage, | 458 | struct hid_field *field, struct hid_usage *usage, |
381 | unsigned long **bit, int *max) | 459 | unsigned long **bit, int *max) |
382 | { | 460 | { |
383 | struct ntrig_data *nd = hid_get_drvdata(hdev); | 461 | struct ntrig_data *nd = hid_get_drvdata(hdev); |
384 | 462 | ||
@@ -448,13 +526,13 @@ static int ntrig_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
448 | /* width/height mapped on TouchMajor/TouchMinor/Orientation */ | 526 | /* width/height mapped on TouchMajor/TouchMinor/Orientation */ |
449 | case HID_DG_WIDTH: | 527 | case HID_DG_WIDTH: |
450 | hid_map_usage(hi, usage, bit, max, | 528 | hid_map_usage(hi, usage, bit, max, |
451 | EV_ABS, ABS_MT_TOUCH_MAJOR); | 529 | EV_ABS, ABS_MT_TOUCH_MAJOR); |
452 | return 1; | 530 | return 1; |
453 | case HID_DG_HEIGHT: | 531 | case HID_DG_HEIGHT: |
454 | hid_map_usage(hi, usage, bit, max, | 532 | hid_map_usage(hi, usage, bit, max, |
455 | EV_ABS, ABS_MT_TOUCH_MINOR); | 533 | EV_ABS, ABS_MT_TOUCH_MINOR); |
456 | input_set_abs_params(hi->input, ABS_MT_ORIENTATION, | 534 | input_set_abs_params(hi->input, ABS_MT_ORIENTATION, |
457 | 0, 1, 0, 0); | 535 | 0, 1, 0, 0); |
458 | return 1; | 536 | return 1; |
459 | } | 537 | } |
460 | return 0; | 538 | return 0; |
@@ -468,8 +546,8 @@ static int ntrig_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
468 | } | 546 | } |
469 | 547 | ||
470 | static int ntrig_input_mapped(struct hid_device *hdev, struct hid_input *hi, | 548 | static int ntrig_input_mapped(struct hid_device *hdev, struct hid_input *hi, |
471 | struct hid_field *field, struct hid_usage *usage, | 549 | struct hid_field *field, struct hid_usage *usage, |
472 | unsigned long **bit, int *max) | 550 | unsigned long **bit, int *max) |
473 | { | 551 | { |
474 | /* No special mappings needed for the pen and single touch */ | 552 | /* No special mappings needed for the pen and single touch */ |
475 | if (field->physical) | 553 | if (field->physical) |
@@ -489,279 +567,290 @@ static int ntrig_input_mapped(struct hid_device *hdev, struct hid_input *hi, | |||
489 | * and call input_mt_sync after each point if necessary | 567 | * and call input_mt_sync after each point if necessary |
490 | */ | 568 | */ |
491 | static int ntrig_event (struct hid_device *hid, struct hid_field *field, | 569 | static int ntrig_event (struct hid_device *hid, struct hid_field *field, |
492 | struct hid_usage *usage, __s32 value) | 570 | struct hid_usage *usage, __s32 value) |
493 | { | 571 | { |
494 | struct input_dev *input = field->hidinput->input; | ||
495 | struct ntrig_data *nd = hid_get_drvdata(hid); | 572 | struct ntrig_data *nd = hid_get_drvdata(hid); |
573 | struct input_dev *input; | ||
574 | |||
575 | /* Skip processing if not a claimed input */ | ||
576 | if (!(hid->claimed & HID_CLAIMED_INPUT)) | ||
577 | goto not_claimed_input; | ||
578 | |||
579 | /* This function is being called before the structures are fully | ||
580 | * initialized */ | ||
581 | if(!(field->hidinput && field->hidinput->input)) | ||
582 | return -EINVAL; | ||
583 | |||
584 | input = field->hidinput->input; | ||
496 | 585 | ||
497 | /* No special handling needed for the pen */ | 586 | /* No special handling needed for the pen */ |
498 | if (field->application == HID_DG_PEN) | 587 | if (field->application == HID_DG_PEN) |
499 | return 0; | 588 | return 0; |
500 | 589 | ||
501 | if (hid->claimed & HID_CLAIMED_INPUT) { | 590 | switch (usage->hid) { |
502 | switch (usage->hid) { | 591 | case 0xff000001: |
503 | case 0xff000001: | 592 | /* Tag indicating the start of a multitouch group */ |
504 | /* Tag indicating the start of a multitouch group */ | 593 | nd->reading_mt = 1; |
505 | nd->reading_mt = 1; | 594 | nd->first_contact_touch = 0; |
506 | nd->first_contact_touch = 0; | 595 | break; |
507 | break; | 596 | case HID_DG_TIPSWITCH: |
508 | case HID_DG_TIPSWITCH: | 597 | nd->tipswitch = value; |
509 | nd->tipswitch = value; | 598 | /* Prevent emission of touch until validated */ |
510 | /* Prevent emission of touch until validated */ | 599 | return 1; |
511 | return 1; | 600 | case HID_DG_CONFIDENCE: |
512 | case HID_DG_CONFIDENCE: | 601 | nd->confidence = value; |
513 | nd->confidence = value; | 602 | break; |
514 | break; | 603 | case HID_GD_X: |
515 | case HID_GD_X: | 604 | nd->x = value; |
516 | nd->x = value; | 605 | /* Clear the contact footer */ |
517 | /* Clear the contact footer */ | 606 | nd->mt_foot_count = 0; |
518 | nd->mt_foot_count = 0; | 607 | break; |
519 | break; | 608 | case HID_GD_Y: |
520 | case HID_GD_Y: | 609 | nd->y = value; |
521 | nd->y = value; | 610 | break; |
522 | break; | 611 | case HID_DG_CONTACTID: |
523 | case HID_DG_CONTACTID: | 612 | nd->id = value; |
524 | nd->id = value; | 613 | break; |
525 | break; | 614 | case HID_DG_WIDTH: |
526 | case HID_DG_WIDTH: | 615 | nd->w = value; |
527 | nd->w = value; | 616 | break; |
528 | break; | 617 | case HID_DG_HEIGHT: |
529 | case HID_DG_HEIGHT: | 618 | nd->h = value; |
530 | nd->h = value; | 619 | /* |
620 | * when in single touch mode, this is the last | ||
621 | * report received in a finger event. We want | ||
622 | * to emit a normal (X, Y) position | ||
623 | */ | ||
624 | if (!nd->reading_mt) { | ||
531 | /* | 625 | /* |
532 | * when in single touch mode, this is the last | 626 | * TipSwitch indicates the presence of a |
533 | * report received in a finger event. We want | 627 | * finger in single touch mode. |
534 | * to emit a normal (X, Y) position | ||
535 | */ | 628 | */ |
536 | if (!nd->reading_mt) { | 629 | input_report_key(input, BTN_TOUCH, |
537 | /* | 630 | nd->tipswitch); |
538 | * TipSwitch indicates the presence of a | 631 | input_report_key(input, BTN_TOOL_DOUBLETAP, |
539 | * finger in single touch mode. | 632 | nd->tipswitch); |
540 | */ | 633 | input_event(input, EV_ABS, ABS_X, nd->x); |
541 | input_report_key(input, BTN_TOUCH, | 634 | input_event(input, EV_ABS, ABS_Y, nd->y); |
542 | nd->tipswitch); | 635 | } |
543 | input_report_key(input, BTN_TOOL_DOUBLETAP, | 636 | break; |
544 | nd->tipswitch); | 637 | case 0xff000002: |
545 | input_event(input, EV_ABS, ABS_X, nd->x); | 638 | /* |
546 | input_event(input, EV_ABS, ABS_Y, nd->y); | 639 | * we receive this when the device is in multitouch |
547 | } | 640 | * mode. The first of the three values tagged with |
641 | * this usage tells if the contact point is real | ||
642 | * or a placeholder | ||
643 | */ | ||
644 | |||
645 | /* Shouldn't get more than 4 footer packets, so skip */ | ||
646 | if (nd->mt_foot_count >= 4) | ||
548 | break; | 647 | break; |
549 | case 0xff000002: | ||
550 | /* | ||
551 | * we receive this when the device is in multitouch | ||
552 | * mode. The first of the three values tagged with | ||
553 | * this usage tells if the contact point is real | ||
554 | * or a placeholder | ||
555 | */ | ||
556 | 648 | ||
557 | /* Shouldn't get more than 4 footer packets, so skip */ | 649 | nd->mt_footer[nd->mt_foot_count++] = value; |
558 | if (nd->mt_foot_count >= 4) | ||
559 | break; | ||
560 | 650 | ||
561 | nd->mt_footer[nd->mt_foot_count++] = value; | 651 | /* if the footer isn't complete break */ |
652 | if (nd->mt_foot_count != 4) | ||
653 | break; | ||
562 | 654 | ||
563 | /* if the footer isn't complete break */ | 655 | /* Pen activity signal. */ |
564 | if (nd->mt_foot_count != 4) | 656 | if (nd->mt_footer[2]) { |
565 | break; | 657 | /* |
658 | * When the pen deactivates touch, we see a | ||
659 | * bogus frame with ContactCount > 0. | ||
660 | * We can | ||
661 | * save a bit of work by ensuring act_state < 0 | ||
662 | * even if deactivation slack is turned off. | ||
663 | */ | ||
664 | nd->act_state = deactivate_slack - 1; | ||
665 | nd->confidence = 0; | ||
666 | break; | ||
667 | } | ||
566 | 668 | ||
567 | /* Pen activity signal. */ | 669 | /* |
568 | if (nd->mt_footer[2]) { | 670 | * The first footer value indicates the presence of a |
569 | /* | 671 | * finger. |
570 | * When the pen deactivates touch, we see a | 672 | */ |
571 | * bogus frame with ContactCount > 0. | 673 | if (nd->mt_footer[0]) { |
572 | * We can | 674 | /* |
573 | * save a bit of work by ensuring act_state < 0 | 675 | * We do not want to process contacts under |
574 | * even if deactivation slack is turned off. | 676 | * the size threshold, but do not want to |
575 | */ | 677 | * ignore them for activation state |
576 | nd->act_state = deactivate_slack - 1; | 678 | */ |
679 | if (nd->w < nd->min_width || | ||
680 | nd->h < nd->min_height) | ||
577 | nd->confidence = 0; | 681 | nd->confidence = 0; |
578 | break; | 682 | } else |
579 | } | 683 | break; |
580 | 684 | ||
685 | if (nd->act_state > 0) { | ||
581 | /* | 686 | /* |
582 | * The first footer value indicates the presence of a | 687 | * Contact meets the activation size threshold |
583 | * finger. | ||
584 | */ | 688 | */ |
585 | if (nd->mt_footer[0]) { | 689 | if (nd->w >= nd->activation_width && |
586 | /* | 690 | nd->h >= nd->activation_height) { |
587 | * We do not want to process contacts under | 691 | if (nd->id) |
588 | * the size threshold, but do not want to | 692 | /* |
589 | * ignore them for activation state | 693 | * first contact, activate now |
590 | */ | 694 | */ |
591 | if (nd->w < nd->min_width || | 695 | nd->act_state = 0; |
592 | nd->h < nd->min_height) | 696 | else { |
593 | nd->confidence = 0; | ||
594 | } else | ||
595 | break; | ||
596 | |||
597 | if (nd->act_state > 0) { | ||
598 | /* | ||
599 | * Contact meets the activation size threshold | ||
600 | */ | ||
601 | if (nd->w >= nd->activation_width && | ||
602 | nd->h >= nd->activation_height) { | ||
603 | if (nd->id) | ||
604 | /* | ||
605 | * first contact, activate now | ||
606 | */ | ||
607 | nd->act_state = 0; | ||
608 | else { | ||
609 | /* | ||
610 | * avoid corrupting this frame | ||
611 | * but ensure next frame will | ||
612 | * be active | ||
613 | */ | ||
614 | nd->act_state = 1; | ||
615 | break; | ||
616 | } | ||
617 | } else | ||
618 | /* | 697 | /* |
619 | * Defer adjusting the activation state | 698 | * avoid corrupting this frame |
620 | * until the end of the frame. | 699 | * but ensure next frame will |
700 | * be active | ||
621 | */ | 701 | */ |
702 | nd->act_state = 1; | ||
622 | break; | 703 | break; |
623 | } | 704 | } |
624 | 705 | } else | |
625 | /* Discarding this contact */ | ||
626 | if (!nd->confidence) | ||
627 | break; | ||
628 | |||
629 | /* emit a normal (X, Y) for the first point only */ | ||
630 | if (nd->id == 0) { | ||
631 | /* | 706 | /* |
632 | * TipSwitch is superfluous in multitouch | 707 | * Defer adjusting the activation state |
633 | * mode. The footer events tell us | 708 | * until the end of the frame. |
634 | * if there is a finger on the screen or | ||
635 | * not. | ||
636 | */ | 709 | */ |
637 | nd->first_contact_touch = nd->confidence; | 710 | break; |
638 | input_event(input, EV_ABS, ABS_X, nd->x); | 711 | } |
639 | input_event(input, EV_ABS, ABS_Y, nd->y); | ||
640 | } | ||
641 | 712 | ||
642 | /* Emit MT events */ | 713 | /* Discarding this contact */ |
643 | input_event(input, EV_ABS, ABS_MT_POSITION_X, nd->x); | 714 | if (!nd->confidence) |
644 | input_event(input, EV_ABS, ABS_MT_POSITION_Y, nd->y); | 715 | break; |
645 | 716 | ||
717 | /* emit a normal (X, Y) for the first point only */ | ||
718 | if (nd->id == 0) { | ||
646 | /* | 719 | /* |
647 | * Translate from height and width to size | 720 | * TipSwitch is superfluous in multitouch |
648 | * and orientation. | 721 | * mode. The footer events tell us |
722 | * if there is a finger on the screen or | ||
723 | * not. | ||
649 | */ | 724 | */ |
650 | if (nd->w > nd->h) { | 725 | nd->first_contact_touch = nd->confidence; |
651 | input_event(input, EV_ABS, | 726 | input_event(input, EV_ABS, ABS_X, nd->x); |
652 | ABS_MT_ORIENTATION, 1); | 727 | input_event(input, EV_ABS, ABS_Y, nd->y); |
653 | input_event(input, EV_ABS, | 728 | } |
654 | ABS_MT_TOUCH_MAJOR, nd->w); | ||
655 | input_event(input, EV_ABS, | ||
656 | ABS_MT_TOUCH_MINOR, nd->h); | ||
657 | } else { | ||
658 | input_event(input, EV_ABS, | ||
659 | ABS_MT_ORIENTATION, 0); | ||
660 | input_event(input, EV_ABS, | ||
661 | ABS_MT_TOUCH_MAJOR, nd->h); | ||
662 | input_event(input, EV_ABS, | ||
663 | ABS_MT_TOUCH_MINOR, nd->w); | ||
664 | } | ||
665 | input_mt_sync(field->hidinput->input); | ||
666 | break; | ||
667 | 729 | ||
668 | case HID_DG_CONTACTCOUNT: /* End of a multitouch group */ | 730 | /* Emit MT events */ |
669 | if (!nd->reading_mt) /* Just to be sure */ | 731 | input_event(input, EV_ABS, ABS_MT_POSITION_X, nd->x); |
670 | break; | 732 | input_event(input, EV_ABS, ABS_MT_POSITION_Y, nd->y); |
733 | |||
734 | /* | ||
735 | * Translate from height and width to size | ||
736 | * and orientation. | ||
737 | */ | ||
738 | if (nd->w > nd->h) { | ||
739 | input_event(input, EV_ABS, | ||
740 | ABS_MT_ORIENTATION, 1); | ||
741 | input_event(input, EV_ABS, | ||
742 | ABS_MT_TOUCH_MAJOR, nd->w); | ||
743 | input_event(input, EV_ABS, | ||
744 | ABS_MT_TOUCH_MINOR, nd->h); | ||
745 | } else { | ||
746 | input_event(input, EV_ABS, | ||
747 | ABS_MT_ORIENTATION, 0); | ||
748 | input_event(input, EV_ABS, | ||
749 | ABS_MT_TOUCH_MAJOR, nd->h); | ||
750 | input_event(input, EV_ABS, | ||
751 | ABS_MT_TOUCH_MINOR, nd->w); | ||
752 | } | ||
753 | input_mt_sync(field->hidinput->input); | ||
754 | break; | ||
671 | 755 | ||
672 | nd->reading_mt = 0; | 756 | case HID_DG_CONTACTCOUNT: /* End of a multitouch group */ |
757 | if (!nd->reading_mt) /* Just to be sure */ | ||
758 | break; | ||
673 | 759 | ||
760 | nd->reading_mt = 0; | ||
761 | |||
762 | |||
763 | /* | ||
764 | * Activation state machine logic: | ||
765 | * | ||
766 | * Fundamental states: | ||
767 | * state > 0: Inactive | ||
768 | * state <= 0: Active | ||
769 | * state < -deactivate_slack: | ||
770 | * Pen termination of touch | ||
771 | * | ||
772 | * Specific values of interest | ||
773 | * state == activate_slack | ||
774 | * no valid input since the last reset | ||
775 | * | ||
776 | * state == 0 | ||
777 | * general operational state | ||
778 | * | ||
779 | * state == -deactivate_slack | ||
780 | * read sufficient empty frames to accept | ||
781 | * the end of input and reset | ||
782 | */ | ||
783 | |||
784 | if (nd->act_state > 0) { /* Currently inactive */ | ||
785 | if (value) | ||
786 | /* | ||
787 | * Consider each live contact as | ||
788 | * evidence of intentional activity. | ||
789 | */ | ||
790 | nd->act_state = (nd->act_state > value) | ||
791 | ? nd->act_state - value | ||
792 | : 0; | ||
793 | else | ||
794 | /* | ||
795 | * Empty frame before we hit the | ||
796 | * activity threshold, reset. | ||
797 | */ | ||
798 | nd->act_state = nd->activate_slack; | ||
674 | 799 | ||
675 | /* | 800 | /* |
676 | * Activation state machine logic: | 801 | * Entered this block inactive and no |
677 | * | 802 | * coordinates sent this frame, so hold off |
678 | * Fundamental states: | 803 | * on button state. |
679 | * state > 0: Inactive | ||
680 | * state <= 0: Active | ||
681 | * state < -deactivate_slack: | ||
682 | * Pen termination of touch | ||
683 | * | ||
684 | * Specific values of interest | ||
685 | * state == activate_slack | ||
686 | * no valid input since the last reset | ||
687 | * | ||
688 | * state == 0 | ||
689 | * general operational state | ||
690 | * | ||
691 | * state == -deactivate_slack | ||
692 | * read sufficient empty frames to accept | ||
693 | * the end of input and reset | ||
694 | */ | 804 | */ |
695 | 805 | break; | |
696 | if (nd->act_state > 0) { /* Currently inactive */ | 806 | } else { /* Currently active */ |
697 | if (value) | 807 | if (value && nd->act_state >= |
698 | /* | 808 | nd->deactivate_slack) |
699 | * Consider each live contact as | ||
700 | * evidence of intentional activity. | ||
701 | */ | ||
702 | nd->act_state = (nd->act_state > value) | ||
703 | ? nd->act_state - value | ||
704 | : 0; | ||
705 | else | ||
706 | /* | ||
707 | * Empty frame before we hit the | ||
708 | * activity threshold, reset. | ||
709 | */ | ||
710 | nd->act_state = nd->activate_slack; | ||
711 | |||
712 | /* | 809 | /* |
713 | * Entered this block inactive and no | 810 | * Live point: clear accumulated |
714 | * coordinates sent this frame, so hold off | 811 | * deactivation count. |
715 | * on button state. | ||
716 | */ | 812 | */ |
717 | break; | 813 | nd->act_state = 0; |
718 | } else { /* Currently active */ | 814 | else if (nd->act_state <= nd->deactivate_slack) |
719 | if (value && nd->act_state >= | ||
720 | nd->deactivate_slack) | ||
721 | /* | ||
722 | * Live point: clear accumulated | ||
723 | * deactivation count. | ||
724 | */ | ||
725 | nd->act_state = 0; | ||
726 | else if (nd->act_state <= nd->deactivate_slack) | ||
727 | /* | ||
728 | * We've consumed the deactivation | ||
729 | * slack, time to deactivate and reset. | ||
730 | */ | ||
731 | nd->act_state = | ||
732 | nd->activate_slack; | ||
733 | else { /* Move towards deactivation */ | ||
734 | nd->act_state--; | ||
735 | break; | ||
736 | } | ||
737 | } | ||
738 | |||
739 | if (nd->first_contact_touch && nd->act_state <= 0) { | ||
740 | /* | 815 | /* |
741 | * Check to see if we're ready to start | 816 | * We've consumed the deactivation |
742 | * emitting touch events. | 817 | * slack, time to deactivate and reset. |
743 | * | ||
744 | * Note: activation slack will decrease over | ||
745 | * the course of the frame, and it will be | ||
746 | * inconsistent from the start to the end of | ||
747 | * the frame. However if the frame starts | ||
748 | * with slack, first_contact_touch will still | ||
749 | * be 0 and we will not get to this point. | ||
750 | */ | 818 | */ |
751 | input_report_key(input, BTN_TOOL_DOUBLETAP, 1); | 819 | nd->act_state = |
752 | input_report_key(input, BTN_TOUCH, 1); | 820 | nd->activate_slack; |
753 | } else { | 821 | else { /* Move towards deactivation */ |
754 | input_report_key(input, BTN_TOOL_DOUBLETAP, 0); | 822 | nd->act_state--; |
755 | input_report_key(input, BTN_TOUCH, 0); | 823 | break; |
756 | } | 824 | } |
757 | break; | 825 | } |
758 | 826 | ||
759 | default: | 827 | if (nd->first_contact_touch && nd->act_state <= 0) { |
760 | /* fall-back to the generic hidinput handling */ | 828 | /* |
761 | return 0; | 829 | * Check to see if we're ready to start |
830 | * emitting touch events. | ||
831 | * | ||
832 | * Note: activation slack will decrease over | ||
833 | * the course of the frame, and it will be | ||
834 | * inconsistent from the start to the end of | ||
835 | * the frame. However if the frame starts | ||
836 | * with slack, first_contact_touch will still | ||
837 | * be 0 and we will not get to this point. | ||
838 | */ | ||
839 | input_report_key(input, BTN_TOOL_DOUBLETAP, 1); | ||
840 | input_report_key(input, BTN_TOUCH, 1); | ||
841 | } else { | ||
842 | input_report_key(input, BTN_TOOL_DOUBLETAP, 0); | ||
843 | input_report_key(input, BTN_TOUCH, 0); | ||
762 | } | 844 | } |
845 | break; | ||
846 | |||
847 | default: | ||
848 | /* fall-back to the generic hidinput handling */ | ||
849 | return 0; | ||
763 | } | 850 | } |
764 | 851 | ||
852 | not_claimed_input: | ||
853 | |||
765 | /* we have handled the hidinput part, now remains hiddev */ | 854 | /* we have handled the hidinput part, now remains hiddev */ |
766 | if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_hid_event) | 855 | if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_hid_event) |
767 | hid->hiddev_hid_event(hid, field, usage, value); | 856 | hid->hiddev_hid_event(hid, field, usage, value); |
@@ -778,11 +867,12 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
778 | struct hid_report *report; | 867 | struct hid_report *report; |
779 | 868 | ||
780 | if (id->driver_data) | 869 | if (id->driver_data) |
781 | hdev->quirks |= HID_QUIRK_MULTI_INPUT; | 870 | hdev->quirks |= HID_QUIRK_MULTI_INPUT |
871 | | HID_QUIRK_NO_INIT_REPORTS; | ||
782 | 872 | ||
783 | nd = kmalloc(sizeof(struct ntrig_data), GFP_KERNEL); | 873 | nd = kmalloc(sizeof(struct ntrig_data), GFP_KERNEL); |
784 | if (!nd) { | 874 | if (!nd) { |
785 | dev_err(&hdev->dev, "cannot allocate N-Trig data\n"); | 875 | hid_err(hdev, "cannot allocate N-Trig data\n"); |
786 | return -ENOMEM; | 876 | return -ENOMEM; |
787 | } | 877 | } |
788 | 878 | ||
@@ -801,13 +891,13 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
801 | 891 | ||
802 | ret = hid_parse(hdev); | 892 | ret = hid_parse(hdev); |
803 | if (ret) { | 893 | if (ret) { |
804 | dev_err(&hdev->dev, "parse failed\n"); | 894 | hid_err(hdev, "parse failed\n"); |
805 | goto err_free; | 895 | goto err_free; |
806 | } | 896 | } |
807 | 897 | ||
808 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); | 898 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); |
809 | if (ret) { | 899 | if (ret) { |
810 | dev_err(&hdev->dev, "hw start failed\n"); | 900 | hid_err(hdev, "hw start failed\n"); |
811 | goto err_free; | 901 | goto err_free; |
812 | } | 902 | } |
813 | 903 | ||
@@ -845,8 +935,21 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
845 | 935 | ||
846 | /* This is needed for devices with more recent firmware versions */ | 936 | /* This is needed for devices with more recent firmware versions */ |
847 | report = hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[0x0a]; | 937 | report = hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[0x0a]; |
848 | if (report) | 938 | if (report) { |
849 | usbhid_submit_report(hdev, report, USB_DIR_OUT); | 939 | /* Let the device settle to ensure the wakeup message gets |
940 | * through */ | ||
941 | usbhid_wait_io(hdev); | ||
942 | usbhid_submit_report(hdev, report, USB_DIR_IN); | ||
943 | |||
944 | /* | ||
945 | * Sanity check: if the current mode is invalid reset it to | ||
946 | * something reasonable. | ||
947 | */ | ||
948 | if (ntrig_get_mode(hdev) >= 4) | ||
949 | ntrig_set_mode(hdev, 3); | ||
950 | } | ||
951 | |||
952 | ntrig_report_version(hdev); | ||
850 | 953 | ||
851 | ret = sysfs_create_group(&hdev->dev.kobj, | 954 | ret = sysfs_create_group(&hdev->dev.kobj, |
852 | &ntrig_attribute_group); | 955 | &ntrig_attribute_group); |
@@ -860,7 +963,7 @@ err_free: | |||
860 | static void ntrig_remove(struct hid_device *hdev) | 963 | static void ntrig_remove(struct hid_device *hdev) |
861 | { | 964 | { |
862 | sysfs_remove_group(&hdev->dev.kobj, | 965 | sysfs_remove_group(&hdev->dev.kobj, |
863 | &ntrig_attribute_group); | 966 | &ntrig_attribute_group); |
864 | hid_hw_stop(hdev); | 967 | hid_hw_stop(hdev); |
865 | kfree(hid_get_drvdata(hdev)); | 968 | kfree(hid_get_drvdata(hdev)); |
866 | } | 969 | } |
diff --git a/drivers/hid/hid-ortek.c b/drivers/hid/hid-ortek.c index aa9a960f73a4..0ffa1d2d64f0 100644 --- a/drivers/hid/hid-ortek.c +++ b/drivers/hid/hid-ortek.c | |||
@@ -1,9 +1,14 @@ | |||
1 | /* | 1 | /* |
2 | * HID driver for Ortek WKB-2000 (wireless keyboard + mouse trackpad). | 2 | * HID driver for various devices which are apparently based on the same chipset |
3 | * Fixes LogicalMaximum error in USB report description, see | 3 | * from certain vendor which produces chips that contain wrong LogicalMaximum |
4 | * http://bugzilla.kernel.org/show_bug.cgi?id=14787 | 4 | * value in their HID report descriptor. Currently supported devices are: |
5 | * | ||
6 | * Ortek PKB-1700 | ||
7 | * Ortek WKB-2000 | ||
8 | * Skycable wireless presenter | ||
5 | * | 9 | * |
6 | * Copyright (c) 2010 Johnathon Harris <jmharris@gmail.com> | 10 | * Copyright (c) 2010 Johnathon Harris <jmharris@gmail.com> |
11 | * Copyright (c) 2011 Jiri Kosina | ||
7 | */ | 12 | */ |
8 | 13 | ||
9 | /* | 14 | /* |
@@ -19,18 +24,23 @@ | |||
19 | 24 | ||
20 | #include "hid-ids.h" | 25 | #include "hid-ids.h" |
21 | 26 | ||
22 | static void ortek_report_fixup(struct hid_device *hdev, __u8 *rdesc, | 27 | static __u8 *ortek_report_fixup(struct hid_device *hdev, __u8 *rdesc, |
23 | unsigned int rsize) | 28 | unsigned int *rsize) |
24 | { | 29 | { |
25 | if (rsize >= 56 && rdesc[54] == 0x25 && rdesc[55] == 0x01) { | 30 | if (*rsize >= 56 && rdesc[54] == 0x25 && rdesc[55] == 0x01) { |
26 | dev_info(&hdev->dev, "Fixing up Ortek WKB-2000 " | 31 | hid_info(hdev, "Fixing up logical minimum in report descriptor (Ortek)\n"); |
27 | "report descriptor.\n"); | ||
28 | rdesc[55] = 0x92; | 32 | rdesc[55] = 0x92; |
33 | } else if (*rsize >= 54 && rdesc[52] == 0x25 && rdesc[53] == 0x01) { | ||
34 | hid_info(hdev, "Fixing up logical minimum in report descriptor (Skycable)\n"); | ||
35 | rdesc[53] = 0x65; | ||
29 | } | 36 | } |
37 | return rdesc; | ||
30 | } | 38 | } |
31 | 39 | ||
32 | static const struct hid_device_id ortek_devices[] = { | 40 | static const struct hid_device_id ortek_devices[] = { |
41 | { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_PKB1700) }, | ||
33 | { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) }, | 42 | { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) }, |
43 | { HID_USB_DEVICE(USB_VENDOR_ID_SKYCABLE, USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER) }, | ||
34 | { } | 44 | { } |
35 | }; | 45 | }; |
36 | MODULE_DEVICE_TABLE(hid, ortek_devices); | 46 | MODULE_DEVICE_TABLE(hid, ortek_devices); |
diff --git a/drivers/hid/hid-petalynx.c b/drivers/hid/hid-petalynx.c index 500fbd0652dc..f1ea3ff8a98d 100644 --- a/drivers/hid/hid-petalynx.c +++ b/drivers/hid/hid-petalynx.c | |||
@@ -23,17 +23,17 @@ | |||
23 | #include "hid-ids.h" | 23 | #include "hid-ids.h" |
24 | 24 | ||
25 | /* Petalynx Maxter Remote has maximum for consumer page set too low */ | 25 | /* Petalynx Maxter Remote has maximum for consumer page set too low */ |
26 | static void pl_report_fixup(struct hid_device *hdev, __u8 *rdesc, | 26 | static __u8 *pl_report_fixup(struct hid_device *hdev, __u8 *rdesc, |
27 | unsigned int rsize) | 27 | unsigned int *rsize) |
28 | { | 28 | { |
29 | if (rsize >= 60 && rdesc[39] == 0x2a && rdesc[40] == 0xf5 && | 29 | if (*rsize >= 60 && rdesc[39] == 0x2a && rdesc[40] == 0xf5 && |
30 | rdesc[41] == 0x00 && rdesc[59] == 0x26 && | 30 | rdesc[41] == 0x00 && rdesc[59] == 0x26 && |
31 | rdesc[60] == 0xf9 && rdesc[61] == 0x00) { | 31 | rdesc[60] == 0xf9 && rdesc[61] == 0x00) { |
32 | dev_info(&hdev->dev, "fixing up Petalynx Maxter Remote report " | 32 | hid_info(hdev, "fixing up Petalynx Maxter Remote report descriptor\n"); |
33 | "descriptor\n"); | ||
34 | rdesc[60] = 0xfa; | 33 | rdesc[60] = 0xfa; |
35 | rdesc[40] = 0xfa; | 34 | rdesc[40] = 0xfa; |
36 | } | 35 | } |
36 | return rdesc; | ||
37 | } | 37 | } |
38 | 38 | ||
39 | #define pl_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ | 39 | #define pl_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ |
@@ -76,13 +76,13 @@ static int pl_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
76 | 76 | ||
77 | ret = hid_parse(hdev); | 77 | ret = hid_parse(hdev); |
78 | if (ret) { | 78 | if (ret) { |
79 | dev_err(&hdev->dev, "parse failed\n"); | 79 | hid_err(hdev, "parse failed\n"); |
80 | goto err_free; | 80 | goto err_free; |
81 | } | 81 | } |
82 | 82 | ||
83 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); | 83 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); |
84 | if (ret) { | 84 | if (ret) { |
85 | dev_err(&hdev->dev, "hw start failed\n"); | 85 | hid_err(hdev, "hw start failed\n"); |
86 | goto err_free; | 86 | goto err_free; |
87 | } | 87 | } |
88 | 88 | ||
diff --git a/drivers/hid/hid-picolcd.c b/drivers/hid/hid-picolcd.c index bc2e07740628..9d8710f8bc79 100644 --- a/drivers/hid/hid-picolcd.c +++ b/drivers/hid/hid-picolcd.c | |||
@@ -253,7 +253,7 @@ static struct hid_report *picolcd_report(int id, struct hid_device *hdev, int di | |||
253 | if (report->id == id) | 253 | if (report->id == id) |
254 | return report; | 254 | return report; |
255 | } | 255 | } |
256 | dev_warn(&hdev->dev, "No report with id 0x%x found\n", id); | 256 | hid_warn(hdev, "No report with id 0x%x found\n", id); |
257 | return NULL; | 257 | return NULL; |
258 | } | 258 | } |
259 | 259 | ||
@@ -944,6 +944,7 @@ static int picolcd_init_backlight(struct picolcd_data *data, struct hid_report * | |||
944 | } | 944 | } |
945 | 945 | ||
946 | memset(&props, 0, sizeof(props)); | 946 | memset(&props, 0, sizeof(props)); |
947 | props.type = BACKLIGHT_RAW; | ||
947 | props.max_brightness = 0xff; | 948 | props.max_brightness = 0xff; |
948 | bdev = backlight_device_register(dev_name(dev), dev, data, | 949 | bdev = backlight_device_register(dev_name(dev), dev, data, |
949 | &picolcd_blops, &props); | 950 | &picolcd_blops, &props); |
@@ -1329,7 +1330,7 @@ static int picolcd_check_version(struct hid_device *hdev) | |||
1329 | 1330 | ||
1330 | verinfo = picolcd_send_and_wait(hdev, REPORT_VERSION, NULL, 0); | 1331 | verinfo = picolcd_send_and_wait(hdev, REPORT_VERSION, NULL, 0); |
1331 | if (!verinfo) { | 1332 | if (!verinfo) { |
1332 | dev_err(&hdev->dev, "no version response from PicoLCD"); | 1333 | hid_err(hdev, "no version response from PicoLCD\n"); |
1333 | return -ENODEV; | 1334 | return -ENODEV; |
1334 | } | 1335 | } |
1335 | 1336 | ||
@@ -1337,14 +1338,14 @@ static int picolcd_check_version(struct hid_device *hdev) | |||
1337 | data->version[0] = verinfo->raw_data[1]; | 1338 | data->version[0] = verinfo->raw_data[1]; |
1338 | data->version[1] = verinfo->raw_data[0]; | 1339 | data->version[1] = verinfo->raw_data[0]; |
1339 | if (data->status & PICOLCD_BOOTLOADER) { | 1340 | if (data->status & PICOLCD_BOOTLOADER) { |
1340 | dev_info(&hdev->dev, "PicoLCD, bootloader version %d.%d\n", | 1341 | hid_info(hdev, "PicoLCD, bootloader version %d.%d\n", |
1341 | verinfo->raw_data[1], verinfo->raw_data[0]); | 1342 | verinfo->raw_data[1], verinfo->raw_data[0]); |
1342 | } else { | 1343 | } else { |
1343 | dev_info(&hdev->dev, "PicoLCD, firmware version %d.%d\n", | 1344 | hid_info(hdev, "PicoLCD, firmware version %d.%d\n", |
1344 | verinfo->raw_data[1], verinfo->raw_data[0]); | 1345 | verinfo->raw_data[1], verinfo->raw_data[0]); |
1345 | } | 1346 | } |
1346 | } else { | 1347 | } else { |
1347 | dev_err(&hdev->dev, "confused, got unexpected version response from PicoLCD\n"); | 1348 | hid_err(hdev, "confused, got unexpected version response from PicoLCD\n"); |
1348 | ret = -EINVAL; | 1349 | ret = -EINVAL; |
1349 | } | 1350 | } |
1350 | kfree(verinfo); | 1351 | kfree(verinfo); |
@@ -1544,7 +1545,7 @@ static ssize_t picolcd_debug_eeprom_read(struct file *f, char __user *u, | |||
1544 | 1545 | ||
1545 | /* prepare buffer with info about what we want to read (addr & len) */ | 1546 | /* prepare buffer with info about what we want to read (addr & len) */ |
1546 | raw_data[0] = *off & 0xff; | 1547 | raw_data[0] = *off & 0xff; |
1547 | raw_data[1] = (*off >> 8) && 0xff; | 1548 | raw_data[1] = (*off >> 8) & 0xff; |
1548 | raw_data[2] = s < 20 ? s : 20; | 1549 | raw_data[2] = s < 20 ? s : 20; |
1549 | if (*off + raw_data[2] > 0xff) | 1550 | if (*off + raw_data[2] > 0xff) |
1550 | raw_data[2] = 0x100 - *off; | 1551 | raw_data[2] = 0x100 - *off; |
@@ -1583,12 +1584,12 @@ static ssize_t picolcd_debug_eeprom_write(struct file *f, const char __user *u, | |||
1583 | 1584 | ||
1584 | memset(raw_data, 0, sizeof(raw_data)); | 1585 | memset(raw_data, 0, sizeof(raw_data)); |
1585 | raw_data[0] = *off & 0xff; | 1586 | raw_data[0] = *off & 0xff; |
1586 | raw_data[1] = (*off >> 8) && 0xff; | 1587 | raw_data[1] = (*off >> 8) & 0xff; |
1587 | raw_data[2] = s < 20 ? s : 20; | 1588 | raw_data[2] = min((size_t)20, s); |
1588 | if (*off + raw_data[2] > 0xff) | 1589 | if (*off + raw_data[2] > 0xff) |
1589 | raw_data[2] = 0x100 - *off; | 1590 | raw_data[2] = 0x100 - *off; |
1590 | 1591 | ||
1591 | if (copy_from_user(raw_data+3, u, raw_data[2])) | 1592 | if (copy_from_user(raw_data+3, u, min((u8)20, raw_data[2]))) |
1592 | return -EFAULT; | 1593 | return -EFAULT; |
1593 | resp = picolcd_send_and_wait(data->hdev, REPORT_EE_WRITE, raw_data, | 1594 | resp = picolcd_send_and_wait(data->hdev, REPORT_EE_WRITE, raw_data, |
1594 | sizeof(raw_data)); | 1595 | sizeof(raw_data)); |
@@ -1805,13 +1806,13 @@ static ssize_t picolcd_debug_flash_write(struct file *f, const char __user *u, | |||
1805 | /* | 1806 | /* |
1806 | * Notes: | 1807 | * Notes: |
1807 | * - concurrent writing is prevented by mutex and all writes must be | 1808 | * - concurrent writing is prevented by mutex and all writes must be |
1808 | * n*64 bytes and 64-byte aligned, each write being preceeded by an | 1809 | * n*64 bytes and 64-byte aligned, each write being preceded by an |
1809 | * ERASE which erases a 64byte block. | 1810 | * ERASE which erases a 64byte block. |
1810 | * If less than requested was written or an error is returned for an | 1811 | * If less than requested was written or an error is returned for an |
1811 | * otherwise correct write request the next 64-byte block which should | 1812 | * otherwise correct write request the next 64-byte block which should |
1812 | * have been written is in undefined state (mostly: original, erased, | 1813 | * have been written is in undefined state (mostly: original, erased, |
1813 | * (half-)written with write error) | 1814 | * (half-)written with write error) |
1814 | * - reading can happend without special restriction | 1815 | * - reading can happen without special restriction |
1815 | */ | 1816 | */ |
1816 | static const struct file_operations picolcd_debug_flash_fops = { | 1817 | static const struct file_operations picolcd_debug_flash_fops = { |
1817 | .owner = THIS_MODULE, | 1818 | .owner = THIS_MODULE, |
@@ -1867,6 +1868,7 @@ static void picolcd_debug_out_report(struct picolcd_data *data, | |||
1867 | report->id, raw_size); | 1868 | report->id, raw_size); |
1868 | hid_debug_event(hdev, buff); | 1869 | hid_debug_event(hdev, buff); |
1869 | if (raw_size + 5 > sizeof(raw_data)) { | 1870 | if (raw_size + 5 > sizeof(raw_data)) { |
1871 | kfree(buff); | ||
1870 | hid_debug_event(hdev, " TOO BIG\n"); | 1872 | hid_debug_event(hdev, " TOO BIG\n"); |
1871 | return; | 1873 | return; |
1872 | } else { | 1874 | } else { |
@@ -2328,8 +2330,7 @@ static void picolcd_init_devfs(struct picolcd_data *data, | |||
2328 | (flash_w ? S_IWUSR : 0) | (flash_r ? S_IRUSR : 0), | 2330 | (flash_w ? S_IWUSR : 0) | (flash_r ? S_IRUSR : 0), |
2329 | hdev->debug_dir, data, &picolcd_debug_flash_fops); | 2331 | hdev->debug_dir, data, &picolcd_debug_flash_fops); |
2330 | } else if (flash_r || flash_w) | 2332 | } else if (flash_r || flash_w) |
2331 | dev_warn(&hdev->dev, "Unexpected FLASH access reports, " | 2333 | hid_warn(hdev, "Unexpected FLASH access reports, please submit rdesc for review\n"); |
2332 | "please submit rdesc for review\n"); | ||
2333 | } | 2334 | } |
2334 | 2335 | ||
2335 | static void picolcd_exit_devfs(struct picolcd_data *data) | 2336 | static void picolcd_exit_devfs(struct picolcd_data *data) |
@@ -2457,13 +2458,13 @@ static int picolcd_init_keys(struct picolcd_data *data, | |||
2457 | return -ENODEV; | 2458 | return -ENODEV; |
2458 | if (report->maxfield != 1 || report->field[0]->report_count != 2 || | 2459 | if (report->maxfield != 1 || report->field[0]->report_count != 2 || |
2459 | report->field[0]->report_size != 8) { | 2460 | report->field[0]->report_size != 8) { |
2460 | dev_err(&hdev->dev, "unsupported KEY_STATE report"); | 2461 | hid_err(hdev, "unsupported KEY_STATE report\n"); |
2461 | return -EINVAL; | 2462 | return -EINVAL; |
2462 | } | 2463 | } |
2463 | 2464 | ||
2464 | idev = input_allocate_device(); | 2465 | idev = input_allocate_device(); |
2465 | if (idev == NULL) { | 2466 | if (idev == NULL) { |
2466 | dev_err(&hdev->dev, "failed to allocate input device"); | 2467 | hid_err(hdev, "failed to allocate input device\n"); |
2467 | return -ENOMEM; | 2468 | return -ENOMEM; |
2468 | } | 2469 | } |
2469 | input_set_drvdata(idev, hdev); | 2470 | input_set_drvdata(idev, hdev); |
@@ -2485,7 +2486,7 @@ static int picolcd_init_keys(struct picolcd_data *data, | |||
2485 | input_set_capability(idev, EV_KEY, data->keycode[i]); | 2486 | input_set_capability(idev, EV_KEY, data->keycode[i]); |
2486 | error = input_register_device(idev); | 2487 | error = input_register_device(idev); |
2487 | if (error) { | 2488 | if (error) { |
2488 | dev_err(&hdev->dev, "error registering the input device"); | 2489 | hid_err(hdev, "error registering the input device\n"); |
2489 | input_free_device(idev); | 2490 | input_free_device(idev); |
2490 | return error; | 2491 | return error; |
2491 | } | 2492 | } |
@@ -2522,9 +2523,8 @@ static int picolcd_probe_lcd(struct hid_device *hdev, struct picolcd_data *data) | |||
2522 | return error; | 2523 | return error; |
2523 | 2524 | ||
2524 | if (data->version[0] != 0 && data->version[1] != 3) | 2525 | if (data->version[0] != 0 && data->version[1] != 3) |
2525 | dev_info(&hdev->dev, "Device with untested firmware revision, " | 2526 | hid_info(hdev, "Device with untested firmware revision, please submit /sys/kernel/debug/hid/%s/rdesc for this device.\n", |
2526 | "please submit /sys/kernel/debug/hid/%s/rdesc for this device.\n", | 2527 | dev_name(&hdev->dev)); |
2527 | dev_name(&hdev->dev)); | ||
2528 | 2528 | ||
2529 | /* Setup keypad input device */ | 2529 | /* Setup keypad input device */ |
2530 | error = picolcd_init_keys(data, picolcd_in_report(REPORT_KEY_STATE, hdev)); | 2530 | error = picolcd_init_keys(data, picolcd_in_report(REPORT_KEY_STATE, hdev)); |
@@ -2581,9 +2581,8 @@ static int picolcd_probe_bootloader(struct hid_device *hdev, struct picolcd_data | |||
2581 | return error; | 2581 | return error; |
2582 | 2582 | ||
2583 | if (data->version[0] != 1 && data->version[1] != 0) | 2583 | if (data->version[0] != 1 && data->version[1] != 0) |
2584 | dev_info(&hdev->dev, "Device with untested bootloader revision, " | 2584 | hid_info(hdev, "Device with untested bootloader revision, please submit /sys/kernel/debug/hid/%s/rdesc for this device.\n", |
2585 | "please submit /sys/kernel/debug/hid/%s/rdesc for this device.\n", | 2585 | dev_name(&hdev->dev)); |
2586 | dev_name(&hdev->dev)); | ||
2587 | 2586 | ||
2588 | picolcd_init_devfs(data, NULL, NULL, | 2587 | picolcd_init_devfs(data, NULL, NULL, |
2589 | picolcd_out_report(REPORT_BL_READ_MEMORY, hdev), | 2588 | picolcd_out_report(REPORT_BL_READ_MEMORY, hdev), |
@@ -2605,7 +2604,7 @@ static int picolcd_probe(struct hid_device *hdev, | |||
2605 | */ | 2604 | */ |
2606 | data = kzalloc(sizeof(struct picolcd_data), GFP_KERNEL); | 2605 | data = kzalloc(sizeof(struct picolcd_data), GFP_KERNEL); |
2607 | if (data == NULL) { | 2606 | if (data == NULL) { |
2608 | dev_err(&hdev->dev, "can't allocate space for Minibox PicoLCD device data\n"); | 2607 | hid_err(hdev, "can't allocate space for Minibox PicoLCD device data\n"); |
2609 | error = -ENOMEM; | 2608 | error = -ENOMEM; |
2610 | goto err_no_cleanup; | 2609 | goto err_no_cleanup; |
2611 | } | 2610 | } |
@@ -2621,7 +2620,7 @@ static int picolcd_probe(struct hid_device *hdev, | |||
2621 | /* Parse the device reports and start it up */ | 2620 | /* Parse the device reports and start it up */ |
2622 | error = hid_parse(hdev); | 2621 | error = hid_parse(hdev); |
2623 | if (error) { | 2622 | if (error) { |
2624 | dev_err(&hdev->dev, "device report parse failed\n"); | 2623 | hid_err(hdev, "device report parse failed\n"); |
2625 | goto err_cleanup_data; | 2624 | goto err_cleanup_data; |
2626 | } | 2625 | } |
2627 | 2626 | ||
@@ -2631,25 +2630,25 @@ static int picolcd_probe(struct hid_device *hdev, | |||
2631 | error = hid_hw_start(hdev, 0); | 2630 | error = hid_hw_start(hdev, 0); |
2632 | hdev->claimed = 0; | 2631 | hdev->claimed = 0; |
2633 | if (error) { | 2632 | if (error) { |
2634 | dev_err(&hdev->dev, "hardware start failed\n"); | 2633 | hid_err(hdev, "hardware start failed\n"); |
2635 | goto err_cleanup_data; | 2634 | goto err_cleanup_data; |
2636 | } | 2635 | } |
2637 | 2636 | ||
2638 | error = hdev->ll_driver->open(hdev); | 2637 | error = hid_hw_open(hdev); |
2639 | if (error) { | 2638 | if (error) { |
2640 | dev_err(&hdev->dev, "failed to open input interrupt pipe for key and IR events\n"); | 2639 | hid_err(hdev, "failed to open input interrupt pipe for key and IR events\n"); |
2641 | goto err_cleanup_hid_hw; | 2640 | goto err_cleanup_hid_hw; |
2642 | } | 2641 | } |
2643 | 2642 | ||
2644 | error = device_create_file(&hdev->dev, &dev_attr_operation_mode_delay); | 2643 | error = device_create_file(&hdev->dev, &dev_attr_operation_mode_delay); |
2645 | if (error) { | 2644 | if (error) { |
2646 | dev_err(&hdev->dev, "failed to create sysfs attributes\n"); | 2645 | hid_err(hdev, "failed to create sysfs attributes\n"); |
2647 | goto err_cleanup_hid_ll; | 2646 | goto err_cleanup_hid_ll; |
2648 | } | 2647 | } |
2649 | 2648 | ||
2650 | error = device_create_file(&hdev->dev, &dev_attr_operation_mode); | 2649 | error = device_create_file(&hdev->dev, &dev_attr_operation_mode); |
2651 | if (error) { | 2650 | if (error) { |
2652 | dev_err(&hdev->dev, "failed to create sysfs attributes\n"); | 2651 | hid_err(hdev, "failed to create sysfs attributes\n"); |
2653 | goto err_cleanup_sysfs1; | 2652 | goto err_cleanup_sysfs1; |
2654 | } | 2653 | } |
2655 | 2654 | ||
@@ -2668,7 +2667,7 @@ err_cleanup_sysfs2: | |||
2668 | err_cleanup_sysfs1: | 2667 | err_cleanup_sysfs1: |
2669 | device_remove_file(&hdev->dev, &dev_attr_operation_mode_delay); | 2668 | device_remove_file(&hdev->dev, &dev_attr_operation_mode_delay); |
2670 | err_cleanup_hid_ll: | 2669 | err_cleanup_hid_ll: |
2671 | hdev->ll_driver->close(hdev); | 2670 | hid_hw_close(hdev); |
2672 | err_cleanup_hid_hw: | 2671 | err_cleanup_hid_hw: |
2673 | hid_hw_stop(hdev); | 2672 | hid_hw_stop(hdev); |
2674 | err_cleanup_data: | 2673 | err_cleanup_data: |
@@ -2699,7 +2698,7 @@ static void picolcd_remove(struct hid_device *hdev) | |||
2699 | picolcd_exit_devfs(data); | 2698 | picolcd_exit_devfs(data); |
2700 | device_remove_file(&hdev->dev, &dev_attr_operation_mode); | 2699 | device_remove_file(&hdev->dev, &dev_attr_operation_mode); |
2701 | device_remove_file(&hdev->dev, &dev_attr_operation_mode_delay); | 2700 | device_remove_file(&hdev->dev, &dev_attr_operation_mode_delay); |
2702 | hdev->ll_driver->close(hdev); | 2701 | hid_hw_close(hdev); |
2703 | hid_hw_stop(hdev); | 2702 | hid_hw_stop(hdev); |
2704 | hid_set_drvdata(hdev, NULL); | 2703 | hid_set_drvdata(hdev, NULL); |
2705 | 2704 | ||
@@ -2753,7 +2752,7 @@ static void __exit picolcd_exit(void) | |||
2753 | { | 2752 | { |
2754 | hid_unregister_driver(&picolcd_driver); | 2753 | hid_unregister_driver(&picolcd_driver); |
2755 | #ifdef CONFIG_HID_PICOLCD_FB | 2754 | #ifdef CONFIG_HID_PICOLCD_FB |
2756 | flush_scheduled_work(); | 2755 | flush_work_sync(&picolcd_fb_cleanup); |
2757 | WARN_ON(fb_pending); | 2756 | WARN_ON(fb_pending); |
2758 | #endif | 2757 | #endif |
2759 | } | 2758 | } |
diff --git a/drivers/hid/hid-pl.c b/drivers/hid/hid-pl.c index 9f41e2bd8483..06e5300d43d2 100644 --- a/drivers/hid/hid-pl.c +++ b/drivers/hid/hid-pl.c | |||
@@ -103,7 +103,7 @@ static int plff_init(struct hid_device *hid) | |||
103 | */ | 103 | */ |
104 | 104 | ||
105 | if (list_empty(report_list)) { | 105 | if (list_empty(report_list)) { |
106 | dev_err(&hid->dev, "no output reports found\n"); | 106 | hid_err(hid, "no output reports found\n"); |
107 | return -ENODEV; | 107 | return -ENODEV; |
108 | } | 108 | } |
109 | 109 | ||
@@ -112,14 +112,13 @@ static int plff_init(struct hid_device *hid) | |||
112 | report_ptr = report_ptr->next; | 112 | report_ptr = report_ptr->next; |
113 | 113 | ||
114 | if (report_ptr == report_list) { | 114 | if (report_ptr == report_list) { |
115 | dev_err(&hid->dev, "required output report is " | 115 | hid_err(hid, "required output report is missing\n"); |
116 | "missing\n"); | ||
117 | return -ENODEV; | 116 | return -ENODEV; |
118 | } | 117 | } |
119 | 118 | ||
120 | report = list_entry(report_ptr, struct hid_report, list); | 119 | report = list_entry(report_ptr, struct hid_report, list); |
121 | if (report->maxfield < 1) { | 120 | if (report->maxfield < 1) { |
122 | dev_err(&hid->dev, "no fields in the report\n"); | 121 | hid_err(hid, "no fields in the report\n"); |
123 | return -ENODEV; | 122 | return -ENODEV; |
124 | } | 123 | } |
125 | 124 | ||
@@ -137,7 +136,7 @@ static int plff_init(struct hid_device *hid) | |||
137 | weak = &report->field[3]->value[0]; | 136 | weak = &report->field[3]->value[0]; |
138 | debug("detected 4-field device"); | 137 | debug("detected 4-field device"); |
139 | } else { | 138 | } else { |
140 | dev_err(&hid->dev, "not enough fields or values\n"); | 139 | hid_err(hid, "not enough fields or values\n"); |
141 | return -ENODEV; | 140 | return -ENODEV; |
142 | } | 141 | } |
143 | 142 | ||
@@ -164,8 +163,7 @@ static int plff_init(struct hid_device *hid) | |||
164 | usbhid_submit_report(hid, plff->report, USB_DIR_OUT); | 163 | usbhid_submit_report(hid, plff->report, USB_DIR_OUT); |
165 | } | 164 | } |
166 | 165 | ||
167 | dev_info(&hid->dev, "Force feedback for PantherLord/GreenAsia " | 166 | hid_info(hid, "Force feedback for PantherLord/GreenAsia devices by Anssi Hannula <anssi.hannula@gmail.com>\n"); |
168 | "devices by Anssi Hannula <anssi.hannula@gmail.com>\n"); | ||
169 | 167 | ||
170 | return 0; | 168 | return 0; |
171 | } | 169 | } |
@@ -185,13 +183,13 @@ static int pl_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
185 | 183 | ||
186 | ret = hid_parse(hdev); | 184 | ret = hid_parse(hdev); |
187 | if (ret) { | 185 | if (ret) { |
188 | dev_err(&hdev->dev, "parse failed\n"); | 186 | hid_err(hdev, "parse failed\n"); |
189 | goto err; | 187 | goto err; |
190 | } | 188 | } |
191 | 189 | ||
192 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); | 190 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); |
193 | if (ret) { | 191 | if (ret) { |
194 | dev_err(&hdev->dev, "hw start failed\n"); | 192 | hid_err(hdev, "hw start failed\n"); |
195 | goto err; | 193 | goto err; |
196 | } | 194 | } |
197 | 195 | ||
diff --git a/drivers/hid/hid-prodikeys.c b/drivers/hid/hid-prodikeys.c index 845f428b8090..ab19f2905d27 100644 --- a/drivers/hid/hid-prodikeys.c +++ b/drivers/hid/hid-prodikeys.c | |||
@@ -16,6 +16,8 @@ | |||
16 | * any later version. | 16 | * any later version. |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
20 | |||
19 | #include <linux/device.h> | 21 | #include <linux/device.h> |
20 | #include <linux/module.h> | 22 | #include <linux/module.h> |
21 | #include <linux/usb.h> | 23 | #include <linux/usb.h> |
@@ -130,7 +132,7 @@ static ssize_t store_channel(struct device *dev, | |||
130 | return -EINVAL; | 132 | return -EINVAL; |
131 | } | 133 | } |
132 | 134 | ||
133 | static DEVICE_ATTR(channel, S_IRUGO | S_IWUGO, show_channel, | 135 | static DEVICE_ATTR(channel, S_IRUGO | S_IWUSR | S_IWGRP , show_channel, |
134 | store_channel); | 136 | store_channel); |
135 | 137 | ||
136 | static struct device_attribute *sysfs_device_attr_channel = { | 138 | static struct device_attribute *sysfs_device_attr_channel = { |
@@ -169,7 +171,7 @@ static ssize_t store_sustain(struct device *dev, | |||
169 | return -EINVAL; | 171 | return -EINVAL; |
170 | } | 172 | } |
171 | 173 | ||
172 | static DEVICE_ATTR(sustain, S_IRUGO | S_IWUGO, show_sustain, | 174 | static DEVICE_ATTR(sustain, S_IRUGO | S_IWUSR | S_IWGRP, show_sustain, |
173 | store_sustain); | 175 | store_sustain); |
174 | 176 | ||
175 | static struct device_attribute *sysfs_device_attr_sustain = { | 177 | static struct device_attribute *sysfs_device_attr_sustain = { |
@@ -207,7 +209,7 @@ static ssize_t store_octave(struct device *dev, | |||
207 | return -EINVAL; | 209 | return -EINVAL; |
208 | } | 210 | } |
209 | 211 | ||
210 | static DEVICE_ATTR(octave, S_IRUGO | S_IWUGO, show_octave, | 212 | static DEVICE_ATTR(octave, S_IRUGO | S_IWUSR | S_IWGRP, show_octave, |
211 | store_octave); | 213 | store_octave); |
212 | 214 | ||
213 | static struct device_attribute *sysfs_device_attr_octave = { | 215 | static struct device_attribute *sysfs_device_attr_octave = { |
@@ -285,11 +287,11 @@ static int pcmidi_get_output_report(struct pcmidi_snd *pm) | |||
285 | continue; | 287 | continue; |
286 | 288 | ||
287 | if (report->maxfield < 1) { | 289 | if (report->maxfield < 1) { |
288 | dev_err(&hdev->dev, "output report is empty\n"); | 290 | hid_err(hdev, "output report is empty\n"); |
289 | break; | 291 | break; |
290 | } | 292 | } |
291 | if (report->field[0]->report_count != 2) { | 293 | if (report->field[0]->report_count != 2) { |
292 | dev_err(&hdev->dev, "field count too low\n"); | 294 | hid_err(hdev, "field count too low\n"); |
293 | break; | 295 | break; |
294 | } | 296 | } |
295 | pm->pcmidi_report6 = report; | 297 | pm->pcmidi_report6 = report; |
@@ -740,17 +742,18 @@ int pcmidi_snd_terminate(struct pcmidi_snd *pm) | |||
740 | /* | 742 | /* |
741 | * PC-MIDI report descriptor for report id is wrong. | 743 | * PC-MIDI report descriptor for report id is wrong. |
742 | */ | 744 | */ |
743 | static void pk_report_fixup(struct hid_device *hdev, __u8 *rdesc, | 745 | static __u8 *pk_report_fixup(struct hid_device *hdev, __u8 *rdesc, |
744 | unsigned int rsize) | 746 | unsigned int *rsize) |
745 | { | 747 | { |
746 | if (rsize == 178 && | 748 | if (*rsize == 178 && |
747 | rdesc[111] == 0x06 && rdesc[112] == 0x00 && | 749 | rdesc[111] == 0x06 && rdesc[112] == 0x00 && |
748 | rdesc[113] == 0xff) { | 750 | rdesc[113] == 0xff) { |
749 | dev_info(&hdev->dev, "fixing up pc-midi keyboard report " | 751 | hid_info(hdev, |
750 | "descriptor\n"); | 752 | "fixing up pc-midi keyboard report descriptor\n"); |
751 | 753 | ||
752 | rdesc[144] = 0x18; /* report 4: was 0x10 report count */ | 754 | rdesc[144] = 0x18; /* report 4: was 0x10 report count */ |
753 | } | 755 | } |
756 | return rdesc; | ||
754 | } | 757 | } |
755 | 758 | ||
756 | static int pk_input_mapping(struct hid_device *hdev, struct hid_input *hi, | 759 | static int pk_input_mapping(struct hid_device *hdev, struct hid_input *hi, |
@@ -804,7 +807,7 @@ static int pk_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
804 | 807 | ||
805 | pk = kzalloc(sizeof(*pk), GFP_KERNEL); | 808 | pk = kzalloc(sizeof(*pk), GFP_KERNEL); |
806 | if (pk == NULL) { | 809 | if (pk == NULL) { |
807 | dev_err(&hdev->dev, "prodikeys: can't alloc descriptor\n"); | 810 | hid_err(hdev, "can't alloc descriptor\n"); |
808 | return -ENOMEM; | 811 | return -ENOMEM; |
809 | } | 812 | } |
810 | 813 | ||
@@ -812,8 +815,7 @@ static int pk_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
812 | 815 | ||
813 | pm = kzalloc(sizeof(*pm), GFP_KERNEL); | 816 | pm = kzalloc(sizeof(*pm), GFP_KERNEL); |
814 | if (pm == NULL) { | 817 | if (pm == NULL) { |
815 | dev_err(&hdev->dev, | 818 | hid_err(hdev, "can't alloc descriptor\n"); |
816 | "prodikeys: can't alloc descriptor\n"); | ||
817 | ret = -ENOMEM; | 819 | ret = -ENOMEM; |
818 | goto err_free; | 820 | goto err_free; |
819 | } | 821 | } |
@@ -826,7 +828,7 @@ static int pk_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
826 | 828 | ||
827 | ret = hid_parse(hdev); | 829 | ret = hid_parse(hdev); |
828 | if (ret) { | 830 | if (ret) { |
829 | dev_err(&hdev->dev, "prodikeys: hid parse failed\n"); | 831 | hid_err(hdev, "hid parse failed\n"); |
830 | goto err_free; | 832 | goto err_free; |
831 | } | 833 | } |
832 | 834 | ||
@@ -836,7 +838,7 @@ static int pk_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
836 | 838 | ||
837 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); | 839 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); |
838 | if (ret) { | 840 | if (ret) { |
839 | dev_err(&hdev->dev, "prodikeys: hw start failed\n"); | 841 | hid_err(hdev, "hw start failed\n"); |
840 | goto err_free; | 842 | goto err_free; |
841 | } | 843 | } |
842 | 844 | ||
@@ -895,7 +897,7 @@ static int pk_init(void) | |||
895 | 897 | ||
896 | ret = hid_register_driver(&pk_driver); | 898 | ret = hid_register_driver(&pk_driver); |
897 | if (ret) | 899 | if (ret) |
898 | printk(KERN_ERR "can't register prodikeys driver\n"); | 900 | pr_err("can't register prodikeys driver\n"); |
899 | 901 | ||
900 | return ret; | 902 | return ret; |
901 | } | 903 | } |
diff --git a/drivers/hid/hid-quanta.c b/drivers/hid/hid-quanta.c index 54d3db50605b..87a54df4d4ac 100644 --- a/drivers/hid/hid-quanta.c +++ b/drivers/hid/hid-quanta.c | |||
@@ -195,7 +195,7 @@ static int quanta_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
195 | 195 | ||
196 | td = kmalloc(sizeof(struct quanta_data), GFP_KERNEL); | 196 | td = kmalloc(sizeof(struct quanta_data), GFP_KERNEL); |
197 | if (!td) { | 197 | if (!td) { |
198 | dev_err(&hdev->dev, "cannot allocate Quanta Touch data\n"); | 198 | hid_err(hdev, "cannot allocate Quanta Touch data\n"); |
199 | return -ENOMEM; | 199 | return -ENOMEM; |
200 | } | 200 | } |
201 | td->valid = false; | 201 | td->valid = false; |
diff --git a/drivers/hid/hid-roccat-arvo.c b/drivers/hid/hid-roccat-arvo.c new file mode 100644 index 000000000000..2307471d96dc --- /dev/null +++ b/drivers/hid/hid-roccat-arvo.c | |||
@@ -0,0 +1,450 @@ | |||
1 | /* | ||
2 | * Roccat Arvo driver for Linux | ||
3 | * | ||
4 | * Copyright (c) 2011 Stefan Achatz <erazor_de@users.sourceforge.net> | ||
5 | */ | ||
6 | |||
7 | /* | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the Free | ||
10 | * Software Foundation; either version 2 of the License, or (at your option) | ||
11 | * any later version. | ||
12 | */ | ||
13 | |||
14 | /* | ||
15 | * Roccat Arvo is a gamer keyboard with 5 macro keys that can be configured in | ||
16 | * 5 profiles. | ||
17 | */ | ||
18 | |||
19 | #include <linux/device.h> | ||
20 | #include <linux/input.h> | ||
21 | #include <linux/hid.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/hid-roccat.h> | ||
25 | #include "hid-ids.h" | ||
26 | #include "hid-roccat-common.h" | ||
27 | #include "hid-roccat-arvo.h" | ||
28 | |||
29 | static struct class *arvo_class; | ||
30 | |||
31 | static ssize_t arvo_sysfs_show_mode_key(struct device *dev, | ||
32 | struct device_attribute *attr, char *buf) | ||
33 | { | ||
34 | struct arvo_device *arvo = | ||
35 | hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); | ||
36 | struct usb_device *usb_dev = | ||
37 | interface_to_usbdev(to_usb_interface(dev->parent->parent)); | ||
38 | struct arvo_mode_key temp_buf; | ||
39 | int retval; | ||
40 | |||
41 | mutex_lock(&arvo->arvo_lock); | ||
42 | retval = roccat_common_receive(usb_dev, ARVO_USB_COMMAND_MODE_KEY, | ||
43 | &temp_buf, sizeof(struct arvo_mode_key)); | ||
44 | mutex_unlock(&arvo->arvo_lock); | ||
45 | if (retval) | ||
46 | return retval; | ||
47 | |||
48 | return snprintf(buf, PAGE_SIZE, "%d\n", temp_buf.state); | ||
49 | } | ||
50 | |||
51 | static ssize_t arvo_sysfs_set_mode_key(struct device *dev, | ||
52 | struct device_attribute *attr, char const *buf, size_t size) | ||
53 | { | ||
54 | struct arvo_device *arvo = | ||
55 | hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); | ||
56 | struct usb_device *usb_dev = | ||
57 | interface_to_usbdev(to_usb_interface(dev->parent->parent)); | ||
58 | struct arvo_mode_key temp_buf; | ||
59 | unsigned long state; | ||
60 | int retval; | ||
61 | |||
62 | retval = strict_strtoul(buf, 10, &state); | ||
63 | if (retval) | ||
64 | return retval; | ||
65 | |||
66 | temp_buf.command = ARVO_COMMAND_MODE_KEY; | ||
67 | temp_buf.state = state; | ||
68 | |||
69 | mutex_lock(&arvo->arvo_lock); | ||
70 | retval = roccat_common_send(usb_dev, ARVO_USB_COMMAND_MODE_KEY, | ||
71 | &temp_buf, sizeof(struct arvo_mode_key)); | ||
72 | mutex_unlock(&arvo->arvo_lock); | ||
73 | if (retval) | ||
74 | return retval; | ||
75 | |||
76 | return size; | ||
77 | } | ||
78 | |||
79 | static ssize_t arvo_sysfs_show_key_mask(struct device *dev, | ||
80 | struct device_attribute *attr, char *buf) | ||
81 | { | ||
82 | struct arvo_device *arvo = | ||
83 | hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); | ||
84 | struct usb_device *usb_dev = | ||
85 | interface_to_usbdev(to_usb_interface(dev->parent->parent)); | ||
86 | struct arvo_key_mask temp_buf; | ||
87 | int retval; | ||
88 | |||
89 | mutex_lock(&arvo->arvo_lock); | ||
90 | retval = roccat_common_receive(usb_dev, ARVO_USB_COMMAND_KEY_MASK, | ||
91 | &temp_buf, sizeof(struct arvo_key_mask)); | ||
92 | mutex_unlock(&arvo->arvo_lock); | ||
93 | if (retval) | ||
94 | return retval; | ||
95 | |||
96 | return snprintf(buf, PAGE_SIZE, "%d\n", temp_buf.key_mask); | ||
97 | } | ||
98 | |||
99 | static ssize_t arvo_sysfs_set_key_mask(struct device *dev, | ||
100 | struct device_attribute *attr, char const *buf, size_t size) | ||
101 | { | ||
102 | struct arvo_device *arvo = | ||
103 | hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); | ||
104 | struct usb_device *usb_dev = | ||
105 | interface_to_usbdev(to_usb_interface(dev->parent->parent)); | ||
106 | struct arvo_key_mask temp_buf; | ||
107 | unsigned long key_mask; | ||
108 | int retval; | ||
109 | |||
110 | retval = strict_strtoul(buf, 10, &key_mask); | ||
111 | if (retval) | ||
112 | return retval; | ||
113 | |||
114 | temp_buf.command = ARVO_COMMAND_KEY_MASK; | ||
115 | temp_buf.key_mask = key_mask; | ||
116 | |||
117 | mutex_lock(&arvo->arvo_lock); | ||
118 | retval = roccat_common_send(usb_dev, ARVO_USB_COMMAND_KEY_MASK, | ||
119 | &temp_buf, sizeof(struct arvo_key_mask)); | ||
120 | mutex_unlock(&arvo->arvo_lock); | ||
121 | if (retval) | ||
122 | return retval; | ||
123 | |||
124 | return size; | ||
125 | } | ||
126 | |||
127 | /* retval is 1-5 on success, < 0 on error */ | ||
128 | static int arvo_get_actual_profile(struct usb_device *usb_dev) | ||
129 | { | ||
130 | struct arvo_actual_profile temp_buf; | ||
131 | int retval; | ||
132 | |||
133 | retval = roccat_common_receive(usb_dev, ARVO_USB_COMMAND_ACTUAL_PROFILE, | ||
134 | &temp_buf, sizeof(struct arvo_actual_profile)); | ||
135 | |||
136 | if (retval) | ||
137 | return retval; | ||
138 | |||
139 | return temp_buf.actual_profile; | ||
140 | } | ||
141 | |||
142 | static ssize_t arvo_sysfs_show_actual_profile(struct device *dev, | ||
143 | struct device_attribute *attr, char *buf) | ||
144 | { | ||
145 | struct arvo_device *arvo = | ||
146 | hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); | ||
147 | |||
148 | return snprintf(buf, PAGE_SIZE, "%d\n", arvo->actual_profile); | ||
149 | } | ||
150 | |||
151 | static ssize_t arvo_sysfs_set_actual_profile(struct device *dev, | ||
152 | struct device_attribute *attr, char const *buf, size_t size) | ||
153 | { | ||
154 | struct arvo_device *arvo = | ||
155 | hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); | ||
156 | struct usb_device *usb_dev = | ||
157 | interface_to_usbdev(to_usb_interface(dev->parent->parent)); | ||
158 | struct arvo_actual_profile temp_buf; | ||
159 | unsigned long profile; | ||
160 | int retval; | ||
161 | |||
162 | retval = strict_strtoul(buf, 10, &profile); | ||
163 | if (retval) | ||
164 | return retval; | ||
165 | |||
166 | temp_buf.command = ARVO_COMMAND_ACTUAL_PROFILE; | ||
167 | temp_buf.actual_profile = profile; | ||
168 | |||
169 | mutex_lock(&arvo->arvo_lock); | ||
170 | retval = roccat_common_send(usb_dev, ARVO_USB_COMMAND_ACTUAL_PROFILE, | ||
171 | &temp_buf, sizeof(struct arvo_actual_profile)); | ||
172 | if (!retval) { | ||
173 | arvo->actual_profile = profile; | ||
174 | retval = size; | ||
175 | } | ||
176 | mutex_unlock(&arvo->arvo_lock); | ||
177 | return retval; | ||
178 | } | ||
179 | |||
180 | static ssize_t arvo_sysfs_write(struct file *fp, | ||
181 | struct kobject *kobj, void const *buf, | ||
182 | loff_t off, size_t count, size_t real_size, uint command) | ||
183 | { | ||
184 | struct device *dev = | ||
185 | container_of(kobj, struct device, kobj)->parent->parent; | ||
186 | struct arvo_device *arvo = hid_get_drvdata(dev_get_drvdata(dev)); | ||
187 | struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); | ||
188 | int retval; | ||
189 | |||
190 | if (off != 0 || count != real_size) | ||
191 | return -EINVAL; | ||
192 | |||
193 | mutex_lock(&arvo->arvo_lock); | ||
194 | retval = roccat_common_send(usb_dev, command, buf, real_size); | ||
195 | mutex_unlock(&arvo->arvo_lock); | ||
196 | |||
197 | return (retval ? retval : real_size); | ||
198 | } | ||
199 | |||
200 | static ssize_t arvo_sysfs_read(struct file *fp, | ||
201 | struct kobject *kobj, void *buf, loff_t off, | ||
202 | size_t count, size_t real_size, uint command) | ||
203 | { | ||
204 | struct device *dev = | ||
205 | container_of(kobj, struct device, kobj)->parent->parent; | ||
206 | struct arvo_device *arvo = hid_get_drvdata(dev_get_drvdata(dev)); | ||
207 | struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); | ||
208 | int retval; | ||
209 | |||
210 | if (off >= real_size) | ||
211 | return 0; | ||
212 | |||
213 | if (off != 0 || count != real_size) | ||
214 | return -EINVAL; | ||
215 | |||
216 | mutex_lock(&arvo->arvo_lock); | ||
217 | retval = roccat_common_receive(usb_dev, command, buf, real_size); | ||
218 | mutex_unlock(&arvo->arvo_lock); | ||
219 | |||
220 | return (retval ? retval : real_size); | ||
221 | } | ||
222 | |||
223 | static ssize_t arvo_sysfs_write_button(struct file *fp, | ||
224 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
225 | loff_t off, size_t count) | ||
226 | { | ||
227 | return arvo_sysfs_write(fp, kobj, buf, off, count, | ||
228 | sizeof(struct arvo_button), ARVO_USB_COMMAND_BUTTON); | ||
229 | } | ||
230 | |||
231 | static ssize_t arvo_sysfs_read_info(struct file *fp, | ||
232 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
233 | loff_t off, size_t count) | ||
234 | { | ||
235 | return arvo_sysfs_read(fp, kobj, buf, off, count, | ||
236 | sizeof(struct arvo_info), ARVO_USB_COMMAND_INFO); | ||
237 | } | ||
238 | |||
239 | |||
240 | static struct device_attribute arvo_attributes[] = { | ||
241 | __ATTR(mode_key, 0660, | ||
242 | arvo_sysfs_show_mode_key, arvo_sysfs_set_mode_key), | ||
243 | __ATTR(key_mask, 0660, | ||
244 | arvo_sysfs_show_key_mask, arvo_sysfs_set_key_mask), | ||
245 | __ATTR(actual_profile, 0660, | ||
246 | arvo_sysfs_show_actual_profile, | ||
247 | arvo_sysfs_set_actual_profile), | ||
248 | __ATTR_NULL | ||
249 | }; | ||
250 | |||
251 | static struct bin_attribute arvo_bin_attributes[] = { | ||
252 | { | ||
253 | .attr = { .name = "button", .mode = 0220 }, | ||
254 | .size = sizeof(struct arvo_button), | ||
255 | .write = arvo_sysfs_write_button | ||
256 | }, | ||
257 | { | ||
258 | .attr = { .name = "info", .mode = 0440 }, | ||
259 | .size = sizeof(struct arvo_info), | ||
260 | .read = arvo_sysfs_read_info | ||
261 | }, | ||
262 | __ATTR_NULL | ||
263 | }; | ||
264 | |||
265 | static int arvo_init_arvo_device_struct(struct usb_device *usb_dev, | ||
266 | struct arvo_device *arvo) | ||
267 | { | ||
268 | int retval; | ||
269 | |||
270 | mutex_init(&arvo->arvo_lock); | ||
271 | |||
272 | retval = arvo_get_actual_profile(usb_dev); | ||
273 | if (retval < 0) | ||
274 | return retval; | ||
275 | arvo->actual_profile = retval; | ||
276 | |||
277 | return 0; | ||
278 | } | ||
279 | |||
280 | static int arvo_init_specials(struct hid_device *hdev) | ||
281 | { | ||
282 | struct usb_interface *intf = to_usb_interface(hdev->dev.parent); | ||
283 | struct usb_device *usb_dev = interface_to_usbdev(intf); | ||
284 | struct arvo_device *arvo; | ||
285 | int retval; | ||
286 | |||
287 | if (intf->cur_altsetting->desc.bInterfaceProtocol | ||
288 | == USB_INTERFACE_PROTOCOL_KEYBOARD) { | ||
289 | hid_set_drvdata(hdev, NULL); | ||
290 | return 0; | ||
291 | } | ||
292 | |||
293 | arvo = kzalloc(sizeof(*arvo), GFP_KERNEL); | ||
294 | if (!arvo) { | ||
295 | hid_err(hdev, "can't alloc device descriptor\n"); | ||
296 | return -ENOMEM; | ||
297 | } | ||
298 | hid_set_drvdata(hdev, arvo); | ||
299 | |||
300 | retval = arvo_init_arvo_device_struct(usb_dev, arvo); | ||
301 | if (retval) { | ||
302 | hid_err(hdev, "couldn't init struct arvo_device\n"); | ||
303 | goto exit_free; | ||
304 | } | ||
305 | |||
306 | retval = roccat_connect(arvo_class, hdev, | ||
307 | sizeof(struct arvo_roccat_report)); | ||
308 | if (retval < 0) { | ||
309 | hid_err(hdev, "couldn't init char dev\n"); | ||
310 | } else { | ||
311 | arvo->chrdev_minor = retval; | ||
312 | arvo->roccat_claimed = 1; | ||
313 | } | ||
314 | |||
315 | return 0; | ||
316 | exit_free: | ||
317 | kfree(arvo); | ||
318 | return retval; | ||
319 | } | ||
320 | |||
321 | static void arvo_remove_specials(struct hid_device *hdev) | ||
322 | { | ||
323 | struct usb_interface *intf = to_usb_interface(hdev->dev.parent); | ||
324 | struct arvo_device *arvo; | ||
325 | |||
326 | if (intf->cur_altsetting->desc.bInterfaceProtocol | ||
327 | == USB_INTERFACE_PROTOCOL_KEYBOARD) | ||
328 | return; | ||
329 | |||
330 | arvo = hid_get_drvdata(hdev); | ||
331 | if (arvo->roccat_claimed) | ||
332 | roccat_disconnect(arvo->chrdev_minor); | ||
333 | kfree(arvo); | ||
334 | } | ||
335 | |||
336 | static int arvo_probe(struct hid_device *hdev, | ||
337 | const struct hid_device_id *id) | ||
338 | { | ||
339 | int retval; | ||
340 | |||
341 | retval = hid_parse(hdev); | ||
342 | if (retval) { | ||
343 | hid_err(hdev, "parse failed\n"); | ||
344 | goto exit; | ||
345 | } | ||
346 | |||
347 | retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT); | ||
348 | if (retval) { | ||
349 | hid_err(hdev, "hw start failed\n"); | ||
350 | goto exit; | ||
351 | } | ||
352 | |||
353 | retval = arvo_init_specials(hdev); | ||
354 | if (retval) { | ||
355 | hid_err(hdev, "couldn't install keyboard\n"); | ||
356 | goto exit_stop; | ||
357 | } | ||
358 | |||
359 | return 0; | ||
360 | |||
361 | exit_stop: | ||
362 | hid_hw_stop(hdev); | ||
363 | exit: | ||
364 | return retval; | ||
365 | } | ||
366 | |||
367 | static void arvo_remove(struct hid_device *hdev) | ||
368 | { | ||
369 | arvo_remove_specials(hdev); | ||
370 | hid_hw_stop(hdev); | ||
371 | } | ||
372 | |||
373 | static void arvo_report_to_chrdev(struct arvo_device const *arvo, | ||
374 | u8 const *data) | ||
375 | { | ||
376 | struct arvo_special_report const *special_report; | ||
377 | struct arvo_roccat_report roccat_report; | ||
378 | |||
379 | special_report = (struct arvo_special_report const *)data; | ||
380 | |||
381 | roccat_report.profile = arvo->actual_profile; | ||
382 | roccat_report.button = special_report->event & | ||
383 | ARVO_SPECIAL_REPORT_EVENT_MASK_BUTTON; | ||
384 | if ((special_report->event & ARVO_SPECIAL_REPORT_EVENT_MASK_ACTION) == | ||
385 | ARVO_SPECIAL_REPORT_EVENT_ACTION_PRESS) | ||
386 | roccat_report.action = ARVO_ROCCAT_REPORT_ACTION_PRESS; | ||
387 | else | ||
388 | roccat_report.action = ARVO_ROCCAT_REPORT_ACTION_RELEASE; | ||
389 | |||
390 | roccat_report_event(arvo->chrdev_minor, | ||
391 | (uint8_t const *)&roccat_report); | ||
392 | } | ||
393 | |||
394 | static int arvo_raw_event(struct hid_device *hdev, | ||
395 | struct hid_report *report, u8 *data, int size) | ||
396 | { | ||
397 | struct arvo_device *arvo = hid_get_drvdata(hdev); | ||
398 | |||
399 | if (size != 3) | ||
400 | return 0; | ||
401 | |||
402 | if (arvo->roccat_claimed) | ||
403 | arvo_report_to_chrdev(arvo, data); | ||
404 | |||
405 | return 0; | ||
406 | } | ||
407 | |||
408 | static const struct hid_device_id arvo_devices[] = { | ||
409 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ARVO) }, | ||
410 | { } | ||
411 | }; | ||
412 | |||
413 | MODULE_DEVICE_TABLE(hid, arvo_devices); | ||
414 | |||
415 | static struct hid_driver arvo_driver = { | ||
416 | .name = "arvo", | ||
417 | .id_table = arvo_devices, | ||
418 | .probe = arvo_probe, | ||
419 | .remove = arvo_remove, | ||
420 | .raw_event = arvo_raw_event | ||
421 | }; | ||
422 | |||
423 | static int __init arvo_init(void) | ||
424 | { | ||
425 | int retval; | ||
426 | |||
427 | arvo_class = class_create(THIS_MODULE, "arvo"); | ||
428 | if (IS_ERR(arvo_class)) | ||
429 | return PTR_ERR(arvo_class); | ||
430 | arvo_class->dev_attrs = arvo_attributes; | ||
431 | arvo_class->dev_bin_attrs = arvo_bin_attributes; | ||
432 | |||
433 | retval = hid_register_driver(&arvo_driver); | ||
434 | if (retval) | ||
435 | class_destroy(arvo_class); | ||
436 | return retval; | ||
437 | } | ||
438 | |||
439 | static void __exit arvo_exit(void) | ||
440 | { | ||
441 | hid_unregister_driver(&arvo_driver); | ||
442 | class_destroy(arvo_class); | ||
443 | } | ||
444 | |||
445 | module_init(arvo_init); | ||
446 | module_exit(arvo_exit); | ||
447 | |||
448 | MODULE_AUTHOR("Stefan Achatz"); | ||
449 | MODULE_DESCRIPTION("USB Roccat Arvo driver"); | ||
450 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/hid/hid-roccat-arvo.h b/drivers/hid/hid-roccat-arvo.h new file mode 100644 index 000000000000..d284a781c99e --- /dev/null +++ b/drivers/hid/hid-roccat-arvo.h | |||
@@ -0,0 +1,98 @@ | |||
1 | #ifndef __HID_ROCCAT_ARVO_H | ||
2 | #define __HID_ROCCAT_ARVO_H | ||
3 | |||
4 | /* | ||
5 | * Copyright (c) 2011 Stefan Achatz <erazor_de@users.sourceforge.net> | ||
6 | */ | ||
7 | |||
8 | /* | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the Free | ||
11 | * Software Foundation; either version 2 of the License, or (at your option) | ||
12 | * any later version. | ||
13 | */ | ||
14 | |||
15 | #include <linux/types.h> | ||
16 | |||
17 | struct arvo_mode_key { /* 2 bytes */ | ||
18 | uint8_t command; /* ARVO_COMMAND_MODE_KEY */ | ||
19 | uint8_t state; | ||
20 | } __packed; | ||
21 | |||
22 | struct arvo_button { | ||
23 | uint8_t unknown[24]; | ||
24 | } __packed; | ||
25 | |||
26 | struct arvo_info { | ||
27 | uint8_t unknown[8]; | ||
28 | } __packed; | ||
29 | |||
30 | struct arvo_key_mask { /* 2 bytes */ | ||
31 | uint8_t command; /* ARVO_COMMAND_KEY_MASK */ | ||
32 | uint8_t key_mask; | ||
33 | } __packed; | ||
34 | |||
35 | /* selected profile is persistent */ | ||
36 | struct arvo_actual_profile { /* 2 bytes */ | ||
37 | uint8_t command; /* ARVO_COMMAND_ACTUAL_PROFILE */ | ||
38 | uint8_t actual_profile; | ||
39 | } __packed; | ||
40 | |||
41 | enum arvo_commands { | ||
42 | ARVO_COMMAND_MODE_KEY = 0x3, | ||
43 | ARVO_COMMAND_BUTTON = 0x4, | ||
44 | ARVO_COMMAND_INFO = 0x5, | ||
45 | ARVO_COMMAND_KEY_MASK = 0x6, | ||
46 | ARVO_COMMAND_ACTUAL_PROFILE = 0x7, | ||
47 | }; | ||
48 | |||
49 | enum arvo_usb_commands { | ||
50 | ARVO_USB_COMMAND_MODE_KEY = 0x303, | ||
51 | /* | ||
52 | * read/write | ||
53 | * Read uses both index bytes as profile/key indexes | ||
54 | * Write has index 0, profile/key is determined by payload | ||
55 | */ | ||
56 | ARVO_USB_COMMAND_BUTTON = 0x304, | ||
57 | ARVO_USB_COMMAND_INFO = 0x305, | ||
58 | ARVO_USB_COMMAND_KEY_MASK = 0x306, | ||
59 | ARVO_USB_COMMAND_ACTUAL_PROFILE = 0x307, | ||
60 | }; | ||
61 | |||
62 | struct arvo_special_report { | ||
63 | uint8_t unknown1; /* always 0x01 */ | ||
64 | uint8_t event; | ||
65 | uint8_t unknown2; /* always 0x70 */ | ||
66 | } __packed; | ||
67 | |||
68 | enum arvo_special_report_events { | ||
69 | ARVO_SPECIAL_REPORT_EVENT_ACTION_PRESS = 0x10, | ||
70 | ARVO_SPECIAL_REPORT_EVENT_ACTION_RELEASE = 0x0, | ||
71 | }; | ||
72 | |||
73 | enum arvo_special_report_event_masks { | ||
74 | ARVO_SPECIAL_REPORT_EVENT_MASK_ACTION = 0xf0, | ||
75 | ARVO_SPECIAL_REPORT_EVENT_MASK_BUTTON = 0x0f, | ||
76 | }; | ||
77 | |||
78 | struct arvo_roccat_report { | ||
79 | uint8_t profile; | ||
80 | uint8_t button; | ||
81 | uint8_t action; | ||
82 | } __packed; | ||
83 | |||
84 | enum arvo_roccat_report_action { | ||
85 | ARVO_ROCCAT_REPORT_ACTION_RELEASE = 0, | ||
86 | ARVO_ROCCAT_REPORT_ACTION_PRESS = 1, | ||
87 | }; | ||
88 | |||
89 | struct arvo_device { | ||
90 | int roccat_claimed; | ||
91 | int chrdev_minor; | ||
92 | |||
93 | struct mutex arvo_lock; | ||
94 | |||
95 | int actual_profile; | ||
96 | }; | ||
97 | |||
98 | #endif | ||
diff --git a/drivers/hid/hid-roccat-common.c b/drivers/hid/hid-roccat-common.c new file mode 100644 index 000000000000..13b1eb0c8c65 --- /dev/null +++ b/drivers/hid/hid-roccat-common.c | |||
@@ -0,0 +1,62 @@ | |||
1 | /* | ||
2 | * Roccat common functions for device specific drivers | ||
3 | * | ||
4 | * Copyright (c) 2011 Stefan Achatz <erazor_de@users.sourceforge.net> | ||
5 | */ | ||
6 | |||
7 | /* | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the Free | ||
10 | * Software Foundation; either version 2 of the License, or (at your option) | ||
11 | * any later version. | ||
12 | */ | ||
13 | |||
14 | #include <linux/slab.h> | ||
15 | #include "hid-roccat-common.h" | ||
16 | |||
17 | int roccat_common_receive(struct usb_device *usb_dev, uint usb_command, | ||
18 | void *data, uint size) | ||
19 | { | ||
20 | char *buf; | ||
21 | int len; | ||
22 | |||
23 | buf = kmalloc(size, GFP_KERNEL); | ||
24 | if (buf == NULL) | ||
25 | return -ENOMEM; | ||
26 | |||
27 | len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), | ||
28 | USB_REQ_CLEAR_FEATURE, | ||
29 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, | ||
30 | usb_command, 0, buf, size, USB_CTRL_SET_TIMEOUT); | ||
31 | |||
32 | memcpy(data, buf, size); | ||
33 | kfree(buf); | ||
34 | return ((len < 0) ? len : ((len != size) ? -EIO : 0)); | ||
35 | } | ||
36 | EXPORT_SYMBOL_GPL(roccat_common_receive); | ||
37 | |||
38 | int roccat_common_send(struct usb_device *usb_dev, uint usb_command, | ||
39 | void const *data, uint size) | ||
40 | { | ||
41 | char *buf; | ||
42 | int len; | ||
43 | |||
44 | buf = kmalloc(size, GFP_KERNEL); | ||
45 | if (buf == NULL) | ||
46 | return -ENOMEM; | ||
47 | |||
48 | memcpy(buf, data, size); | ||
49 | |||
50 | len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), | ||
51 | USB_REQ_SET_CONFIGURATION, | ||
52 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, | ||
53 | usb_command, 0, buf, size, USB_CTRL_SET_TIMEOUT); | ||
54 | |||
55 | kfree(buf); | ||
56 | return ((len < 0) ? len : ((len != size) ? -EIO : 0)); | ||
57 | } | ||
58 | EXPORT_SYMBOL_GPL(roccat_common_send); | ||
59 | |||
60 | MODULE_AUTHOR("Stefan Achatz"); | ||
61 | MODULE_DESCRIPTION("USB Roccat common driver"); | ||
62 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/hid/hid-roccat-common.h b/drivers/hid/hid-roccat-common.h new file mode 100644 index 000000000000..fe45fae05bb9 --- /dev/null +++ b/drivers/hid/hid-roccat-common.h | |||
@@ -0,0 +1,23 @@ | |||
1 | #ifndef __HID_ROCCAT_COMMON_H | ||
2 | #define __HID_ROCCAT_COMMON_H | ||
3 | |||
4 | /* | ||
5 | * Copyright (c) 2011 Stefan Achatz <erazor_de@users.sourceforge.net> | ||
6 | */ | ||
7 | |||
8 | /* | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the Free | ||
11 | * Software Foundation; either version 2 of the License, or (at your option) | ||
12 | * any later version. | ||
13 | */ | ||
14 | |||
15 | #include <linux/usb.h> | ||
16 | #include <linux/types.h> | ||
17 | |||
18 | int roccat_common_receive(struct usb_device *usb_dev, uint usb_command, | ||
19 | void *data, uint size); | ||
20 | int roccat_common_send(struct usb_device *usb_dev, uint usb_command, | ||
21 | void const *data, uint size); | ||
22 | |||
23 | #endif | ||
diff --git a/drivers/hid/hid-roccat-kone.c b/drivers/hid/hid-roccat-kone.c index f77695762cb5..a57838d15267 100644 --- a/drivers/hid/hid-roccat-kone.c +++ b/drivers/hid/hid-roccat-kone.c | |||
@@ -28,13 +28,18 @@ | |||
28 | #include <linux/device.h> | 28 | #include <linux/device.h> |
29 | #include <linux/input.h> | 29 | #include <linux/input.h> |
30 | #include <linux/hid.h> | 30 | #include <linux/hid.h> |
31 | #include <linux/usb.h> | ||
32 | #include <linux/module.h> | 31 | #include <linux/module.h> |
33 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
33 | #include <linux/hid-roccat.h> | ||
34 | #include "hid-ids.h" | 34 | #include "hid-ids.h" |
35 | #include "hid-roccat.h" | 35 | #include "hid-roccat-common.h" |
36 | #include "hid-roccat-kone.h" | 36 | #include "hid-roccat-kone.h" |
37 | 37 | ||
38 | static uint profile_numbers[5] = {0, 1, 2, 3, 4}; | ||
39 | |||
40 | /* kone_class is used for creating sysfs attributes via roccat char device */ | ||
41 | static struct class *kone_class; | ||
42 | |||
38 | static void kone_set_settings_checksum(struct kone_settings *settings) | 43 | static void kone_set_settings_checksum(struct kone_settings *settings) |
39 | { | 44 | { |
40 | uint16_t checksum = 0; | 45 | uint16_t checksum = 0; |
@@ -53,12 +58,8 @@ static void kone_set_settings_checksum(struct kone_settings *settings) | |||
53 | */ | 58 | */ |
54 | static int kone_check_write(struct usb_device *usb_dev) | 59 | static int kone_check_write(struct usb_device *usb_dev) |
55 | { | 60 | { |
56 | int len; | 61 | int retval; |
57 | unsigned char *data; | 62 | uint8_t data; |
58 | |||
59 | data = kmalloc(1, GFP_KERNEL); | ||
60 | if (!data) | ||
61 | return -ENOMEM; | ||
62 | 63 | ||
63 | do { | 64 | do { |
64 | /* | 65 | /* |
@@ -67,57 +68,36 @@ static int kone_check_write(struct usb_device *usb_dev) | |||
67 | */ | 68 | */ |
68 | msleep(80); | 69 | msleep(80); |
69 | 70 | ||
70 | len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), | 71 | retval = roccat_common_receive(usb_dev, |
71 | USB_REQ_CLEAR_FEATURE, | 72 | kone_command_confirm_write, &data, 1); |
72 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | | 73 | if (retval) |
73 | USB_DIR_IN, | 74 | return retval; |
74 | kone_command_confirm_write, 0, data, 1, | ||
75 | USB_CTRL_SET_TIMEOUT); | ||
76 | |||
77 | if (len != 1) { | ||
78 | kfree(data); | ||
79 | return -EIO; | ||
80 | } | ||
81 | 75 | ||
82 | /* | 76 | /* |
83 | * value of 3 seems to mean something like | 77 | * value of 3 seems to mean something like |
84 | * "not finished yet, but it looks good" | 78 | * "not finished yet, but it looks good" |
85 | * So check again after a moment. | 79 | * So check again after a moment. |
86 | */ | 80 | */ |
87 | } while (*data == 3); | 81 | } while (data == 3); |
88 | 82 | ||
89 | if (*data == 1) { /* everything alright */ | 83 | if (data == 1) /* everything alright */ |
90 | kfree(data); | ||
91 | return 0; | 84 | return 0; |
92 | } else { /* unknown answer */ | 85 | |
93 | dev_err(&usb_dev->dev, "got retval %d when checking write\n", | 86 | /* unknown answer */ |
94 | *data); | 87 | hid_err(usb_dev, "got retval %d when checking write\n", data); |
95 | kfree(data); | 88 | return -EIO; |
96 | return -EIO; | ||
97 | } | ||
98 | } | 89 | } |
99 | 90 | ||
100 | /* | 91 | /* |
101 | * Reads settings from mouse and stores it in @buf | 92 | * Reads settings from mouse and stores it in @buf |
102 | * @buf has to be alloced with GFP_KERNEL | ||
103 | * On success returns 0 | 93 | * On success returns 0 |
104 | * On failure returns errno | 94 | * On failure returns errno |
105 | */ | 95 | */ |
106 | static int kone_get_settings(struct usb_device *usb_dev, | 96 | static int kone_get_settings(struct usb_device *usb_dev, |
107 | struct kone_settings *buf) | 97 | struct kone_settings *buf) |
108 | { | 98 | { |
109 | int len; | 99 | return roccat_common_receive(usb_dev, kone_command_settings, buf, |
110 | 100 | sizeof(struct kone_settings)); | |
111 | len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), | ||
112 | USB_REQ_CLEAR_FEATURE, | ||
113 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, | ||
114 | kone_command_settings, 0, buf, | ||
115 | sizeof(struct kone_settings), USB_CTRL_SET_TIMEOUT); | ||
116 | |||
117 | if (len != sizeof(struct kone_settings)) | ||
118 | return -EIO; | ||
119 | |||
120 | return 0; | ||
121 | } | 101 | } |
122 | 102 | ||
123 | /* | 103 | /* |
@@ -128,22 +108,12 @@ static int kone_get_settings(struct usb_device *usb_dev, | |||
128 | static int kone_set_settings(struct usb_device *usb_dev, | 108 | static int kone_set_settings(struct usb_device *usb_dev, |
129 | struct kone_settings const *settings) | 109 | struct kone_settings const *settings) |
130 | { | 110 | { |
131 | int len; | 111 | int retval; |
132 | 112 | retval = roccat_common_send(usb_dev, kone_command_settings, | |
133 | len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), | 113 | settings, sizeof(struct kone_settings)); |
134 | USB_REQ_SET_CONFIGURATION, | 114 | if (retval) |
135 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, | 115 | return retval; |
136 | kone_command_settings, 0, (char *)settings, | 116 | return kone_check_write(usb_dev); |
137 | sizeof(struct kone_settings), | ||
138 | USB_CTRL_SET_TIMEOUT); | ||
139 | |||
140 | if (len != sizeof(struct kone_settings)) | ||
141 | return -EIO; | ||
142 | |||
143 | if (kone_check_write(usb_dev)) | ||
144 | return -EIO; | ||
145 | |||
146 | return 0; | ||
147 | } | 117 | } |
148 | 118 | ||
149 | /* | 119 | /* |
@@ -189,7 +159,7 @@ static int kone_set_profile(struct usb_device *usb_dev, | |||
189 | len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), | 159 | len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), |
190 | USB_REQ_SET_CONFIGURATION, | 160 | USB_REQ_SET_CONFIGURATION, |
191 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, | 161 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, |
192 | kone_command_profile, number, (char *)profile, | 162 | kone_command_profile, number, (void *)profile, |
193 | sizeof(struct kone_profile), | 163 | sizeof(struct kone_profile), |
194 | USB_CTRL_SET_TIMEOUT); | 164 | USB_CTRL_SET_TIMEOUT); |
195 | 165 | ||
@@ -209,24 +179,15 @@ static int kone_set_profile(struct usb_device *usb_dev, | |||
209 | */ | 179 | */ |
210 | static int kone_get_weight(struct usb_device *usb_dev, int *result) | 180 | static int kone_get_weight(struct usb_device *usb_dev, int *result) |
211 | { | 181 | { |
212 | int len; | 182 | int retval; |
213 | uint8_t *data; | 183 | uint8_t data; |
214 | 184 | ||
215 | data = kmalloc(1, GFP_KERNEL); | 185 | retval = roccat_common_receive(usb_dev, kone_command_weight, &data, 1); |
216 | if (!data) | ||
217 | return -ENOMEM; | ||
218 | 186 | ||
219 | len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), | 187 | if (retval) |
220 | USB_REQ_CLEAR_FEATURE, | 188 | return retval; |
221 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, | ||
222 | kone_command_weight, 0, data, 1, USB_CTRL_SET_TIMEOUT); | ||
223 | 189 | ||
224 | if (len != 1) { | 190 | *result = (int)data; |
225 | kfree(data); | ||
226 | return -EIO; | ||
227 | } | ||
228 | *result = (int)*data; | ||
229 | kfree(data); | ||
230 | return 0; | 191 | return 0; |
231 | } | 192 | } |
232 | 193 | ||
@@ -237,32 +198,23 @@ static int kone_get_weight(struct usb_device *usb_dev, int *result) | |||
237 | */ | 198 | */ |
238 | static int kone_get_firmware_version(struct usb_device *usb_dev, int *result) | 199 | static int kone_get_firmware_version(struct usb_device *usb_dev, int *result) |
239 | { | 200 | { |
240 | int len; | 201 | int retval; |
241 | unsigned char *data; | 202 | uint16_t data; |
242 | |||
243 | data = kmalloc(2, GFP_KERNEL); | ||
244 | if (!data) | ||
245 | return -ENOMEM; | ||
246 | 203 | ||
247 | len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), | 204 | retval = roccat_common_receive(usb_dev, kone_command_firmware_version, |
248 | USB_REQ_CLEAR_FEATURE, | 205 | &data, 2); |
249 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, | 206 | if (retval) |
250 | kone_command_firmware_version, 0, data, 2, | 207 | return retval; |
251 | USB_CTRL_SET_TIMEOUT); | ||
252 | 208 | ||
253 | if (len != 2) { | 209 | *result = le16_to_cpu(data); |
254 | kfree(data); | ||
255 | return -EIO; | ||
256 | } | ||
257 | *result = le16_to_cpu(*data); | ||
258 | kfree(data); | ||
259 | return 0; | 210 | return 0; |
260 | } | 211 | } |
261 | 212 | ||
262 | static ssize_t kone_sysfs_read_settings(struct file *fp, struct kobject *kobj, | 213 | static ssize_t kone_sysfs_read_settings(struct file *fp, struct kobject *kobj, |
263 | struct bin_attribute *attr, char *buf, | 214 | struct bin_attribute *attr, char *buf, |
264 | loff_t off, size_t count) { | 215 | loff_t off, size_t count) { |
265 | struct device *dev = container_of(kobj, struct device, kobj); | 216 | struct device *dev = |
217 | container_of(kobj, struct device, kobj)->parent->parent; | ||
266 | struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev)); | 218 | struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev)); |
267 | 219 | ||
268 | if (off >= sizeof(struct kone_settings)) | 220 | if (off >= sizeof(struct kone_settings)) |
@@ -286,7 +238,8 @@ static ssize_t kone_sysfs_read_settings(struct file *fp, struct kobject *kobj, | |||
286 | static ssize_t kone_sysfs_write_settings(struct file *fp, struct kobject *kobj, | 238 | static ssize_t kone_sysfs_write_settings(struct file *fp, struct kobject *kobj, |
287 | struct bin_attribute *attr, char *buf, | 239 | struct bin_attribute *attr, char *buf, |
288 | loff_t off, size_t count) { | 240 | loff_t off, size_t count) { |
289 | struct device *dev = container_of(kobj, struct device, kobj); | 241 | struct device *dev = |
242 | container_of(kobj, struct device, kobj)->parent->parent; | ||
290 | struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev)); | 243 | struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev)); |
291 | struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); | 244 | struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); |
292 | int retval = 0, difference; | 245 | int retval = 0, difference; |
@@ -319,10 +272,11 @@ static ssize_t kone_sysfs_write_settings(struct file *fp, struct kobject *kobj, | |||
319 | return sizeof(struct kone_settings); | 272 | return sizeof(struct kone_settings); |
320 | } | 273 | } |
321 | 274 | ||
322 | static ssize_t kone_sysfs_read_profilex(struct kobject *kobj, | 275 | static ssize_t kone_sysfs_read_profilex(struct file *fp, |
323 | struct bin_attribute *attr, char *buf, | 276 | struct kobject *kobj, struct bin_attribute *attr, |
324 | loff_t off, size_t count, int number) { | 277 | char *buf, loff_t off, size_t count) { |
325 | struct device *dev = container_of(kobj, struct device, kobj); | 278 | struct device *dev = |
279 | container_of(kobj, struct device, kobj)->parent->parent; | ||
326 | struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev)); | 280 | struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev)); |
327 | 281 | ||
328 | if (off >= sizeof(struct kone_profile)) | 282 | if (off >= sizeof(struct kone_profile)) |
@@ -332,47 +286,18 @@ static ssize_t kone_sysfs_read_profilex(struct kobject *kobj, | |||
332 | count = sizeof(struct kone_profile) - off; | 286 | count = sizeof(struct kone_profile) - off; |
333 | 287 | ||
334 | mutex_lock(&kone->kone_lock); | 288 | mutex_lock(&kone->kone_lock); |
335 | memcpy(buf, ((char const *)&kone->profiles[number - 1]) + off, count); | 289 | memcpy(buf, ((char const *)&kone->profiles[*(uint *)(attr->private)]) + off, count); |
336 | mutex_unlock(&kone->kone_lock); | 290 | mutex_unlock(&kone->kone_lock); |
337 | 291 | ||
338 | return count; | 292 | return count; |
339 | } | 293 | } |
340 | 294 | ||
341 | static ssize_t kone_sysfs_read_profile1(struct file *fp, struct kobject *kobj, | ||
342 | struct bin_attribute *attr, char *buf, | ||
343 | loff_t off, size_t count) { | ||
344 | return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 1); | ||
345 | } | ||
346 | |||
347 | static ssize_t kone_sysfs_read_profile2(struct file *fp, struct kobject *kobj, | ||
348 | struct bin_attribute *attr, char *buf, | ||
349 | loff_t off, size_t count) { | ||
350 | return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 2); | ||
351 | } | ||
352 | |||
353 | static ssize_t kone_sysfs_read_profile3(struct file *fp, struct kobject *kobj, | ||
354 | struct bin_attribute *attr, char *buf, | ||
355 | loff_t off, size_t count) { | ||
356 | return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 3); | ||
357 | } | ||
358 | |||
359 | static ssize_t kone_sysfs_read_profile4(struct file *fp, struct kobject *kobj, | ||
360 | struct bin_attribute *attr, char *buf, | ||
361 | loff_t off, size_t count) { | ||
362 | return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 4); | ||
363 | } | ||
364 | |||
365 | static ssize_t kone_sysfs_read_profile5(struct file *fp, struct kobject *kobj, | ||
366 | struct bin_attribute *attr, char *buf, | ||
367 | loff_t off, size_t count) { | ||
368 | return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 5); | ||
369 | } | ||
370 | |||
371 | /* Writes data only if different to stored data */ | 295 | /* Writes data only if different to stored data */ |
372 | static ssize_t kone_sysfs_write_profilex(struct kobject *kobj, | 296 | static ssize_t kone_sysfs_write_profilex(struct file *fp, |
373 | struct bin_attribute *attr, char *buf, | 297 | struct kobject *kobj, struct bin_attribute *attr, |
374 | loff_t off, size_t count, int number) { | 298 | char *buf, loff_t off, size_t count) { |
375 | struct device *dev = container_of(kobj, struct device, kobj); | 299 | struct device *dev = |
300 | container_of(kobj, struct device, kobj)->parent->parent; | ||
376 | struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev)); | 301 | struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev)); |
377 | struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); | 302 | struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); |
378 | struct kone_profile *profile; | 303 | struct kone_profile *profile; |
@@ -382,13 +307,14 @@ static ssize_t kone_sysfs_write_profilex(struct kobject *kobj, | |||
382 | if (off != 0 || count != sizeof(struct kone_profile)) | 307 | if (off != 0 || count != sizeof(struct kone_profile)) |
383 | return -EINVAL; | 308 | return -EINVAL; |
384 | 309 | ||
385 | profile = &kone->profiles[number - 1]; | 310 | profile = &kone->profiles[*(uint *)(attr->private)]; |
386 | 311 | ||
387 | mutex_lock(&kone->kone_lock); | 312 | mutex_lock(&kone->kone_lock); |
388 | difference = memcmp(buf, profile, sizeof(struct kone_profile)); | 313 | difference = memcmp(buf, profile, sizeof(struct kone_profile)); |
389 | if (difference) { | 314 | if (difference) { |
390 | retval = kone_set_profile(usb_dev, | 315 | retval = kone_set_profile(usb_dev, |
391 | (struct kone_profile const *)buf, number); | 316 | (struct kone_profile const *)buf, |
317 | *(uint *)(attr->private) + 1); | ||
392 | if (!retval) | 318 | if (!retval) |
393 | memcpy(profile, buf, sizeof(struct kone_profile)); | 319 | memcpy(profile, buf, sizeof(struct kone_profile)); |
394 | } | 320 | } |
@@ -400,47 +326,19 @@ static ssize_t kone_sysfs_write_profilex(struct kobject *kobj, | |||
400 | return sizeof(struct kone_profile); | 326 | return sizeof(struct kone_profile); |
401 | } | 327 | } |
402 | 328 | ||
403 | static ssize_t kone_sysfs_write_profile1(struct file *fp, struct kobject *kobj, | ||
404 | struct bin_attribute *attr, char *buf, | ||
405 | loff_t off, size_t count) { | ||
406 | return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 1); | ||
407 | } | ||
408 | |||
409 | static ssize_t kone_sysfs_write_profile2(struct file *fp, struct kobject *kobj, | ||
410 | struct bin_attribute *attr, char *buf, | ||
411 | loff_t off, size_t count) { | ||
412 | return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 2); | ||
413 | } | ||
414 | |||
415 | static ssize_t kone_sysfs_write_profile3(struct file *fp, struct kobject *kobj, | ||
416 | struct bin_attribute *attr, char *buf, | ||
417 | loff_t off, size_t count) { | ||
418 | return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 3); | ||
419 | } | ||
420 | |||
421 | static ssize_t kone_sysfs_write_profile4(struct file *fp, struct kobject *kobj, | ||
422 | struct bin_attribute *attr, char *buf, | ||
423 | loff_t off, size_t count) { | ||
424 | return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 4); | ||
425 | } | ||
426 | |||
427 | static ssize_t kone_sysfs_write_profile5(struct file *fp, struct kobject *kobj, | ||
428 | struct bin_attribute *attr, char *buf, | ||
429 | loff_t off, size_t count) { | ||
430 | return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 5); | ||
431 | } | ||
432 | |||
433 | static ssize_t kone_sysfs_show_actual_profile(struct device *dev, | 329 | static ssize_t kone_sysfs_show_actual_profile(struct device *dev, |
434 | struct device_attribute *attr, char *buf) | 330 | struct device_attribute *attr, char *buf) |
435 | { | 331 | { |
436 | struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev)); | 332 | struct kone_device *kone = |
333 | hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); | ||
437 | return snprintf(buf, PAGE_SIZE, "%d\n", kone->actual_profile); | 334 | return snprintf(buf, PAGE_SIZE, "%d\n", kone->actual_profile); |
438 | } | 335 | } |
439 | 336 | ||
440 | static ssize_t kone_sysfs_show_actual_dpi(struct device *dev, | 337 | static ssize_t kone_sysfs_show_actual_dpi(struct device *dev, |
441 | struct device_attribute *attr, char *buf) | 338 | struct device_attribute *attr, char *buf) |
442 | { | 339 | { |
443 | struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev)); | 340 | struct kone_device *kone = |
341 | hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); | ||
444 | return snprintf(buf, PAGE_SIZE, "%d\n", kone->actual_dpi); | 342 | return snprintf(buf, PAGE_SIZE, "%d\n", kone->actual_dpi); |
445 | } | 343 | } |
446 | 344 | ||
@@ -448,11 +346,15 @@ static ssize_t kone_sysfs_show_actual_dpi(struct device *dev, | |||
448 | static ssize_t kone_sysfs_show_weight(struct device *dev, | 346 | static ssize_t kone_sysfs_show_weight(struct device *dev, |
449 | struct device_attribute *attr, char *buf) | 347 | struct device_attribute *attr, char *buf) |
450 | { | 348 | { |
451 | struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev)); | 349 | struct kone_device *kone; |
452 | struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); | 350 | struct usb_device *usb_dev; |
453 | int weight = 0; | 351 | int weight = 0; |
454 | int retval; | 352 | int retval; |
455 | 353 | ||
354 | dev = dev->parent->parent; | ||
355 | kone = hid_get_drvdata(dev_get_drvdata(dev)); | ||
356 | usb_dev = interface_to_usbdev(to_usb_interface(dev)); | ||
357 | |||
456 | mutex_lock(&kone->kone_lock); | 358 | mutex_lock(&kone->kone_lock); |
457 | retval = kone_get_weight(usb_dev, &weight); | 359 | retval = kone_get_weight(usb_dev, &weight); |
458 | mutex_unlock(&kone->kone_lock); | 360 | mutex_unlock(&kone->kone_lock); |
@@ -465,36 +367,24 @@ static ssize_t kone_sysfs_show_weight(struct device *dev, | |||
465 | static ssize_t kone_sysfs_show_firmware_version(struct device *dev, | 367 | static ssize_t kone_sysfs_show_firmware_version(struct device *dev, |
466 | struct device_attribute *attr, char *buf) | 368 | struct device_attribute *attr, char *buf) |
467 | { | 369 | { |
468 | struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev)); | 370 | struct kone_device *kone = |
371 | hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); | ||
469 | return snprintf(buf, PAGE_SIZE, "%d\n", kone->firmware_version); | 372 | return snprintf(buf, PAGE_SIZE, "%d\n", kone->firmware_version); |
470 | } | 373 | } |
471 | 374 | ||
472 | static ssize_t kone_sysfs_show_tcu(struct device *dev, | 375 | static ssize_t kone_sysfs_show_tcu(struct device *dev, |
473 | struct device_attribute *attr, char *buf) | 376 | struct device_attribute *attr, char *buf) |
474 | { | 377 | { |
475 | struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev)); | 378 | struct kone_device *kone = |
379 | hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); | ||
476 | return snprintf(buf, PAGE_SIZE, "%d\n", kone->settings.tcu); | 380 | return snprintf(buf, PAGE_SIZE, "%d\n", kone->settings.tcu); |
477 | } | 381 | } |
478 | 382 | ||
479 | static int kone_tcu_command(struct usb_device *usb_dev, int number) | 383 | static int kone_tcu_command(struct usb_device *usb_dev, int number) |
480 | { | 384 | { |
481 | int len; | 385 | unsigned char value; |
482 | char *value; | 386 | value = number; |
483 | 387 | return roccat_common_send(usb_dev, kone_command_calibrate, &value, 1); | |
484 | value = kmalloc(1, GFP_KERNEL); | ||
485 | if (!value) | ||
486 | return -ENOMEM; | ||
487 | |||
488 | *value = number; | ||
489 | |||
490 | len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), | ||
491 | USB_REQ_SET_CONFIGURATION, | ||
492 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, | ||
493 | kone_command_calibrate, 0, value, 1, | ||
494 | USB_CTRL_SET_TIMEOUT); | ||
495 | |||
496 | kfree(value); | ||
497 | return ((len != 1) ? -EIO : 0); | ||
498 | } | 388 | } |
499 | 389 | ||
500 | /* | 390 | /* |
@@ -504,11 +394,15 @@ static int kone_tcu_command(struct usb_device *usb_dev, int number) | |||
504 | static ssize_t kone_sysfs_set_tcu(struct device *dev, | 394 | static ssize_t kone_sysfs_set_tcu(struct device *dev, |
505 | struct device_attribute *attr, char const *buf, size_t size) | 395 | struct device_attribute *attr, char const *buf, size_t size) |
506 | { | 396 | { |
507 | struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev)); | 397 | struct kone_device *kone; |
508 | struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); | 398 | struct usb_device *usb_dev; |
509 | int retval; | 399 | int retval; |
510 | unsigned long state; | 400 | unsigned long state; |
511 | 401 | ||
402 | dev = dev->parent->parent; | ||
403 | kone = hid_get_drvdata(dev_get_drvdata(dev)); | ||
404 | usb_dev = interface_to_usbdev(to_usb_interface(dev)); | ||
405 | |||
512 | retval = strict_strtoul(buf, 10, &state); | 406 | retval = strict_strtoul(buf, 10, &state); |
513 | if (retval) | 407 | if (retval) |
514 | return retval; | 408 | return retval; |
@@ -556,7 +450,7 @@ static ssize_t kone_sysfs_set_tcu(struct device *dev, | |||
556 | 450 | ||
557 | retval = kone_set_settings(usb_dev, &kone->settings); | 451 | retval = kone_set_settings(usb_dev, &kone->settings); |
558 | if (retval) { | 452 | if (retval) { |
559 | dev_err(&usb_dev->dev, "couldn't set tcu state\n"); | 453 | hid_err(usb_dev, "couldn't set tcu state\n"); |
560 | /* | 454 | /* |
561 | * try to reread valid settings into buffer overwriting | 455 | * try to reread valid settings into buffer overwriting |
562 | * first error code | 456 | * first error code |
@@ -570,7 +464,7 @@ static ssize_t kone_sysfs_set_tcu(struct device *dev, | |||
570 | 464 | ||
571 | retval = size; | 465 | retval = size; |
572 | exit_no_settings: | 466 | exit_no_settings: |
573 | dev_err(&usb_dev->dev, "couldn't read settings\n"); | 467 | hid_err(usb_dev, "couldn't read settings\n"); |
574 | exit_unlock: | 468 | exit_unlock: |
575 | mutex_unlock(&kone->kone_lock); | 469 | mutex_unlock(&kone->kone_lock); |
576 | return retval; | 470 | return retval; |
@@ -579,18 +473,23 @@ exit_unlock: | |||
579 | static ssize_t kone_sysfs_show_startup_profile(struct device *dev, | 473 | static ssize_t kone_sysfs_show_startup_profile(struct device *dev, |
580 | struct device_attribute *attr, char *buf) | 474 | struct device_attribute *attr, char *buf) |
581 | { | 475 | { |
582 | struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev)); | 476 | struct kone_device *kone = |
477 | hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); | ||
583 | return snprintf(buf, PAGE_SIZE, "%d\n", kone->settings.startup_profile); | 478 | return snprintf(buf, PAGE_SIZE, "%d\n", kone->settings.startup_profile); |
584 | } | 479 | } |
585 | 480 | ||
586 | static ssize_t kone_sysfs_set_startup_profile(struct device *dev, | 481 | static ssize_t kone_sysfs_set_startup_profile(struct device *dev, |
587 | struct device_attribute *attr, char const *buf, size_t size) | 482 | struct device_attribute *attr, char const *buf, size_t size) |
588 | { | 483 | { |
589 | struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev)); | 484 | struct kone_device *kone; |
590 | struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); | 485 | struct usb_device *usb_dev; |
591 | int retval; | 486 | int retval; |
592 | unsigned long new_startup_profile; | 487 | unsigned long new_startup_profile; |
593 | 488 | ||
489 | dev = dev->parent->parent; | ||
490 | kone = hid_get_drvdata(dev_get_drvdata(dev)); | ||
491 | usb_dev = interface_to_usbdev(to_usb_interface(dev)); | ||
492 | |||
594 | retval = strict_strtoul(buf, 10, &new_startup_profile); | 493 | retval = strict_strtoul(buf, 10, &new_startup_profile); |
595 | if (retval) | 494 | if (retval) |
596 | return retval; | 495 | return retval; |
@@ -617,160 +516,92 @@ static ssize_t kone_sysfs_set_startup_profile(struct device *dev, | |||
617 | return size; | 516 | return size; |
618 | } | 517 | } |
619 | 518 | ||
620 | /* | 519 | static struct device_attribute kone_attributes[] = { |
621 | * Read actual dpi settings. | 520 | /* |
622 | * Returns raw value for further processing. Refer to enum kone_polling_rates to | 521 | * Read actual dpi settings. |
623 | * get real value. | 522 | * Returns raw value for further processing. Refer to enum |
624 | */ | 523 | * kone_polling_rates to get real value. |
625 | static DEVICE_ATTR(actual_dpi, 0440, kone_sysfs_show_actual_dpi, NULL); | 524 | */ |
626 | 525 | __ATTR(actual_dpi, 0440, kone_sysfs_show_actual_dpi, NULL), | |
627 | static DEVICE_ATTR(actual_profile, 0440, kone_sysfs_show_actual_profile, NULL); | 526 | __ATTR(actual_profile, 0440, kone_sysfs_show_actual_profile, NULL), |
628 | |||
629 | /* | ||
630 | * The mouse can be equipped with one of four supplied weights from 5 to 20 | ||
631 | * grams which are recognized and its value can be read out. | ||
632 | * This returns the raw value reported by the mouse for easy evaluation by | ||
633 | * software. Refer to enum kone_weights to get corresponding real weight. | ||
634 | */ | ||
635 | static DEVICE_ATTR(weight, 0440, kone_sysfs_show_weight, NULL); | ||
636 | |||
637 | /* | ||
638 | * Prints firmware version stored in mouse as integer. | ||
639 | * The raw value reported by the mouse is returned for easy evaluation, to get | ||
640 | * the real version number the decimal point has to be shifted 2 positions to | ||
641 | * the left. E.g. a value of 138 means 1.38. | ||
642 | */ | ||
643 | static DEVICE_ATTR(firmware_version, 0440, | ||
644 | kone_sysfs_show_firmware_version, NULL); | ||
645 | |||
646 | /* | ||
647 | * Prints state of Tracking Control Unit as number where 0 = off and 1 = on | ||
648 | * Writing 0 deactivates tcu and writing 1 calibrates and activates the tcu | ||
649 | */ | ||
650 | static DEVICE_ATTR(tcu, 0660, kone_sysfs_show_tcu, kone_sysfs_set_tcu); | ||
651 | |||
652 | /* Prints and takes the number of the profile the mouse starts with */ | ||
653 | static DEVICE_ATTR(startup_profile, 0660, | ||
654 | kone_sysfs_show_startup_profile, | ||
655 | kone_sysfs_set_startup_profile); | ||
656 | |||
657 | static struct attribute *kone_attributes[] = { | ||
658 | &dev_attr_actual_dpi.attr, | ||
659 | &dev_attr_actual_profile.attr, | ||
660 | &dev_attr_weight.attr, | ||
661 | &dev_attr_firmware_version.attr, | ||
662 | &dev_attr_tcu.attr, | ||
663 | &dev_attr_startup_profile.attr, | ||
664 | NULL | ||
665 | }; | ||
666 | |||
667 | static struct attribute_group kone_attribute_group = { | ||
668 | .attrs = kone_attributes | ||
669 | }; | ||
670 | |||
671 | static struct bin_attribute kone_settings_attr = { | ||
672 | .attr = { .name = "settings", .mode = 0660 }, | ||
673 | .size = sizeof(struct kone_settings), | ||
674 | .read = kone_sysfs_read_settings, | ||
675 | .write = kone_sysfs_write_settings | ||
676 | }; | ||
677 | 527 | ||
678 | static struct bin_attribute kone_profile1_attr = { | 528 | /* |
679 | .attr = { .name = "profile1", .mode = 0660 }, | 529 | * The mouse can be equipped with one of four supplied weights from 5 |
680 | .size = sizeof(struct kone_profile), | 530 | * to 20 grams which are recognized and its value can be read out. |
681 | .read = kone_sysfs_read_profile1, | 531 | * This returns the raw value reported by the mouse for easy evaluation |
682 | .write = kone_sysfs_write_profile1 | 532 | * by software. Refer to enum kone_weights to get corresponding real |
683 | }; | 533 | * weight. |
534 | */ | ||
535 | __ATTR(weight, 0440, kone_sysfs_show_weight, NULL), | ||
684 | 536 | ||
685 | static struct bin_attribute kone_profile2_attr = { | 537 | /* |
686 | .attr = { .name = "profile2", .mode = 0660 }, | 538 | * Prints firmware version stored in mouse as integer. |
687 | .size = sizeof(struct kone_profile), | 539 | * The raw value reported by the mouse is returned for easy evaluation, |
688 | .read = kone_sysfs_read_profile2, | 540 | * to get the real version number the decimal point has to be shifted 2 |
689 | .write = kone_sysfs_write_profile2 | 541 | * positions to the left. E.g. a value of 138 means 1.38. |
690 | }; | 542 | */ |
543 | __ATTR(firmware_version, 0440, | ||
544 | kone_sysfs_show_firmware_version, NULL), | ||
691 | 545 | ||
692 | static struct bin_attribute kone_profile3_attr = { | 546 | /* |
693 | .attr = { .name = "profile3", .mode = 0660 }, | 547 | * Prints state of Tracking Control Unit as number where 0 = off and |
694 | .size = sizeof(struct kone_profile), | 548 | * 1 = on. Writing 0 deactivates tcu and writing 1 calibrates and |
695 | .read = kone_sysfs_read_profile3, | 549 | * activates the tcu |
696 | .write = kone_sysfs_write_profile3 | 550 | */ |
697 | }; | 551 | __ATTR(tcu, 0660, kone_sysfs_show_tcu, kone_sysfs_set_tcu), |
698 | 552 | ||
699 | static struct bin_attribute kone_profile4_attr = { | 553 | /* Prints and takes the number of the profile the mouse starts with */ |
700 | .attr = { .name = "profile4", .mode = 0660 }, | 554 | __ATTR(startup_profile, 0660, |
701 | .size = sizeof(struct kone_profile), | 555 | kone_sysfs_show_startup_profile, |
702 | .read = kone_sysfs_read_profile4, | 556 | kone_sysfs_set_startup_profile), |
703 | .write = kone_sysfs_write_profile4 | 557 | __ATTR_NULL |
704 | }; | 558 | }; |
705 | 559 | ||
706 | static struct bin_attribute kone_profile5_attr = { | 560 | static struct bin_attribute kone_bin_attributes[] = { |
707 | .attr = { .name = "profile5", .mode = 0660 }, | 561 | { |
708 | .size = sizeof(struct kone_profile), | 562 | .attr = { .name = "settings", .mode = 0660 }, |
709 | .read = kone_sysfs_read_profile5, | 563 | .size = sizeof(struct kone_settings), |
710 | .write = kone_sysfs_write_profile5 | 564 | .read = kone_sysfs_read_settings, |
565 | .write = kone_sysfs_write_settings | ||
566 | }, | ||
567 | { | ||
568 | .attr = { .name = "profile1", .mode = 0660 }, | ||
569 | .size = sizeof(struct kone_profile), | ||
570 | .read = kone_sysfs_read_profilex, | ||
571 | .write = kone_sysfs_write_profilex, | ||
572 | .private = &profile_numbers[0] | ||
573 | }, | ||
574 | { | ||
575 | .attr = { .name = "profile2", .mode = 0660 }, | ||
576 | .size = sizeof(struct kone_profile), | ||
577 | .read = kone_sysfs_read_profilex, | ||
578 | .write = kone_sysfs_write_profilex, | ||
579 | .private = &profile_numbers[1] | ||
580 | }, | ||
581 | { | ||
582 | .attr = { .name = "profile3", .mode = 0660 }, | ||
583 | .size = sizeof(struct kone_profile), | ||
584 | .read = kone_sysfs_read_profilex, | ||
585 | .write = kone_sysfs_write_profilex, | ||
586 | .private = &profile_numbers[2] | ||
587 | }, | ||
588 | { | ||
589 | .attr = { .name = "profile4", .mode = 0660 }, | ||
590 | .size = sizeof(struct kone_profile), | ||
591 | .read = kone_sysfs_read_profilex, | ||
592 | .write = kone_sysfs_write_profilex, | ||
593 | .private = &profile_numbers[3] | ||
594 | }, | ||
595 | { | ||
596 | .attr = { .name = "profile5", .mode = 0660 }, | ||
597 | .size = sizeof(struct kone_profile), | ||
598 | .read = kone_sysfs_read_profilex, | ||
599 | .write = kone_sysfs_write_profilex, | ||
600 | .private = &profile_numbers[4] | ||
601 | }, | ||
602 | __ATTR_NULL | ||
711 | }; | 603 | }; |
712 | 604 | ||
713 | static int kone_create_sysfs_attributes(struct usb_interface *intf) | ||
714 | { | ||
715 | int retval; | ||
716 | |||
717 | retval = sysfs_create_group(&intf->dev.kobj, &kone_attribute_group); | ||
718 | if (retval) | ||
719 | goto exit_1; | ||
720 | |||
721 | retval = sysfs_create_bin_file(&intf->dev.kobj, &kone_settings_attr); | ||
722 | if (retval) | ||
723 | goto exit_2; | ||
724 | |||
725 | retval = sysfs_create_bin_file(&intf->dev.kobj, &kone_profile1_attr); | ||
726 | if (retval) | ||
727 | goto exit_3; | ||
728 | |||
729 | retval = sysfs_create_bin_file(&intf->dev.kobj, &kone_profile2_attr); | ||
730 | if (retval) | ||
731 | goto exit_4; | ||
732 | |||
733 | retval = sysfs_create_bin_file(&intf->dev.kobj, &kone_profile3_attr); | ||
734 | if (retval) | ||
735 | goto exit_5; | ||
736 | |||
737 | retval = sysfs_create_bin_file(&intf->dev.kobj, &kone_profile4_attr); | ||
738 | if (retval) | ||
739 | goto exit_6; | ||
740 | |||
741 | retval = sysfs_create_bin_file(&intf->dev.kobj, &kone_profile5_attr); | ||
742 | if (retval) | ||
743 | goto exit_7; | ||
744 | |||
745 | return 0; | ||
746 | |||
747 | exit_7: | ||
748 | sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile4_attr); | ||
749 | exit_6: | ||
750 | sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile3_attr); | ||
751 | exit_5: | ||
752 | sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile2_attr); | ||
753 | exit_4: | ||
754 | sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile1_attr); | ||
755 | exit_3: | ||
756 | sysfs_remove_bin_file(&intf->dev.kobj, &kone_settings_attr); | ||
757 | exit_2: | ||
758 | sysfs_remove_group(&intf->dev.kobj, &kone_attribute_group); | ||
759 | exit_1: | ||
760 | return retval; | ||
761 | } | ||
762 | |||
763 | static void kone_remove_sysfs_attributes(struct usb_interface *intf) | ||
764 | { | ||
765 | sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile5_attr); | ||
766 | sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile4_attr); | ||
767 | sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile3_attr); | ||
768 | sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile2_attr); | ||
769 | sysfs_remove_bin_file(&intf->dev.kobj, &kone_profile1_attr); | ||
770 | sysfs_remove_bin_file(&intf->dev.kobj, &kone_settings_attr); | ||
771 | sysfs_remove_group(&intf->dev.kobj, &kone_attribute_group); | ||
772 | } | ||
773 | |||
774 | static int kone_init_kone_device_struct(struct usb_device *usb_dev, | 605 | static int kone_init_kone_device_struct(struct usb_device *usb_dev, |
775 | struct kone_device *kone) | 606 | struct kone_device *kone) |
776 | { | 607 | { |
@@ -818,32 +649,26 @@ static int kone_init_specials(struct hid_device *hdev) | |||
818 | 649 | ||
819 | kone = kzalloc(sizeof(*kone), GFP_KERNEL); | 650 | kone = kzalloc(sizeof(*kone), GFP_KERNEL); |
820 | if (!kone) { | 651 | if (!kone) { |
821 | dev_err(&hdev->dev, "can't alloc device descriptor\n"); | 652 | hid_err(hdev, "can't alloc device descriptor\n"); |
822 | return -ENOMEM; | 653 | return -ENOMEM; |
823 | } | 654 | } |
824 | hid_set_drvdata(hdev, kone); | 655 | hid_set_drvdata(hdev, kone); |
825 | 656 | ||
826 | retval = kone_init_kone_device_struct(usb_dev, kone); | 657 | retval = kone_init_kone_device_struct(usb_dev, kone); |
827 | if (retval) { | 658 | if (retval) { |
828 | dev_err(&hdev->dev, | 659 | hid_err(hdev, "couldn't init struct kone_device\n"); |
829 | "couldn't init struct kone_device\n"); | ||
830 | goto exit_free; | 660 | goto exit_free; |
831 | } | 661 | } |
832 | 662 | ||
833 | retval = roccat_connect(hdev); | 663 | retval = roccat_connect(kone_class, hdev, |
664 | sizeof(struct kone_roccat_report)); | ||
834 | if (retval < 0) { | 665 | if (retval < 0) { |
835 | dev_err(&hdev->dev, "couldn't init char dev\n"); | 666 | hid_err(hdev, "couldn't init char dev\n"); |
836 | /* be tolerant about not getting chrdev */ | 667 | /* be tolerant about not getting chrdev */ |
837 | } else { | 668 | } else { |
838 | kone->roccat_claimed = 1; | 669 | kone->roccat_claimed = 1; |
839 | kone->chrdev_minor = retval; | 670 | kone->chrdev_minor = retval; |
840 | } | 671 | } |
841 | |||
842 | retval = kone_create_sysfs_attributes(intf); | ||
843 | if (retval) { | ||
844 | dev_err(&hdev->dev, "cannot create sysfs files\n"); | ||
845 | goto exit_free; | ||
846 | } | ||
847 | } else { | 672 | } else { |
848 | hid_set_drvdata(hdev, NULL); | 673 | hid_set_drvdata(hdev, NULL); |
849 | } | 674 | } |
@@ -854,7 +679,6 @@ exit_free: | |||
854 | return retval; | 679 | return retval; |
855 | } | 680 | } |
856 | 681 | ||
857 | |||
858 | static void kone_remove_specials(struct hid_device *hdev) | 682 | static void kone_remove_specials(struct hid_device *hdev) |
859 | { | 683 | { |
860 | struct usb_interface *intf = to_usb_interface(hdev->dev.parent); | 684 | struct usb_interface *intf = to_usb_interface(hdev->dev.parent); |
@@ -862,7 +686,6 @@ static void kone_remove_specials(struct hid_device *hdev) | |||
862 | 686 | ||
863 | if (intf->cur_altsetting->desc.bInterfaceProtocol | 687 | if (intf->cur_altsetting->desc.bInterfaceProtocol |
864 | == USB_INTERFACE_PROTOCOL_MOUSE) { | 688 | == USB_INTERFACE_PROTOCOL_MOUSE) { |
865 | kone_remove_sysfs_attributes(intf); | ||
866 | kone = hid_get_drvdata(hdev); | 689 | kone = hid_get_drvdata(hdev); |
867 | if (kone->roccat_claimed) | 690 | if (kone->roccat_claimed) |
868 | roccat_disconnect(kone->chrdev_minor); | 691 | roccat_disconnect(kone->chrdev_minor); |
@@ -876,19 +699,19 @@ static int kone_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
876 | 699 | ||
877 | retval = hid_parse(hdev); | 700 | retval = hid_parse(hdev); |
878 | if (retval) { | 701 | if (retval) { |
879 | dev_err(&hdev->dev, "parse failed\n"); | 702 | hid_err(hdev, "parse failed\n"); |
880 | goto exit; | 703 | goto exit; |
881 | } | 704 | } |
882 | 705 | ||
883 | retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT); | 706 | retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT); |
884 | if (retval) { | 707 | if (retval) { |
885 | dev_err(&hdev->dev, "hw start failed\n"); | 708 | hid_err(hdev, "hw start failed\n"); |
886 | goto exit; | 709 | goto exit; |
887 | } | 710 | } |
888 | 711 | ||
889 | retval = kone_init_specials(hdev); | 712 | retval = kone_init_specials(hdev); |
890 | if (retval) { | 713 | if (retval) { |
891 | dev_err(&hdev->dev, "couldn't install mouse\n"); | 714 | hid_err(hdev, "couldn't install mouse\n"); |
892 | goto exit_stop; | 715 | goto exit_stop; |
893 | } | 716 | } |
894 | 717 | ||
@@ -938,8 +761,7 @@ static void kone_report_to_chrdev(struct kone_device const *kone, | |||
938 | roccat_report.value = event->value; | 761 | roccat_report.value = event->value; |
939 | roccat_report.key = 0; | 762 | roccat_report.key = 0; |
940 | roccat_report_event(kone->chrdev_minor, | 763 | roccat_report_event(kone->chrdev_minor, |
941 | (uint8_t *)&roccat_report, | 764 | (uint8_t *)&roccat_report); |
942 | sizeof(struct kone_roccat_report)); | ||
943 | break; | 765 | break; |
944 | case kone_mouse_event_call_overlong_macro: | 766 | case kone_mouse_event_call_overlong_macro: |
945 | if (event->value == kone_keystroke_action_press) { | 767 | if (event->value == kone_keystroke_action_press) { |
@@ -947,8 +769,7 @@ static void kone_report_to_chrdev(struct kone_device const *kone, | |||
947 | roccat_report.value = kone->actual_profile; | 769 | roccat_report.value = kone->actual_profile; |
948 | roccat_report.key = event->macro_key; | 770 | roccat_report.key = event->macro_key; |
949 | roccat_report_event(kone->chrdev_minor, | 771 | roccat_report_event(kone->chrdev_minor, |
950 | (uint8_t *)&roccat_report, | 772 | (uint8_t *)&roccat_report); |
951 | sizeof(struct kone_roccat_report)); | ||
952 | } | 773 | } |
953 | break; | 774 | break; |
954 | } | 775 | } |
@@ -1006,12 +827,25 @@ static struct hid_driver kone_driver = { | |||
1006 | 827 | ||
1007 | static int __init kone_init(void) | 828 | static int __init kone_init(void) |
1008 | { | 829 | { |
1009 | return hid_register_driver(&kone_driver); | 830 | int retval; |
831 | |||
832 | /* class name has to be same as driver name */ | ||
833 | kone_class = class_create(THIS_MODULE, "kone"); | ||
834 | if (IS_ERR(kone_class)) | ||
835 | return PTR_ERR(kone_class); | ||
836 | kone_class->dev_attrs = kone_attributes; | ||
837 | kone_class->dev_bin_attrs = kone_bin_attributes; | ||
838 | |||
839 | retval = hid_register_driver(&kone_driver); | ||
840 | if (retval) | ||
841 | class_destroy(kone_class); | ||
842 | return retval; | ||
1010 | } | 843 | } |
1011 | 844 | ||
1012 | static void __exit kone_exit(void) | 845 | static void __exit kone_exit(void) |
1013 | { | 846 | { |
1014 | hid_unregister_driver(&kone_driver); | 847 | hid_unregister_driver(&kone_driver); |
848 | class_destroy(kone_class); | ||
1015 | } | 849 | } |
1016 | 850 | ||
1017 | module_init(kone_init); | 851 | module_init(kone_init); |
diff --git a/drivers/hid/hid-roccat-kone.h b/drivers/hid/hid-roccat-kone.h index 130d6566ea82..4109a028e138 100644 --- a/drivers/hid/hid-roccat-kone.h +++ b/drivers/hid/hid-roccat-kone.h | |||
@@ -14,14 +14,11 @@ | |||
14 | 14 | ||
15 | #include <linux/types.h> | 15 | #include <linux/types.h> |
16 | 16 | ||
17 | #pragma pack(push) | ||
18 | #pragma pack(1) | ||
19 | |||
20 | struct kone_keystroke { | 17 | struct kone_keystroke { |
21 | uint8_t key; | 18 | uint8_t key; |
22 | uint8_t action; | 19 | uint8_t action; |
23 | uint16_t period; /* in milliseconds */ | 20 | uint16_t period; /* in milliseconds */ |
24 | }; | 21 | } __attribute__ ((__packed__)); |
25 | 22 | ||
26 | enum kone_keystroke_buttons { | 23 | enum kone_keystroke_buttons { |
27 | kone_keystroke_button_1 = 0xf0, /* left mouse button */ | 24 | kone_keystroke_button_1 = 0xf0, /* left mouse button */ |
@@ -44,7 +41,7 @@ struct kone_button_info { | |||
44 | uint8_t macro_name[16]; /* can be max 15 chars long */ | 41 | uint8_t macro_name[16]; /* can be max 15 chars long */ |
45 | uint8_t count; | 42 | uint8_t count; |
46 | struct kone_keystroke keystrokes[20]; | 43 | struct kone_keystroke keystrokes[20]; |
47 | }; | 44 | } __attribute__ ((__packed__)); |
48 | 45 | ||
49 | enum kone_button_info_types { | 46 | enum kone_button_info_types { |
50 | /* valid button types until firmware 1.32 */ | 47 | /* valid button types until firmware 1.32 */ |
@@ -95,7 +92,7 @@ struct kone_light_info { | |||
95 | uint8_t red; /* range 0x00-0xff */ | 92 | uint8_t red; /* range 0x00-0xff */ |
96 | uint8_t green; /* range 0x00-0xff */ | 93 | uint8_t green; /* range 0x00-0xff */ |
97 | uint8_t blue; /* range 0x00-0xff */ | 94 | uint8_t blue; /* range 0x00-0xff */ |
98 | }; | 95 | } __attribute__ ((__packed__)); |
99 | 96 | ||
100 | struct kone_profile { | 97 | struct kone_profile { |
101 | uint16_t size; /* always 975 */ | 98 | uint16_t size; /* always 975 */ |
@@ -130,7 +127,7 @@ struct kone_profile { | |||
130 | struct kone_button_info button_infos[8]; | 127 | struct kone_button_info button_infos[8]; |
131 | 128 | ||
132 | uint16_t checksum; /* \brief holds checksum of struct */ | 129 | uint16_t checksum; /* \brief holds checksum of struct */ |
133 | }; | 130 | } __attribute__ ((__packed__)); |
134 | 131 | ||
135 | enum kone_polling_rates { | 132 | enum kone_polling_rates { |
136 | kone_polling_rate_125 = 1, | 133 | kone_polling_rate_125 = 1, |
@@ -147,7 +144,7 @@ struct kone_settings { | |||
147 | uint8_t calibration_data[4]; | 144 | uint8_t calibration_data[4]; |
148 | uint8_t unknown3[2]; | 145 | uint8_t unknown3[2]; |
149 | uint16_t checksum; | 146 | uint16_t checksum; |
150 | }; | 147 | } __attribute__ ((__packed__)); |
151 | 148 | ||
152 | /* | 149 | /* |
153 | * 12 byte mouse event read by interrupt_read | 150 | * 12 byte mouse event read by interrupt_read |
@@ -163,13 +160,13 @@ struct kone_mouse_event { | |||
163 | uint8_t event; | 160 | uint8_t event; |
164 | uint8_t value; /* press = 0, release = 1 */ | 161 | uint8_t value; /* press = 0, release = 1 */ |
165 | uint8_t macro_key; /* 0 to 8 */ | 162 | uint8_t macro_key; /* 0 to 8 */ |
166 | }; | 163 | } __attribute__ ((__packed__)); |
167 | 164 | ||
168 | enum kone_mouse_events { | 165 | enum kone_mouse_events { |
169 | /* osd events are thought to be display on screen */ | 166 | /* osd events are thought to be display on screen */ |
170 | kone_mouse_event_osd_dpi = 0xa0, | 167 | kone_mouse_event_osd_dpi = 0xa0, |
171 | kone_mouse_event_osd_profile = 0xb0, | 168 | kone_mouse_event_osd_profile = 0xb0, |
172 | /* TODO clarify meaning and occurence of kone_mouse_event_calibration */ | 169 | /* TODO clarify meaning and occurrence of kone_mouse_event_calibration */ |
173 | kone_mouse_event_calibration = 0xc0, | 170 | kone_mouse_event_calibration = 0xc0, |
174 | kone_mouse_event_call_overlong_macro = 0xe0, | 171 | kone_mouse_event_call_overlong_macro = 0xe0, |
175 | /* switch events notify if user changed values with mousebutton click */ | 172 | /* switch events notify if user changed values with mousebutton click */ |
@@ -191,9 +188,7 @@ struct kone_roccat_report { | |||
191 | uint8_t event; | 188 | uint8_t event; |
192 | uint8_t value; /* holds dpi or profile value */ | 189 | uint8_t value; /* holds dpi or profile value */ |
193 | uint8_t key; /* macro key on overlong macro execution */ | 190 | uint8_t key; /* macro key on overlong macro execution */ |
194 | }; | 191 | } __attribute__ ((__packed__)); |
195 | |||
196 | #pragma pack(pop) | ||
197 | 192 | ||
198 | struct kone_device { | 193 | struct kone_device { |
199 | /* | 194 | /* |
diff --git a/drivers/hid/hid-roccat-koneplus.c b/drivers/hid/hid-roccat-koneplus.c new file mode 100644 index 000000000000..5b640a7a15a7 --- /dev/null +++ b/drivers/hid/hid-roccat-koneplus.c | |||
@@ -0,0 +1,792 @@ | |||
1 | /* | ||
2 | * Roccat Kone[+] driver for Linux | ||
3 | * | ||
4 | * Copyright (c) 2010 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 Kone[+] is an updated/improved version of the Kone with more memory | ||
16 | * and functionality and without the non-standard behaviours the Kone had. | ||
17 | */ | ||
18 | |||
19 | #include <linux/device.h> | ||
20 | #include <linux/input.h> | ||
21 | #include <linux/hid.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/hid-roccat.h> | ||
25 | #include "hid-ids.h" | ||
26 | #include "hid-roccat-common.h" | ||
27 | #include "hid-roccat-koneplus.h" | ||
28 | |||
29 | static uint profile_numbers[5] = {0, 1, 2, 3, 4}; | ||
30 | |||
31 | static struct class *koneplus_class; | ||
32 | |||
33 | static void koneplus_profile_activated(struct koneplus_device *koneplus, | ||
34 | uint new_profile) | ||
35 | { | ||
36 | koneplus->actual_profile = new_profile; | ||
37 | } | ||
38 | |||
39 | static int koneplus_send_control(struct usb_device *usb_dev, uint value, | ||
40 | enum koneplus_control_requests request) | ||
41 | { | ||
42 | struct koneplus_control control; | ||
43 | |||
44 | if ((request == KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS || | ||
45 | request == KONEPLUS_CONTROL_REQUEST_PROFILE_BUTTONS) && | ||
46 | value > 4) | ||
47 | return -EINVAL; | ||
48 | |||
49 | control.command = KONEPLUS_COMMAND_CONTROL; | ||
50 | control.value = value; | ||
51 | control.request = request; | ||
52 | |||
53 | return roccat_common_send(usb_dev, KONEPLUS_USB_COMMAND_CONTROL, | ||
54 | &control, sizeof(struct koneplus_control)); | ||
55 | } | ||
56 | |||
57 | static int koneplus_receive_control_status(struct usb_device *usb_dev) | ||
58 | { | ||
59 | int retval; | ||
60 | struct koneplus_control control; | ||
61 | |||
62 | do { | ||
63 | retval = roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_CONTROL, | ||
64 | &control, sizeof(struct koneplus_control)); | ||
65 | |||
66 | /* check if we get a completely wrong answer */ | ||
67 | if (retval) | ||
68 | return retval; | ||
69 | |||
70 | if (control.value == KONEPLUS_CONTROL_REQUEST_STATUS_OK) | ||
71 | return 0; | ||
72 | |||
73 | /* indicates that hardware needs some more time to complete action */ | ||
74 | if (control.value == KONEPLUS_CONTROL_REQUEST_STATUS_WAIT) { | ||
75 | msleep(500); /* windows driver uses 1000 */ | ||
76 | continue; | ||
77 | } | ||
78 | |||
79 | /* seems to be critical - replug necessary */ | ||
80 | if (control.value == KONEPLUS_CONTROL_REQUEST_STATUS_OVERLOAD) | ||
81 | return -EINVAL; | ||
82 | |||
83 | hid_err(usb_dev, "koneplus_receive_control_status: " | ||
84 | "unknown response value 0x%x\n", control.value); | ||
85 | return -EINVAL; | ||
86 | } while (1); | ||
87 | } | ||
88 | |||
89 | static int koneplus_send(struct usb_device *usb_dev, uint command, | ||
90 | void const *buf, uint size) | ||
91 | { | ||
92 | int retval; | ||
93 | |||
94 | retval = roccat_common_send(usb_dev, command, buf, size); | ||
95 | if (retval) | ||
96 | return retval; | ||
97 | |||
98 | return koneplus_receive_control_status(usb_dev); | ||
99 | } | ||
100 | |||
101 | static int koneplus_select_profile(struct usb_device *usb_dev, uint number, | ||
102 | enum koneplus_control_requests request) | ||
103 | { | ||
104 | int retval; | ||
105 | |||
106 | retval = koneplus_send_control(usb_dev, number, request); | ||
107 | if (retval) | ||
108 | return retval; | ||
109 | |||
110 | /* allow time to settle things - windows driver uses 500 */ | ||
111 | msleep(100); | ||
112 | |||
113 | retval = koneplus_receive_control_status(usb_dev); | ||
114 | if (retval) | ||
115 | return retval; | ||
116 | |||
117 | return 0; | ||
118 | } | ||
119 | |||
120 | static int koneplus_get_info(struct usb_device *usb_dev, | ||
121 | struct koneplus_info *buf) | ||
122 | { | ||
123 | return roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_INFO, | ||
124 | buf, sizeof(struct koneplus_info)); | ||
125 | } | ||
126 | |||
127 | static int koneplus_get_profile_settings(struct usb_device *usb_dev, | ||
128 | struct koneplus_profile_settings *buf, uint number) | ||
129 | { | ||
130 | int retval; | ||
131 | |||
132 | retval = koneplus_select_profile(usb_dev, number, | ||
133 | KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS); | ||
134 | if (retval) | ||
135 | return retval; | ||
136 | |||
137 | return roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_SETTINGS, | ||
138 | buf, sizeof(struct koneplus_profile_settings)); | ||
139 | } | ||
140 | |||
141 | static int koneplus_set_profile_settings(struct usb_device *usb_dev, | ||
142 | struct koneplus_profile_settings const *settings) | ||
143 | { | ||
144 | return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_SETTINGS, | ||
145 | settings, sizeof(struct koneplus_profile_settings)); | ||
146 | } | ||
147 | |||
148 | static int koneplus_get_profile_buttons(struct usb_device *usb_dev, | ||
149 | struct koneplus_profile_buttons *buf, int number) | ||
150 | { | ||
151 | int retval; | ||
152 | |||
153 | retval = koneplus_select_profile(usb_dev, number, | ||
154 | KONEPLUS_CONTROL_REQUEST_PROFILE_BUTTONS); | ||
155 | if (retval) | ||
156 | return retval; | ||
157 | |||
158 | return roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_BUTTONS, | ||
159 | buf, sizeof(struct koneplus_profile_buttons)); | ||
160 | } | ||
161 | |||
162 | static int koneplus_set_profile_buttons(struct usb_device *usb_dev, | ||
163 | struct koneplus_profile_buttons const *buttons) | ||
164 | { | ||
165 | return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_BUTTONS, | ||
166 | buttons, sizeof(struct koneplus_profile_buttons)); | ||
167 | } | ||
168 | |||
169 | /* retval is 0-4 on success, < 0 on error */ | ||
170 | static int koneplus_get_actual_profile(struct usb_device *usb_dev) | ||
171 | { | ||
172 | struct koneplus_actual_profile buf; | ||
173 | int retval; | ||
174 | |||
175 | retval = roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_ACTUAL_PROFILE, | ||
176 | &buf, sizeof(struct koneplus_actual_profile)); | ||
177 | |||
178 | return retval ? retval : buf.actual_profile; | ||
179 | } | ||
180 | |||
181 | static int koneplus_set_actual_profile(struct usb_device *usb_dev, | ||
182 | int new_profile) | ||
183 | { | ||
184 | struct koneplus_actual_profile buf; | ||
185 | |||
186 | buf.command = KONEPLUS_COMMAND_ACTUAL_PROFILE; | ||
187 | buf.size = sizeof(struct koneplus_actual_profile); | ||
188 | buf.actual_profile = new_profile; | ||
189 | |||
190 | return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_ACTUAL_PROFILE, | ||
191 | &buf, sizeof(struct koneplus_actual_profile)); | ||
192 | } | ||
193 | |||
194 | static ssize_t koneplus_sysfs_read(struct file *fp, struct kobject *kobj, | ||
195 | char *buf, loff_t off, size_t count, | ||
196 | size_t real_size, uint command) | ||
197 | { | ||
198 | struct device *dev = | ||
199 | container_of(kobj, struct device, kobj)->parent->parent; | ||
200 | struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev)); | ||
201 | struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); | ||
202 | int retval; | ||
203 | |||
204 | if (off >= real_size) | ||
205 | return 0; | ||
206 | |||
207 | if (off != 0 || count != real_size) | ||
208 | return -EINVAL; | ||
209 | |||
210 | mutex_lock(&koneplus->koneplus_lock); | ||
211 | retval = roccat_common_receive(usb_dev, command, buf, real_size); | ||
212 | mutex_unlock(&koneplus->koneplus_lock); | ||
213 | |||
214 | if (retval) | ||
215 | return retval; | ||
216 | |||
217 | return real_size; | ||
218 | } | ||
219 | |||
220 | static ssize_t koneplus_sysfs_write(struct file *fp, struct kobject *kobj, | ||
221 | void const *buf, loff_t off, size_t count, | ||
222 | size_t real_size, uint command) | ||
223 | { | ||
224 | struct device *dev = | ||
225 | container_of(kobj, struct device, kobj)->parent->parent; | ||
226 | struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev)); | ||
227 | struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); | ||
228 | int retval; | ||
229 | |||
230 | if (off != 0 || count != real_size) | ||
231 | return -EINVAL; | ||
232 | |||
233 | mutex_lock(&koneplus->koneplus_lock); | ||
234 | retval = koneplus_send(usb_dev, command, buf, real_size); | ||
235 | mutex_unlock(&koneplus->koneplus_lock); | ||
236 | |||
237 | if (retval) | ||
238 | return retval; | ||
239 | |||
240 | return real_size; | ||
241 | } | ||
242 | |||
243 | static ssize_t koneplus_sysfs_write_macro(struct file *fp, | ||
244 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
245 | loff_t off, size_t count) | ||
246 | { | ||
247 | return koneplus_sysfs_write(fp, kobj, buf, off, count, | ||
248 | sizeof(struct koneplus_macro), KONEPLUS_USB_COMMAND_MACRO); | ||
249 | } | ||
250 | |||
251 | static ssize_t koneplus_sysfs_read_sensor(struct file *fp, | ||
252 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
253 | loff_t off, size_t count) | ||
254 | { | ||
255 | return koneplus_sysfs_read(fp, kobj, buf, off, count, | ||
256 | sizeof(struct koneplus_sensor), KONEPLUS_USB_COMMAND_SENSOR); | ||
257 | } | ||
258 | |||
259 | static ssize_t koneplus_sysfs_write_sensor(struct file *fp, | ||
260 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
261 | loff_t off, size_t count) | ||
262 | { | ||
263 | return koneplus_sysfs_write(fp, kobj, buf, off, count, | ||
264 | sizeof(struct koneplus_sensor), KONEPLUS_USB_COMMAND_SENSOR); | ||
265 | } | ||
266 | |||
267 | static ssize_t koneplus_sysfs_write_tcu(struct file *fp, | ||
268 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
269 | loff_t off, size_t count) | ||
270 | { | ||
271 | return koneplus_sysfs_write(fp, kobj, buf, off, count, | ||
272 | sizeof(struct koneplus_tcu), KONEPLUS_USB_COMMAND_TCU); | ||
273 | } | ||
274 | |||
275 | static ssize_t koneplus_sysfs_read_tcu_image(struct file *fp, | ||
276 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
277 | loff_t off, size_t count) | ||
278 | { | ||
279 | return koneplus_sysfs_read(fp, kobj, buf, off, count, | ||
280 | sizeof(struct koneplus_tcu_image), KONEPLUS_USB_COMMAND_TCU); | ||
281 | } | ||
282 | |||
283 | static ssize_t koneplus_sysfs_read_profilex_settings(struct file *fp, | ||
284 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
285 | loff_t off, size_t count) | ||
286 | { | ||
287 | struct device *dev = | ||
288 | container_of(kobj, struct device, kobj)->parent->parent; | ||
289 | struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev)); | ||
290 | |||
291 | if (off >= sizeof(struct koneplus_profile_settings)) | ||
292 | return 0; | ||
293 | |||
294 | if (off + count > sizeof(struct koneplus_profile_settings)) | ||
295 | count = sizeof(struct koneplus_profile_settings) - off; | ||
296 | |||
297 | mutex_lock(&koneplus->koneplus_lock); | ||
298 | memcpy(buf, ((char const *)&koneplus->profile_settings[*(uint *)(attr->private)]) + off, | ||
299 | count); | ||
300 | mutex_unlock(&koneplus->koneplus_lock); | ||
301 | |||
302 | return count; | ||
303 | } | ||
304 | |||
305 | static ssize_t koneplus_sysfs_write_profile_settings(struct file *fp, | ||
306 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
307 | loff_t off, size_t count) | ||
308 | { | ||
309 | struct device *dev = | ||
310 | container_of(kobj, struct device, kobj)->parent->parent; | ||
311 | struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev)); | ||
312 | struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); | ||
313 | int retval = 0; | ||
314 | int difference; | ||
315 | int profile_number; | ||
316 | struct koneplus_profile_settings *profile_settings; | ||
317 | |||
318 | if (off != 0 || count != sizeof(struct koneplus_profile_settings)) | ||
319 | return -EINVAL; | ||
320 | |||
321 | profile_number = ((struct koneplus_profile_settings const *)buf)->number; | ||
322 | profile_settings = &koneplus->profile_settings[profile_number]; | ||
323 | |||
324 | mutex_lock(&koneplus->koneplus_lock); | ||
325 | difference = memcmp(buf, profile_settings, | ||
326 | sizeof(struct koneplus_profile_settings)); | ||
327 | if (difference) { | ||
328 | retval = koneplus_set_profile_settings(usb_dev, | ||
329 | (struct koneplus_profile_settings const *)buf); | ||
330 | if (!retval) | ||
331 | memcpy(profile_settings, buf, | ||
332 | sizeof(struct koneplus_profile_settings)); | ||
333 | } | ||
334 | mutex_unlock(&koneplus->koneplus_lock); | ||
335 | |||
336 | if (retval) | ||
337 | return retval; | ||
338 | |||
339 | return sizeof(struct koneplus_profile_settings); | ||
340 | } | ||
341 | |||
342 | static ssize_t koneplus_sysfs_read_profilex_buttons(struct file *fp, | ||
343 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
344 | loff_t off, size_t count) | ||
345 | { | ||
346 | struct device *dev = | ||
347 | container_of(kobj, struct device, kobj)->parent->parent; | ||
348 | struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev)); | ||
349 | |||
350 | if (off >= sizeof(struct koneplus_profile_buttons)) | ||
351 | return 0; | ||
352 | |||
353 | if (off + count > sizeof(struct koneplus_profile_buttons)) | ||
354 | count = sizeof(struct koneplus_profile_buttons) - off; | ||
355 | |||
356 | mutex_lock(&koneplus->koneplus_lock); | ||
357 | memcpy(buf, ((char const *)&koneplus->profile_buttons[*(uint *)(attr->private)]) + off, | ||
358 | count); | ||
359 | mutex_unlock(&koneplus->koneplus_lock); | ||
360 | |||
361 | return count; | ||
362 | } | ||
363 | |||
364 | static ssize_t koneplus_sysfs_write_profile_buttons(struct file *fp, | ||
365 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
366 | loff_t off, size_t count) | ||
367 | { | ||
368 | struct device *dev = | ||
369 | container_of(kobj, struct device, kobj)->parent->parent; | ||
370 | struct koneplus_device *koneplus = hid_get_drvdata(dev_get_drvdata(dev)); | ||
371 | struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); | ||
372 | int retval = 0; | ||
373 | int difference; | ||
374 | uint profile_number; | ||
375 | struct koneplus_profile_buttons *profile_buttons; | ||
376 | |||
377 | if (off != 0 || count != sizeof(struct koneplus_profile_buttons)) | ||
378 | return -EINVAL; | ||
379 | |||
380 | profile_number = ((struct koneplus_profile_buttons const *)buf)->number; | ||
381 | profile_buttons = &koneplus->profile_buttons[profile_number]; | ||
382 | |||
383 | mutex_lock(&koneplus->koneplus_lock); | ||
384 | difference = memcmp(buf, profile_buttons, | ||
385 | sizeof(struct koneplus_profile_buttons)); | ||
386 | if (difference) { | ||
387 | retval = koneplus_set_profile_buttons(usb_dev, | ||
388 | (struct koneplus_profile_buttons const *)buf); | ||
389 | if (!retval) | ||
390 | memcpy(profile_buttons, buf, | ||
391 | sizeof(struct koneplus_profile_buttons)); | ||
392 | } | ||
393 | mutex_unlock(&koneplus->koneplus_lock); | ||
394 | |||
395 | if (retval) | ||
396 | return retval; | ||
397 | |||
398 | return sizeof(struct koneplus_profile_buttons); | ||
399 | } | ||
400 | |||
401 | static ssize_t koneplus_sysfs_show_actual_profile(struct device *dev, | ||
402 | struct device_attribute *attr, char *buf) | ||
403 | { | ||
404 | struct koneplus_device *koneplus = | ||
405 | hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); | ||
406 | return snprintf(buf, PAGE_SIZE, "%d\n", koneplus->actual_profile); | ||
407 | } | ||
408 | |||
409 | static ssize_t koneplus_sysfs_set_actual_profile(struct device *dev, | ||
410 | struct device_attribute *attr, char const *buf, size_t size) | ||
411 | { | ||
412 | struct koneplus_device *koneplus; | ||
413 | struct usb_device *usb_dev; | ||
414 | unsigned long profile; | ||
415 | int retval; | ||
416 | struct koneplus_roccat_report roccat_report; | ||
417 | |||
418 | dev = dev->parent->parent; | ||
419 | koneplus = hid_get_drvdata(dev_get_drvdata(dev)); | ||
420 | usb_dev = interface_to_usbdev(to_usb_interface(dev)); | ||
421 | |||
422 | retval = strict_strtoul(buf, 10, &profile); | ||
423 | if (retval) | ||
424 | return retval; | ||
425 | |||
426 | mutex_lock(&koneplus->koneplus_lock); | ||
427 | |||
428 | retval = koneplus_set_actual_profile(usb_dev, profile); | ||
429 | if (retval) { | ||
430 | mutex_unlock(&koneplus->koneplus_lock); | ||
431 | return retval; | ||
432 | } | ||
433 | |||
434 | koneplus->actual_profile = profile; | ||
435 | |||
436 | roccat_report.type = KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE; | ||
437 | roccat_report.data1 = profile + 1; | ||
438 | roccat_report.data2 = 0; | ||
439 | roccat_report.profile = profile + 1; | ||
440 | roccat_report_event(koneplus->chrdev_minor, | ||
441 | (uint8_t const *)&roccat_report); | ||
442 | |||
443 | mutex_unlock(&koneplus->koneplus_lock); | ||
444 | |||
445 | return size; | ||
446 | } | ||
447 | |||
448 | static ssize_t koneplus_sysfs_show_firmware_version(struct device *dev, | ||
449 | struct device_attribute *attr, char *buf) | ||
450 | { | ||
451 | struct koneplus_device *koneplus = | ||
452 | hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); | ||
453 | return snprintf(buf, PAGE_SIZE, "%d\n", koneplus->info.firmware_version); | ||
454 | } | ||
455 | |||
456 | static struct device_attribute koneplus_attributes[] = { | ||
457 | __ATTR(actual_profile, 0660, | ||
458 | koneplus_sysfs_show_actual_profile, | ||
459 | koneplus_sysfs_set_actual_profile), | ||
460 | __ATTR(startup_profile, 0660, | ||
461 | koneplus_sysfs_show_actual_profile, | ||
462 | koneplus_sysfs_set_actual_profile), | ||
463 | __ATTR(firmware_version, 0440, | ||
464 | koneplus_sysfs_show_firmware_version, NULL), | ||
465 | __ATTR_NULL | ||
466 | }; | ||
467 | |||
468 | static struct bin_attribute koneplus_bin_attributes[] = { | ||
469 | { | ||
470 | .attr = { .name = "sensor", .mode = 0660 }, | ||
471 | .size = sizeof(struct koneplus_sensor), | ||
472 | .read = koneplus_sysfs_read_sensor, | ||
473 | .write = koneplus_sysfs_write_sensor | ||
474 | }, | ||
475 | { | ||
476 | .attr = { .name = "tcu", .mode = 0220 }, | ||
477 | .size = sizeof(struct koneplus_tcu), | ||
478 | .write = koneplus_sysfs_write_tcu | ||
479 | }, | ||
480 | { | ||
481 | .attr = { .name = "tcu_image", .mode = 0440 }, | ||
482 | .size = sizeof(struct koneplus_tcu_image), | ||
483 | .read = koneplus_sysfs_read_tcu_image | ||
484 | }, | ||
485 | { | ||
486 | .attr = { .name = "profile_settings", .mode = 0220 }, | ||
487 | .size = sizeof(struct koneplus_profile_settings), | ||
488 | .write = koneplus_sysfs_write_profile_settings | ||
489 | }, | ||
490 | { | ||
491 | .attr = { .name = "profile1_settings", .mode = 0440 }, | ||
492 | .size = sizeof(struct koneplus_profile_settings), | ||
493 | .read = koneplus_sysfs_read_profilex_settings, | ||
494 | .private = &profile_numbers[0] | ||
495 | }, | ||
496 | { | ||
497 | .attr = { .name = "profile2_settings", .mode = 0440 }, | ||
498 | .size = sizeof(struct koneplus_profile_settings), | ||
499 | .read = koneplus_sysfs_read_profilex_settings, | ||
500 | .private = &profile_numbers[1] | ||
501 | }, | ||
502 | { | ||
503 | .attr = { .name = "profile3_settings", .mode = 0440 }, | ||
504 | .size = sizeof(struct koneplus_profile_settings), | ||
505 | .read = koneplus_sysfs_read_profilex_settings, | ||
506 | .private = &profile_numbers[2] | ||
507 | }, | ||
508 | { | ||
509 | .attr = { .name = "profile4_settings", .mode = 0440 }, | ||
510 | .size = sizeof(struct koneplus_profile_settings), | ||
511 | .read = koneplus_sysfs_read_profilex_settings, | ||
512 | .private = &profile_numbers[3] | ||
513 | }, | ||
514 | { | ||
515 | .attr = { .name = "profile5_settings", .mode = 0440 }, | ||
516 | .size = sizeof(struct koneplus_profile_settings), | ||
517 | .read = koneplus_sysfs_read_profilex_settings, | ||
518 | .private = &profile_numbers[4] | ||
519 | }, | ||
520 | { | ||
521 | .attr = { .name = "profile_buttons", .mode = 0220 }, | ||
522 | .size = sizeof(struct koneplus_profile_buttons), | ||
523 | .write = koneplus_sysfs_write_profile_buttons | ||
524 | }, | ||
525 | { | ||
526 | .attr = { .name = "profile1_buttons", .mode = 0440 }, | ||
527 | .size = sizeof(struct koneplus_profile_buttons), | ||
528 | .read = koneplus_sysfs_read_profilex_buttons, | ||
529 | .private = &profile_numbers[0] | ||
530 | }, | ||
531 | { | ||
532 | .attr = { .name = "profile2_buttons", .mode = 0440 }, | ||
533 | .size = sizeof(struct koneplus_profile_buttons), | ||
534 | .read = koneplus_sysfs_read_profilex_buttons, | ||
535 | .private = &profile_numbers[1] | ||
536 | }, | ||
537 | { | ||
538 | .attr = { .name = "profile3_buttons", .mode = 0440 }, | ||
539 | .size = sizeof(struct koneplus_profile_buttons), | ||
540 | .read = koneplus_sysfs_read_profilex_buttons, | ||
541 | .private = &profile_numbers[2] | ||
542 | }, | ||
543 | { | ||
544 | .attr = { .name = "profile4_buttons", .mode = 0440 }, | ||
545 | .size = sizeof(struct koneplus_profile_buttons), | ||
546 | .read = koneplus_sysfs_read_profilex_buttons, | ||
547 | .private = &profile_numbers[3] | ||
548 | }, | ||
549 | { | ||
550 | .attr = { .name = "profile5_buttons", .mode = 0440 }, | ||
551 | .size = sizeof(struct koneplus_profile_buttons), | ||
552 | .read = koneplus_sysfs_read_profilex_buttons, | ||
553 | .private = &profile_numbers[4] | ||
554 | }, | ||
555 | { | ||
556 | .attr = { .name = "macro", .mode = 0220 }, | ||
557 | .size = sizeof(struct koneplus_macro), | ||
558 | .write = koneplus_sysfs_write_macro | ||
559 | }, | ||
560 | __ATTR_NULL | ||
561 | }; | ||
562 | |||
563 | static int koneplus_init_koneplus_device_struct(struct usb_device *usb_dev, | ||
564 | struct koneplus_device *koneplus) | ||
565 | { | ||
566 | int retval, i; | ||
567 | static uint wait = 200; | ||
568 | |||
569 | mutex_init(&koneplus->koneplus_lock); | ||
570 | |||
571 | retval = koneplus_get_info(usb_dev, &koneplus->info); | ||
572 | if (retval) | ||
573 | return retval; | ||
574 | |||
575 | for (i = 0; i < 5; ++i) { | ||
576 | msleep(wait); | ||
577 | retval = koneplus_get_profile_settings(usb_dev, | ||
578 | &koneplus->profile_settings[i], i); | ||
579 | if (retval) | ||
580 | return retval; | ||
581 | |||
582 | msleep(wait); | ||
583 | retval = koneplus_get_profile_buttons(usb_dev, | ||
584 | &koneplus->profile_buttons[i], i); | ||
585 | if (retval) | ||
586 | return retval; | ||
587 | } | ||
588 | |||
589 | msleep(wait); | ||
590 | retval = koneplus_get_actual_profile(usb_dev); | ||
591 | if (retval < 0) | ||
592 | return retval; | ||
593 | koneplus_profile_activated(koneplus, retval); | ||
594 | |||
595 | return 0; | ||
596 | } | ||
597 | |||
598 | static int koneplus_init_specials(struct hid_device *hdev) | ||
599 | { | ||
600 | struct usb_interface *intf = to_usb_interface(hdev->dev.parent); | ||
601 | struct usb_device *usb_dev = interface_to_usbdev(intf); | ||
602 | struct koneplus_device *koneplus; | ||
603 | int retval; | ||
604 | |||
605 | if (intf->cur_altsetting->desc.bInterfaceProtocol | ||
606 | == USB_INTERFACE_PROTOCOL_MOUSE) { | ||
607 | |||
608 | koneplus = kzalloc(sizeof(*koneplus), GFP_KERNEL); | ||
609 | if (!koneplus) { | ||
610 | hid_err(hdev, "can't alloc device descriptor\n"); | ||
611 | return -ENOMEM; | ||
612 | } | ||
613 | hid_set_drvdata(hdev, koneplus); | ||
614 | |||
615 | retval = koneplus_init_koneplus_device_struct(usb_dev, koneplus); | ||
616 | if (retval) { | ||
617 | hid_err(hdev, "couldn't init struct koneplus_device\n"); | ||
618 | goto exit_free; | ||
619 | } | ||
620 | |||
621 | retval = roccat_connect(koneplus_class, hdev, | ||
622 | sizeof(struct koneplus_roccat_report)); | ||
623 | if (retval < 0) { | ||
624 | hid_err(hdev, "couldn't init char dev\n"); | ||
625 | } else { | ||
626 | koneplus->chrdev_minor = retval; | ||
627 | koneplus->roccat_claimed = 1; | ||
628 | } | ||
629 | } else { | ||
630 | hid_set_drvdata(hdev, NULL); | ||
631 | } | ||
632 | |||
633 | return 0; | ||
634 | exit_free: | ||
635 | kfree(koneplus); | ||
636 | return retval; | ||
637 | } | ||
638 | |||
639 | static void koneplus_remove_specials(struct hid_device *hdev) | ||
640 | { | ||
641 | struct usb_interface *intf = to_usb_interface(hdev->dev.parent); | ||
642 | struct koneplus_device *koneplus; | ||
643 | |||
644 | if (intf->cur_altsetting->desc.bInterfaceProtocol | ||
645 | == USB_INTERFACE_PROTOCOL_MOUSE) { | ||
646 | koneplus = hid_get_drvdata(hdev); | ||
647 | if (koneplus->roccat_claimed) | ||
648 | roccat_disconnect(koneplus->chrdev_minor); | ||
649 | kfree(koneplus); | ||
650 | } | ||
651 | } | ||
652 | |||
653 | static int koneplus_probe(struct hid_device *hdev, | ||
654 | const struct hid_device_id *id) | ||
655 | { | ||
656 | int retval; | ||
657 | |||
658 | retval = hid_parse(hdev); | ||
659 | if (retval) { | ||
660 | hid_err(hdev, "parse failed\n"); | ||
661 | goto exit; | ||
662 | } | ||
663 | |||
664 | retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT); | ||
665 | if (retval) { | ||
666 | hid_err(hdev, "hw start failed\n"); | ||
667 | goto exit; | ||
668 | } | ||
669 | |||
670 | retval = koneplus_init_specials(hdev); | ||
671 | if (retval) { | ||
672 | hid_err(hdev, "couldn't install mouse\n"); | ||
673 | goto exit_stop; | ||
674 | } | ||
675 | |||
676 | return 0; | ||
677 | |||
678 | exit_stop: | ||
679 | hid_hw_stop(hdev); | ||
680 | exit: | ||
681 | return retval; | ||
682 | } | ||
683 | |||
684 | static void koneplus_remove(struct hid_device *hdev) | ||
685 | { | ||
686 | koneplus_remove_specials(hdev); | ||
687 | hid_hw_stop(hdev); | ||
688 | } | ||
689 | |||
690 | static void koneplus_keep_values_up_to_date(struct koneplus_device *koneplus, | ||
691 | u8 const *data) | ||
692 | { | ||
693 | struct koneplus_mouse_report_button const *button_report; | ||
694 | |||
695 | switch (data[0]) { | ||
696 | case KONEPLUS_MOUSE_REPORT_NUMBER_BUTTON: | ||
697 | button_report = (struct koneplus_mouse_report_button const *)data; | ||
698 | switch (button_report->type) { | ||
699 | case KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE: | ||
700 | koneplus_profile_activated(koneplus, button_report->data1 - 1); | ||
701 | break; | ||
702 | } | ||
703 | break; | ||
704 | } | ||
705 | } | ||
706 | |||
707 | static void koneplus_report_to_chrdev(struct koneplus_device const *koneplus, | ||
708 | u8 const *data) | ||
709 | { | ||
710 | struct koneplus_roccat_report roccat_report; | ||
711 | struct koneplus_mouse_report_button const *button_report; | ||
712 | |||
713 | if (data[0] != KONEPLUS_MOUSE_REPORT_NUMBER_BUTTON) | ||
714 | return; | ||
715 | |||
716 | button_report = (struct koneplus_mouse_report_button const *)data; | ||
717 | |||
718 | if ((button_report->type == KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_QUICKLAUNCH || | ||
719 | button_report->type == KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_TIMER) && | ||
720 | button_report->data2 != KONEPLUS_MOUSE_REPORT_BUTTON_ACTION_PRESS) | ||
721 | return; | ||
722 | |||
723 | roccat_report.type = button_report->type; | ||
724 | roccat_report.data1 = button_report->data1; | ||
725 | roccat_report.data2 = button_report->data2; | ||
726 | roccat_report.profile = koneplus->actual_profile + 1; | ||
727 | roccat_report_event(koneplus->chrdev_minor, | ||
728 | (uint8_t const *)&roccat_report); | ||
729 | } | ||
730 | |||
731 | static int koneplus_raw_event(struct hid_device *hdev, | ||
732 | struct hid_report *report, u8 *data, int size) | ||
733 | { | ||
734 | struct usb_interface *intf = to_usb_interface(hdev->dev.parent); | ||
735 | struct koneplus_device *koneplus = hid_get_drvdata(hdev); | ||
736 | |||
737 | if (intf->cur_altsetting->desc.bInterfaceProtocol | ||
738 | != USB_INTERFACE_PROTOCOL_MOUSE) | ||
739 | return 0; | ||
740 | |||
741 | koneplus_keep_values_up_to_date(koneplus, data); | ||
742 | |||
743 | if (koneplus->roccat_claimed) | ||
744 | koneplus_report_to_chrdev(koneplus, data); | ||
745 | |||
746 | return 0; | ||
747 | } | ||
748 | |||
749 | static const struct hid_device_id koneplus_devices[] = { | ||
750 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) }, | ||
751 | { } | ||
752 | }; | ||
753 | |||
754 | MODULE_DEVICE_TABLE(hid, koneplus_devices); | ||
755 | |||
756 | static struct hid_driver koneplus_driver = { | ||
757 | .name = "koneplus", | ||
758 | .id_table = koneplus_devices, | ||
759 | .probe = koneplus_probe, | ||
760 | .remove = koneplus_remove, | ||
761 | .raw_event = koneplus_raw_event | ||
762 | }; | ||
763 | |||
764 | static int __init koneplus_init(void) | ||
765 | { | ||
766 | int retval; | ||
767 | |||
768 | /* class name has to be same as driver name */ | ||
769 | koneplus_class = class_create(THIS_MODULE, "koneplus"); | ||
770 | if (IS_ERR(koneplus_class)) | ||
771 | return PTR_ERR(koneplus_class); | ||
772 | koneplus_class->dev_attrs = koneplus_attributes; | ||
773 | koneplus_class->dev_bin_attrs = koneplus_bin_attributes; | ||
774 | |||
775 | retval = hid_register_driver(&koneplus_driver); | ||
776 | if (retval) | ||
777 | class_destroy(koneplus_class); | ||
778 | return retval; | ||
779 | } | ||
780 | |||
781 | static void __exit koneplus_exit(void) | ||
782 | { | ||
783 | hid_unregister_driver(&koneplus_driver); | ||
784 | class_destroy(koneplus_class); | ||
785 | } | ||
786 | |||
787 | module_init(koneplus_init); | ||
788 | module_exit(koneplus_exit); | ||
789 | |||
790 | MODULE_AUTHOR("Stefan Achatz"); | ||
791 | MODULE_DESCRIPTION("USB Roccat Kone[+] driver"); | ||
792 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/hid/hid-roccat-koneplus.h b/drivers/hid/hid-roccat-koneplus.h new file mode 100644 index 000000000000..c57a376ab8ae --- /dev/null +++ b/drivers/hid/hid-roccat-koneplus.h | |||
@@ -0,0 +1,223 @@ | |||
1 | #ifndef __HID_ROCCAT_KONEPLUS_H | ||
2 | #define __HID_ROCCAT_KONEPLUS_H | ||
3 | |||
4 | /* | ||
5 | * Copyright (c) 2010 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 | /* | ||
18 | * case 1: writes request 80 and reads value 1 | ||
19 | * | ||
20 | */ | ||
21 | struct koneplus_control { | ||
22 | uint8_t command; /* KONEPLUS_COMMAND_CONTROL */ | ||
23 | /* | ||
24 | * value is profile number in range 0-4 for requesting settings and buttons | ||
25 | * 1 if status ok for requesting status | ||
26 | */ | ||
27 | uint8_t value; | ||
28 | uint8_t request; | ||
29 | } __attribute__ ((__packed__)); | ||
30 | |||
31 | enum koneplus_control_requests { | ||
32 | KONEPLUS_CONTROL_REQUEST_STATUS = 0x00, | ||
33 | KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS = 0x80, | ||
34 | KONEPLUS_CONTROL_REQUEST_PROFILE_BUTTONS = 0x90, | ||
35 | }; | ||
36 | |||
37 | enum koneplus_control_values { | ||
38 | KONEPLUS_CONTROL_REQUEST_STATUS_OVERLOAD = 0, | ||
39 | KONEPLUS_CONTROL_REQUEST_STATUS_OK = 1, | ||
40 | KONEPLUS_CONTROL_REQUEST_STATUS_WAIT = 3, | ||
41 | }; | ||
42 | |||
43 | struct koneplus_actual_profile { | ||
44 | uint8_t command; /* KONEPLUS_COMMAND_ACTUAL_PROFILE */ | ||
45 | uint8_t size; /* always 3 */ | ||
46 | uint8_t actual_profile; /* Range 0-4! */ | ||
47 | } __attribute__ ((__packed__)); | ||
48 | |||
49 | struct koneplus_profile_settings { | ||
50 | uint8_t command; /* KONEPLUS_COMMAND_PROFILE_SETTINGS */ | ||
51 | uint8_t size; /* always 43 */ | ||
52 | uint8_t number; /* range 0-4 */ | ||
53 | uint8_t advanced_sensitivity; | ||
54 | uint8_t sensitivity_x; | ||
55 | uint8_t sensitivity_y; | ||
56 | uint8_t cpi_levels_enabled; | ||
57 | uint8_t cpi_levels_x[5]; | ||
58 | uint8_t cpi_startup_level; /* range 0-4 */ | ||
59 | uint8_t cpi_levels_y[5]; /* range 1-60 means 100-6000 cpi */ | ||
60 | uint8_t unknown1; | ||
61 | uint8_t polling_rate; | ||
62 | uint8_t lights_enabled; | ||
63 | uint8_t light_effect_mode; | ||
64 | uint8_t color_flow_effect; | ||
65 | uint8_t light_effect_type; | ||
66 | uint8_t light_effect_speed; | ||
67 | uint8_t lights[16]; | ||
68 | uint16_t checksum; | ||
69 | } __attribute__ ((__packed__)); | ||
70 | |||
71 | struct koneplus_profile_buttons { | ||
72 | uint8_t command; /* KONEPLUS_COMMAND_PROFILE_BUTTONS */ | ||
73 | uint8_t size; /* always 77 */ | ||
74 | uint8_t number; /* range 0-4 */ | ||
75 | uint8_t data[72]; | ||
76 | uint16_t checksum; | ||
77 | } __attribute__ ((__packed__)); | ||
78 | |||
79 | struct koneplus_macro { | ||
80 | uint8_t command; /* KONEPLUS_COMMAND_MACRO */ | ||
81 | uint16_t size; /* always 0x822 little endian */ | ||
82 | uint8_t profile; /* range 0-4 */ | ||
83 | uint8_t button; /* range 0-23 */ | ||
84 | uint8_t data[2075]; | ||
85 | uint16_t checksum; | ||
86 | } __attribute__ ((__packed__)); | ||
87 | |||
88 | struct koneplus_info { | ||
89 | uint8_t command; /* KONEPLUS_COMMAND_INFO */ | ||
90 | uint8_t size; /* always 6 */ | ||
91 | uint8_t firmware_version; | ||
92 | uint8_t unknown[3]; | ||
93 | } __attribute__ ((__packed__)); | ||
94 | |||
95 | struct koneplus_e { | ||
96 | uint8_t command; /* KONEPLUS_COMMAND_E */ | ||
97 | uint8_t size; /* always 3 */ | ||
98 | uint8_t unknown; /* TODO 1; 0 before firmware update */ | ||
99 | } __attribute__ ((__packed__)); | ||
100 | |||
101 | struct koneplus_sensor { | ||
102 | uint8_t command; /* KONEPLUS_COMMAND_SENSOR */ | ||
103 | uint8_t size; /* always 6 */ | ||
104 | uint8_t data[4]; | ||
105 | } __attribute__ ((__packed__)); | ||
106 | |||
107 | struct koneplus_firmware_write { | ||
108 | uint8_t command; /* KONEPLUS_COMMAND_FIRMWARE_WRITE */ | ||
109 | uint8_t unknown[1025]; | ||
110 | } __attribute__ ((__packed__)); | ||
111 | |||
112 | struct koneplus_firmware_write_control { | ||
113 | uint8_t command; /* KONEPLUS_COMMAND_FIRMWARE_WRITE_CONTROL */ | ||
114 | /* | ||
115 | * value is 1 on success | ||
116 | * 3 means "not finished yet" | ||
117 | */ | ||
118 | uint8_t value; | ||
119 | uint8_t unknown; /* always 0x75 */ | ||
120 | } __attribute__ ((__packed__)); | ||
121 | |||
122 | struct koneplus_tcu { | ||
123 | uint16_t usb_command; /* KONEPLUS_USB_COMMAND_TCU */ | ||
124 | uint8_t data[2]; | ||
125 | } __attribute__ ((__packed__)); | ||
126 | |||
127 | struct koneplus_tcu_image { | ||
128 | uint16_t usb_command; /* KONEPLUS_USB_COMMAND_TCU */ | ||
129 | uint8_t data[1024]; | ||
130 | uint16_t checksum; | ||
131 | } __attribute__ ((__packed__)); | ||
132 | |||
133 | enum koneplus_commands { | ||
134 | KONEPLUS_COMMAND_CONTROL = 0x4, | ||
135 | KONEPLUS_COMMAND_ACTUAL_PROFILE = 0x5, | ||
136 | KONEPLUS_COMMAND_PROFILE_SETTINGS = 0x6, | ||
137 | KONEPLUS_COMMAND_PROFILE_BUTTONS = 0x7, | ||
138 | KONEPLUS_COMMAND_MACRO = 0x8, | ||
139 | KONEPLUS_COMMAND_INFO = 0x9, | ||
140 | KONEPLUS_COMMAND_E = 0xe, | ||
141 | KONEPLUS_COMMAND_SENSOR = 0xf, | ||
142 | KONEPLUS_COMMAND_FIRMWARE_WRITE = 0x1b, | ||
143 | KONEPLUS_COMMAND_FIRMWARE_WRITE_CONTROL = 0x1c, | ||
144 | }; | ||
145 | |||
146 | enum koneplus_usb_commands { | ||
147 | KONEPLUS_USB_COMMAND_CONTROL = 0x304, | ||
148 | KONEPLUS_USB_COMMAND_ACTUAL_PROFILE = 0x305, | ||
149 | KONEPLUS_USB_COMMAND_PROFILE_SETTINGS = 0x306, | ||
150 | KONEPLUS_USB_COMMAND_PROFILE_BUTTONS = 0x307, | ||
151 | KONEPLUS_USB_COMMAND_MACRO = 0x308, | ||
152 | KONEPLUS_USB_COMMAND_INFO = 0x309, | ||
153 | KONEPLUS_USB_COMMAND_TCU = 0x30c, | ||
154 | KONEPLUS_USB_COMMAND_E = 0x30e, | ||
155 | KONEPLUS_USB_COMMAND_SENSOR = 0x30f, | ||
156 | KONEPLUS_USB_COMMAND_FIRMWARE_WRITE = 0x31b, | ||
157 | KONEPLUS_USB_COMMAND_FIRMWARE_WRITE_CONTROL = 0x31c, | ||
158 | }; | ||
159 | |||
160 | enum koneplus_mouse_report_numbers { | ||
161 | KONEPLUS_MOUSE_REPORT_NUMBER_HID = 1, | ||
162 | KONEPLUS_MOUSE_REPORT_NUMBER_AUDIO = 2, | ||
163 | KONEPLUS_MOUSE_REPORT_NUMBER_BUTTON = 3, | ||
164 | }; | ||
165 | |||
166 | struct koneplus_mouse_report_button { | ||
167 | uint8_t report_number; /* always KONEPLUS_MOUSE_REPORT_NUMBER_BUTTON */ | ||
168 | uint8_t zero1; | ||
169 | uint8_t type; | ||
170 | uint8_t data1; | ||
171 | uint8_t data2; | ||
172 | uint8_t zero2; | ||
173 | uint8_t unknown[2]; | ||
174 | } __attribute__ ((__packed__)); | ||
175 | |||
176 | enum koneplus_mouse_report_button_types { | ||
177 | /* data1 = new profile range 1-5 */ | ||
178 | KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE = 0x20, | ||
179 | |||
180 | /* data1 = button number range 1-24; data2 = action */ | ||
181 | KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_QUICKLAUNCH = 0x60, | ||
182 | |||
183 | /* data1 = button number range 1-24; data2 = action */ | ||
184 | KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_TIMER = 0x80, | ||
185 | |||
186 | /* data1 = setting number range 1-5 */ | ||
187 | KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_CPI = 0xb0, | ||
188 | |||
189 | /* data1 and data2 = range 0x1-0xb */ | ||
190 | KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_SENSITIVITY = 0xc0, | ||
191 | |||
192 | /* data1 = 22 = next track... | ||
193 | * data2 = action | ||
194 | */ | ||
195 | KONEPLUS_MOUSE_REPORT_BUTTON_TYPE_MULTIMEDIA = 0xf0, | ||
196 | }; | ||
197 | |||
198 | enum koneplus_mouse_report_button_action { | ||
199 | KONEPLUS_MOUSE_REPORT_BUTTON_ACTION_PRESS = 0, | ||
200 | KONEPLUS_MOUSE_REPORT_BUTTON_ACTION_RELEASE = 1, | ||
201 | }; | ||
202 | |||
203 | struct koneplus_roccat_report { | ||
204 | uint8_t type; | ||
205 | uint8_t data1; | ||
206 | uint8_t data2; | ||
207 | uint8_t profile; | ||
208 | } __attribute__ ((__packed__)); | ||
209 | |||
210 | struct koneplus_device { | ||
211 | int actual_profile; | ||
212 | |||
213 | int roccat_claimed; | ||
214 | int chrdev_minor; | ||
215 | |||
216 | struct mutex koneplus_lock; | ||
217 | |||
218 | struct koneplus_info info; | ||
219 | struct koneplus_profile_settings profile_settings[5]; | ||
220 | struct koneplus_profile_buttons profile_buttons[5]; | ||
221 | }; | ||
222 | |||
223 | #endif | ||
diff --git a/drivers/hid/hid-roccat-kovaplus.c b/drivers/hid/hid-roccat-kovaplus.c new file mode 100644 index 000000000000..984be2f8967e --- /dev/null +++ b/drivers/hid/hid-roccat-kovaplus.c | |||
@@ -0,0 +1,715 @@ | |||
1 | /* | ||
2 | * Roccat Kova[+] driver for Linux | ||
3 | * | ||
4 | * Copyright (c) 2011 Stefan Achatz <erazor_de@users.sourceforge.net> | ||
5 | */ | ||
6 | |||
7 | /* | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the Free | ||
10 | * Software Foundation; either version 2 of the License, or (at your option) | ||
11 | * any later version. | ||
12 | */ | ||
13 | |||
14 | /* | ||
15 | * Roccat Kova[+] is a bigger version of the Pyra with two more side buttons. | ||
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-kovaplus.h" | ||
27 | |||
28 | static uint profile_numbers[5] = {0, 1, 2, 3, 4}; | ||
29 | |||
30 | static struct class *kovaplus_class; | ||
31 | |||
32 | static uint kovaplus_convert_event_cpi(uint value) | ||
33 | { | ||
34 | return (value == 7 ? 4 : (value == 4 ? 3 : value)); | ||
35 | } | ||
36 | |||
37 | static void kovaplus_profile_activated(struct kovaplus_device *kovaplus, | ||
38 | uint new_profile_index) | ||
39 | { | ||
40 | kovaplus->actual_profile = new_profile_index; | ||
41 | kovaplus->actual_cpi = kovaplus->profile_settings[new_profile_index].cpi_startup_level; | ||
42 | kovaplus->actual_x_sensitivity = kovaplus->profile_settings[new_profile_index].sensitivity_x; | ||
43 | kovaplus->actual_y_sensitivity = kovaplus->profile_settings[new_profile_index].sensitivity_y; | ||
44 | } | ||
45 | |||
46 | static int kovaplus_send_control(struct usb_device *usb_dev, uint value, | ||
47 | enum kovaplus_control_requests request) | ||
48 | { | ||
49 | int retval; | ||
50 | struct kovaplus_control control; | ||
51 | |||
52 | if ((request == KOVAPLUS_CONTROL_REQUEST_PROFILE_SETTINGS || | ||
53 | request == KOVAPLUS_CONTROL_REQUEST_PROFILE_BUTTONS) && | ||
54 | value > 4) | ||
55 | return -EINVAL; | ||
56 | |||
57 | control.command = KOVAPLUS_COMMAND_CONTROL; | ||
58 | control.value = value; | ||
59 | control.request = request; | ||
60 | |||
61 | retval = roccat_common_send(usb_dev, KOVAPLUS_USB_COMMAND_CONTROL, | ||
62 | &control, sizeof(struct kovaplus_control)); | ||
63 | |||
64 | return retval; | ||
65 | } | ||
66 | |||
67 | static int kovaplus_receive_control_status(struct usb_device *usb_dev) | ||
68 | { | ||
69 | int retval; | ||
70 | struct kovaplus_control control; | ||
71 | |||
72 | do { | ||
73 | retval = roccat_common_receive(usb_dev, KOVAPLUS_USB_COMMAND_CONTROL, | ||
74 | &control, sizeof(struct kovaplus_control)); | ||
75 | |||
76 | /* check if we get a completely wrong answer */ | ||
77 | if (retval) | ||
78 | return retval; | ||
79 | |||
80 | if (control.value == KOVAPLUS_CONTROL_REQUEST_STATUS_OK) | ||
81 | return 0; | ||
82 | |||
83 | /* indicates that hardware needs some more time to complete action */ | ||
84 | if (control.value == KOVAPLUS_CONTROL_REQUEST_STATUS_WAIT) { | ||
85 | msleep(500); /* windows driver uses 1000 */ | ||
86 | continue; | ||
87 | } | ||
88 | |||
89 | /* seems to be critical - replug necessary */ | ||
90 | if (control.value == KOVAPLUS_CONTROL_REQUEST_STATUS_OVERLOAD) | ||
91 | return -EINVAL; | ||
92 | |||
93 | hid_err(usb_dev, "kovaplus_receive_control_status: " | ||
94 | "unknown response value 0x%x\n", control.value); | ||
95 | return -EINVAL; | ||
96 | } while (1); | ||
97 | } | ||
98 | |||
99 | static int kovaplus_send(struct usb_device *usb_dev, uint command, | ||
100 | void const *buf, uint size) | ||
101 | { | ||
102 | int retval; | ||
103 | |||
104 | retval = roccat_common_send(usb_dev, command, buf, size); | ||
105 | if (retval) | ||
106 | return retval; | ||
107 | |||
108 | msleep(100); | ||
109 | |||
110 | return kovaplus_receive_control_status(usb_dev); | ||
111 | } | ||
112 | |||
113 | static int kovaplus_select_profile(struct usb_device *usb_dev, uint number, | ||
114 | enum kovaplus_control_requests request) | ||
115 | { | ||
116 | return kovaplus_send_control(usb_dev, number, request); | ||
117 | } | ||
118 | |||
119 | static int kovaplus_get_info(struct usb_device *usb_dev, | ||
120 | struct kovaplus_info *buf) | ||
121 | { | ||
122 | return roccat_common_receive(usb_dev, KOVAPLUS_USB_COMMAND_INFO, | ||
123 | buf, sizeof(struct kovaplus_info)); | ||
124 | } | ||
125 | |||
126 | static int kovaplus_get_profile_settings(struct usb_device *usb_dev, | ||
127 | struct kovaplus_profile_settings *buf, uint number) | ||
128 | { | ||
129 | int retval; | ||
130 | |||
131 | retval = kovaplus_select_profile(usb_dev, number, | ||
132 | KOVAPLUS_CONTROL_REQUEST_PROFILE_SETTINGS); | ||
133 | if (retval) | ||
134 | return retval; | ||
135 | |||
136 | return roccat_common_receive(usb_dev, KOVAPLUS_USB_COMMAND_PROFILE_SETTINGS, | ||
137 | buf, sizeof(struct kovaplus_profile_settings)); | ||
138 | } | ||
139 | |||
140 | static int kovaplus_set_profile_settings(struct usb_device *usb_dev, | ||
141 | struct kovaplus_profile_settings const *settings) | ||
142 | { | ||
143 | return kovaplus_send(usb_dev, KOVAPLUS_USB_COMMAND_PROFILE_SETTINGS, | ||
144 | settings, sizeof(struct kovaplus_profile_settings)); | ||
145 | } | ||
146 | |||
147 | static int kovaplus_get_profile_buttons(struct usb_device *usb_dev, | ||
148 | struct kovaplus_profile_buttons *buf, int number) | ||
149 | { | ||
150 | int retval; | ||
151 | |||
152 | retval = kovaplus_select_profile(usb_dev, number, | ||
153 | KOVAPLUS_CONTROL_REQUEST_PROFILE_BUTTONS); | ||
154 | if (retval) | ||
155 | return retval; | ||
156 | |||
157 | return roccat_common_receive(usb_dev, KOVAPLUS_USB_COMMAND_PROFILE_BUTTONS, | ||
158 | buf, sizeof(struct kovaplus_profile_buttons)); | ||
159 | } | ||
160 | |||
161 | static int kovaplus_set_profile_buttons(struct usb_device *usb_dev, | ||
162 | struct kovaplus_profile_buttons const *buttons) | ||
163 | { | ||
164 | return kovaplus_send(usb_dev, KOVAPLUS_USB_COMMAND_PROFILE_BUTTONS, | ||
165 | buttons, sizeof(struct kovaplus_profile_buttons)); | ||
166 | } | ||
167 | |||
168 | /* retval is 0-4 on success, < 0 on error */ | ||
169 | static int kovaplus_get_actual_profile(struct usb_device *usb_dev) | ||
170 | { | ||
171 | struct kovaplus_actual_profile buf; | ||
172 | int retval; | ||
173 | |||
174 | retval = roccat_common_receive(usb_dev, KOVAPLUS_USB_COMMAND_ACTUAL_PROFILE, | ||
175 | &buf, sizeof(struct kovaplus_actual_profile)); | ||
176 | |||
177 | return retval ? retval : buf.actual_profile; | ||
178 | } | ||
179 | |||
180 | static int kovaplus_set_actual_profile(struct usb_device *usb_dev, | ||
181 | int new_profile) | ||
182 | { | ||
183 | struct kovaplus_actual_profile buf; | ||
184 | |||
185 | buf.command = KOVAPLUS_COMMAND_ACTUAL_PROFILE; | ||
186 | buf.size = sizeof(struct kovaplus_actual_profile); | ||
187 | buf.actual_profile = new_profile; | ||
188 | |||
189 | return kovaplus_send(usb_dev, KOVAPLUS_USB_COMMAND_ACTUAL_PROFILE, | ||
190 | &buf, sizeof(struct kovaplus_actual_profile)); | ||
191 | } | ||
192 | |||
193 | static ssize_t kovaplus_sysfs_read_profilex_settings(struct file *fp, | ||
194 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
195 | loff_t off, size_t count) | ||
196 | { | ||
197 | struct device *dev = | ||
198 | container_of(kobj, struct device, kobj)->parent->parent; | ||
199 | struct kovaplus_device *kovaplus = hid_get_drvdata(dev_get_drvdata(dev)); | ||
200 | |||
201 | if (off >= sizeof(struct kovaplus_profile_settings)) | ||
202 | return 0; | ||
203 | |||
204 | if (off + count > sizeof(struct kovaplus_profile_settings)) | ||
205 | count = sizeof(struct kovaplus_profile_settings) - off; | ||
206 | |||
207 | mutex_lock(&kovaplus->kovaplus_lock); | ||
208 | memcpy(buf, ((char const *)&kovaplus->profile_settings[*(uint *)(attr->private)]) + off, | ||
209 | count); | ||
210 | mutex_unlock(&kovaplus->kovaplus_lock); | ||
211 | |||
212 | return count; | ||
213 | } | ||
214 | |||
215 | static ssize_t kovaplus_sysfs_write_profile_settings(struct file *fp, | ||
216 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
217 | loff_t off, size_t count) | ||
218 | { | ||
219 | struct device *dev = | ||
220 | container_of(kobj, struct device, kobj)->parent->parent; | ||
221 | struct kovaplus_device *kovaplus = hid_get_drvdata(dev_get_drvdata(dev)); | ||
222 | struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); | ||
223 | int retval = 0; | ||
224 | int difference; | ||
225 | int profile_index; | ||
226 | struct kovaplus_profile_settings *profile_settings; | ||
227 | |||
228 | if (off != 0 || count != sizeof(struct kovaplus_profile_settings)) | ||
229 | return -EINVAL; | ||
230 | |||
231 | profile_index = ((struct kovaplus_profile_settings const *)buf)->profile_index; | ||
232 | profile_settings = &kovaplus->profile_settings[profile_index]; | ||
233 | |||
234 | mutex_lock(&kovaplus->kovaplus_lock); | ||
235 | difference = memcmp(buf, profile_settings, | ||
236 | sizeof(struct kovaplus_profile_settings)); | ||
237 | if (difference) { | ||
238 | retval = kovaplus_set_profile_settings(usb_dev, | ||
239 | (struct kovaplus_profile_settings const *)buf); | ||
240 | if (!retval) | ||
241 | memcpy(profile_settings, buf, | ||
242 | sizeof(struct kovaplus_profile_settings)); | ||
243 | } | ||
244 | mutex_unlock(&kovaplus->kovaplus_lock); | ||
245 | |||
246 | if (retval) | ||
247 | return retval; | ||
248 | |||
249 | return sizeof(struct kovaplus_profile_settings); | ||
250 | } | ||
251 | |||
252 | static ssize_t kovaplus_sysfs_read_profilex_buttons(struct file *fp, | ||
253 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
254 | loff_t off, size_t count) | ||
255 | { | ||
256 | struct device *dev = | ||
257 | container_of(kobj, struct device, kobj)->parent->parent; | ||
258 | struct kovaplus_device *kovaplus = hid_get_drvdata(dev_get_drvdata(dev)); | ||
259 | |||
260 | if (off >= sizeof(struct kovaplus_profile_buttons)) | ||
261 | return 0; | ||
262 | |||
263 | if (off + count > sizeof(struct kovaplus_profile_buttons)) | ||
264 | count = sizeof(struct kovaplus_profile_buttons) - off; | ||
265 | |||
266 | mutex_lock(&kovaplus->kovaplus_lock); | ||
267 | memcpy(buf, ((char const *)&kovaplus->profile_buttons[*(uint *)(attr->private)]) + off, | ||
268 | count); | ||
269 | mutex_unlock(&kovaplus->kovaplus_lock); | ||
270 | |||
271 | return count; | ||
272 | } | ||
273 | |||
274 | static ssize_t kovaplus_sysfs_write_profile_buttons(struct file *fp, | ||
275 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
276 | loff_t off, size_t count) | ||
277 | { | ||
278 | struct device *dev = | ||
279 | container_of(kobj, struct device, kobj)->parent->parent; | ||
280 | struct kovaplus_device *kovaplus = hid_get_drvdata(dev_get_drvdata(dev)); | ||
281 | struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); | ||
282 | int retval = 0; | ||
283 | int difference; | ||
284 | uint profile_index; | ||
285 | struct kovaplus_profile_buttons *profile_buttons; | ||
286 | |||
287 | if (off != 0 || count != sizeof(struct kovaplus_profile_buttons)) | ||
288 | return -EINVAL; | ||
289 | |||
290 | profile_index = ((struct kovaplus_profile_buttons const *)buf)->profile_index; | ||
291 | profile_buttons = &kovaplus->profile_buttons[profile_index]; | ||
292 | |||
293 | mutex_lock(&kovaplus->kovaplus_lock); | ||
294 | difference = memcmp(buf, profile_buttons, | ||
295 | sizeof(struct kovaplus_profile_buttons)); | ||
296 | if (difference) { | ||
297 | retval = kovaplus_set_profile_buttons(usb_dev, | ||
298 | (struct kovaplus_profile_buttons const *)buf); | ||
299 | if (!retval) | ||
300 | memcpy(profile_buttons, buf, | ||
301 | sizeof(struct kovaplus_profile_buttons)); | ||
302 | } | ||
303 | mutex_unlock(&kovaplus->kovaplus_lock); | ||
304 | |||
305 | if (retval) | ||
306 | return retval; | ||
307 | |||
308 | return sizeof(struct kovaplus_profile_buttons); | ||
309 | } | ||
310 | |||
311 | static ssize_t kovaplus_sysfs_show_actual_profile(struct device *dev, | ||
312 | struct device_attribute *attr, char *buf) | ||
313 | { | ||
314 | struct kovaplus_device *kovaplus = | ||
315 | hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); | ||
316 | return snprintf(buf, PAGE_SIZE, "%d\n", kovaplus->actual_profile); | ||
317 | } | ||
318 | |||
319 | static ssize_t kovaplus_sysfs_set_actual_profile(struct device *dev, | ||
320 | struct device_attribute *attr, char const *buf, size_t size) | ||
321 | { | ||
322 | struct kovaplus_device *kovaplus; | ||
323 | struct usb_device *usb_dev; | ||
324 | unsigned long profile; | ||
325 | int retval; | ||
326 | |||
327 | dev = dev->parent->parent; | ||
328 | kovaplus = hid_get_drvdata(dev_get_drvdata(dev)); | ||
329 | usb_dev = interface_to_usbdev(to_usb_interface(dev)); | ||
330 | |||
331 | retval = strict_strtoul(buf, 10, &profile); | ||
332 | if (retval) | ||
333 | return retval; | ||
334 | |||
335 | if (profile >= 5) | ||
336 | return -EINVAL; | ||
337 | |||
338 | mutex_lock(&kovaplus->kovaplus_lock); | ||
339 | retval = kovaplus_set_actual_profile(usb_dev, profile); | ||
340 | kovaplus->actual_profile = profile; | ||
341 | mutex_unlock(&kovaplus->kovaplus_lock); | ||
342 | if (retval) | ||
343 | return retval; | ||
344 | |||
345 | return size; | ||
346 | } | ||
347 | |||
348 | static ssize_t kovaplus_sysfs_show_actual_cpi(struct device *dev, | ||
349 | struct device_attribute *attr, char *buf) | ||
350 | { | ||
351 | struct kovaplus_device *kovaplus = | ||
352 | hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); | ||
353 | return snprintf(buf, PAGE_SIZE, "%d\n", kovaplus->actual_cpi); | ||
354 | } | ||
355 | |||
356 | static ssize_t kovaplus_sysfs_show_actual_sensitivity_x(struct device *dev, | ||
357 | struct device_attribute *attr, char *buf) | ||
358 | { | ||
359 | struct kovaplus_device *kovaplus = | ||
360 | hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); | ||
361 | return snprintf(buf, PAGE_SIZE, "%d\n", kovaplus->actual_x_sensitivity); | ||
362 | } | ||
363 | |||
364 | static ssize_t kovaplus_sysfs_show_actual_sensitivity_y(struct device *dev, | ||
365 | struct device_attribute *attr, char *buf) | ||
366 | { | ||
367 | struct kovaplus_device *kovaplus = | ||
368 | hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); | ||
369 | return snprintf(buf, PAGE_SIZE, "%d\n", kovaplus->actual_y_sensitivity); | ||
370 | } | ||
371 | |||
372 | static ssize_t kovaplus_sysfs_show_firmware_version(struct device *dev, | ||
373 | struct device_attribute *attr, char *buf) | ||
374 | { | ||
375 | struct kovaplus_device *kovaplus = | ||
376 | hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); | ||
377 | return snprintf(buf, PAGE_SIZE, "%d\n", kovaplus->info.firmware_version); | ||
378 | } | ||
379 | |||
380 | static struct device_attribute kovaplus_attributes[] = { | ||
381 | __ATTR(actual_cpi, 0440, | ||
382 | kovaplus_sysfs_show_actual_cpi, NULL), | ||
383 | __ATTR(firmware_version, 0440, | ||
384 | kovaplus_sysfs_show_firmware_version, NULL), | ||
385 | __ATTR(actual_profile, 0660, | ||
386 | kovaplus_sysfs_show_actual_profile, | ||
387 | kovaplus_sysfs_set_actual_profile), | ||
388 | __ATTR(actual_sensitivity_x, 0440, | ||
389 | kovaplus_sysfs_show_actual_sensitivity_x, NULL), | ||
390 | __ATTR(actual_sensitivity_y, 0440, | ||
391 | kovaplus_sysfs_show_actual_sensitivity_y, NULL), | ||
392 | __ATTR_NULL | ||
393 | }; | ||
394 | |||
395 | static struct bin_attribute kovaplus_bin_attributes[] = { | ||
396 | { | ||
397 | .attr = { .name = "profile_settings", .mode = 0220 }, | ||
398 | .size = sizeof(struct kovaplus_profile_settings), | ||
399 | .write = kovaplus_sysfs_write_profile_settings | ||
400 | }, | ||
401 | { | ||
402 | .attr = { .name = "profile1_settings", .mode = 0440 }, | ||
403 | .size = sizeof(struct kovaplus_profile_settings), | ||
404 | .read = kovaplus_sysfs_read_profilex_settings, | ||
405 | .private = &profile_numbers[0] | ||
406 | }, | ||
407 | { | ||
408 | .attr = { .name = "profile2_settings", .mode = 0440 }, | ||
409 | .size = sizeof(struct kovaplus_profile_settings), | ||
410 | .read = kovaplus_sysfs_read_profilex_settings, | ||
411 | .private = &profile_numbers[1] | ||
412 | }, | ||
413 | { | ||
414 | .attr = { .name = "profile3_settings", .mode = 0440 }, | ||
415 | .size = sizeof(struct kovaplus_profile_settings), | ||
416 | .read = kovaplus_sysfs_read_profilex_settings, | ||
417 | .private = &profile_numbers[2] | ||
418 | }, | ||
419 | { | ||
420 | .attr = { .name = "profile4_settings", .mode = 0440 }, | ||
421 | .size = sizeof(struct kovaplus_profile_settings), | ||
422 | .read = kovaplus_sysfs_read_profilex_settings, | ||
423 | .private = &profile_numbers[3] | ||
424 | }, | ||
425 | { | ||
426 | .attr = { .name = "profile5_settings", .mode = 0440 }, | ||
427 | .size = sizeof(struct kovaplus_profile_settings), | ||
428 | .read = kovaplus_sysfs_read_profilex_settings, | ||
429 | .private = &profile_numbers[4] | ||
430 | }, | ||
431 | { | ||
432 | .attr = { .name = "profile_buttons", .mode = 0220 }, | ||
433 | .size = sizeof(struct kovaplus_profile_buttons), | ||
434 | .write = kovaplus_sysfs_write_profile_buttons | ||
435 | }, | ||
436 | { | ||
437 | .attr = { .name = "profile1_buttons", .mode = 0440 }, | ||
438 | .size = sizeof(struct kovaplus_profile_buttons), | ||
439 | .read = kovaplus_sysfs_read_profilex_buttons, | ||
440 | .private = &profile_numbers[0] | ||
441 | }, | ||
442 | { | ||
443 | .attr = { .name = "profile2_buttons", .mode = 0440 }, | ||
444 | .size = sizeof(struct kovaplus_profile_buttons), | ||
445 | .read = kovaplus_sysfs_read_profilex_buttons, | ||
446 | .private = &profile_numbers[1] | ||
447 | }, | ||
448 | { | ||
449 | .attr = { .name = "profile3_buttons", .mode = 0440 }, | ||
450 | .size = sizeof(struct kovaplus_profile_buttons), | ||
451 | .read = kovaplus_sysfs_read_profilex_buttons, | ||
452 | .private = &profile_numbers[2] | ||
453 | }, | ||
454 | { | ||
455 | .attr = { .name = "profile4_buttons", .mode = 0440 }, | ||
456 | .size = sizeof(struct kovaplus_profile_buttons), | ||
457 | .read = kovaplus_sysfs_read_profilex_buttons, | ||
458 | .private = &profile_numbers[3] | ||
459 | }, | ||
460 | { | ||
461 | .attr = { .name = "profile5_buttons", .mode = 0440 }, | ||
462 | .size = sizeof(struct kovaplus_profile_buttons), | ||
463 | .read = kovaplus_sysfs_read_profilex_buttons, | ||
464 | .private = &profile_numbers[4] | ||
465 | }, | ||
466 | __ATTR_NULL | ||
467 | }; | ||
468 | |||
469 | static int kovaplus_init_kovaplus_device_struct(struct usb_device *usb_dev, | ||
470 | struct kovaplus_device *kovaplus) | ||
471 | { | ||
472 | int retval, i; | ||
473 | static uint wait = 70; /* device will freeze with just 60 */ | ||
474 | |||
475 | mutex_init(&kovaplus->kovaplus_lock); | ||
476 | |||
477 | retval = kovaplus_get_info(usb_dev, &kovaplus->info); | ||
478 | if (retval) | ||
479 | return retval; | ||
480 | |||
481 | for (i = 0; i < 5; ++i) { | ||
482 | msleep(wait); | ||
483 | retval = kovaplus_get_profile_settings(usb_dev, | ||
484 | &kovaplus->profile_settings[i], i); | ||
485 | if (retval) | ||
486 | return retval; | ||
487 | |||
488 | msleep(wait); | ||
489 | retval = kovaplus_get_profile_buttons(usb_dev, | ||
490 | &kovaplus->profile_buttons[i], i); | ||
491 | if (retval) | ||
492 | return retval; | ||
493 | } | ||
494 | |||
495 | msleep(wait); | ||
496 | retval = kovaplus_get_actual_profile(usb_dev); | ||
497 | if (retval < 0) | ||
498 | return retval; | ||
499 | kovaplus_profile_activated(kovaplus, retval); | ||
500 | |||
501 | return 0; | ||
502 | } | ||
503 | |||
504 | static int kovaplus_init_specials(struct hid_device *hdev) | ||
505 | { | ||
506 | struct usb_interface *intf = to_usb_interface(hdev->dev.parent); | ||
507 | struct usb_device *usb_dev = interface_to_usbdev(intf); | ||
508 | struct kovaplus_device *kovaplus; | ||
509 | int retval; | ||
510 | |||
511 | if (intf->cur_altsetting->desc.bInterfaceProtocol | ||
512 | == USB_INTERFACE_PROTOCOL_MOUSE) { | ||
513 | |||
514 | kovaplus = kzalloc(sizeof(*kovaplus), GFP_KERNEL); | ||
515 | if (!kovaplus) { | ||
516 | hid_err(hdev, "can't alloc device descriptor\n"); | ||
517 | return -ENOMEM; | ||
518 | } | ||
519 | hid_set_drvdata(hdev, kovaplus); | ||
520 | |||
521 | retval = kovaplus_init_kovaplus_device_struct(usb_dev, kovaplus); | ||
522 | if (retval) { | ||
523 | hid_err(hdev, "couldn't init struct kovaplus_device\n"); | ||
524 | goto exit_free; | ||
525 | } | ||
526 | |||
527 | retval = roccat_connect(kovaplus_class, hdev, | ||
528 | sizeof(struct kovaplus_roccat_report)); | ||
529 | if (retval < 0) { | ||
530 | hid_err(hdev, "couldn't init char dev\n"); | ||
531 | } else { | ||
532 | kovaplus->chrdev_minor = retval; | ||
533 | kovaplus->roccat_claimed = 1; | ||
534 | } | ||
535 | |||
536 | } else { | ||
537 | hid_set_drvdata(hdev, NULL); | ||
538 | } | ||
539 | |||
540 | return 0; | ||
541 | exit_free: | ||
542 | kfree(kovaplus); | ||
543 | return retval; | ||
544 | } | ||
545 | |||
546 | static void kovaplus_remove_specials(struct hid_device *hdev) | ||
547 | { | ||
548 | struct usb_interface *intf = to_usb_interface(hdev->dev.parent); | ||
549 | struct kovaplus_device *kovaplus; | ||
550 | |||
551 | if (intf->cur_altsetting->desc.bInterfaceProtocol | ||
552 | == USB_INTERFACE_PROTOCOL_MOUSE) { | ||
553 | kovaplus = hid_get_drvdata(hdev); | ||
554 | if (kovaplus->roccat_claimed) | ||
555 | roccat_disconnect(kovaplus->chrdev_minor); | ||
556 | kfree(kovaplus); | ||
557 | } | ||
558 | } | ||
559 | |||
560 | static int kovaplus_probe(struct hid_device *hdev, | ||
561 | const struct hid_device_id *id) | ||
562 | { | ||
563 | int retval; | ||
564 | |||
565 | retval = hid_parse(hdev); | ||
566 | if (retval) { | ||
567 | hid_err(hdev, "parse failed\n"); | ||
568 | goto exit; | ||
569 | } | ||
570 | |||
571 | retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT); | ||
572 | if (retval) { | ||
573 | hid_err(hdev, "hw start failed\n"); | ||
574 | goto exit; | ||
575 | } | ||
576 | |||
577 | retval = kovaplus_init_specials(hdev); | ||
578 | if (retval) { | ||
579 | hid_err(hdev, "couldn't install mouse\n"); | ||
580 | goto exit_stop; | ||
581 | } | ||
582 | |||
583 | return 0; | ||
584 | |||
585 | exit_stop: | ||
586 | hid_hw_stop(hdev); | ||
587 | exit: | ||
588 | return retval; | ||
589 | } | ||
590 | |||
591 | static void kovaplus_remove(struct hid_device *hdev) | ||
592 | { | ||
593 | kovaplus_remove_specials(hdev); | ||
594 | hid_hw_stop(hdev); | ||
595 | } | ||
596 | |||
597 | static void kovaplus_keep_values_up_to_date(struct kovaplus_device *kovaplus, | ||
598 | u8 const *data) | ||
599 | { | ||
600 | struct kovaplus_mouse_report_button const *button_report; | ||
601 | |||
602 | if (data[0] != KOVAPLUS_MOUSE_REPORT_NUMBER_BUTTON) | ||
603 | return; | ||
604 | |||
605 | button_report = (struct kovaplus_mouse_report_button const *)data; | ||
606 | |||
607 | switch (button_report->type) { | ||
608 | case KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE_1: | ||
609 | kovaplus_profile_activated(kovaplus, button_report->data1 - 1); | ||
610 | break; | ||
611 | case KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_CPI: | ||
612 | kovaplus->actual_cpi = kovaplus_convert_event_cpi(button_report->data1); | ||
613 | case KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_SENSITIVITY: | ||
614 | kovaplus->actual_x_sensitivity = button_report->data1; | ||
615 | kovaplus->actual_y_sensitivity = button_report->data2; | ||
616 | } | ||
617 | } | ||
618 | |||
619 | static void kovaplus_report_to_chrdev(struct kovaplus_device const *kovaplus, | ||
620 | u8 const *data) | ||
621 | { | ||
622 | struct kovaplus_roccat_report roccat_report; | ||
623 | struct kovaplus_mouse_report_button const *button_report; | ||
624 | |||
625 | if (data[0] != KOVAPLUS_MOUSE_REPORT_NUMBER_BUTTON) | ||
626 | return; | ||
627 | |||
628 | button_report = (struct kovaplus_mouse_report_button const *)data; | ||
629 | |||
630 | if (button_report->type == KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE_2) | ||
631 | return; | ||
632 | |||
633 | roccat_report.type = button_report->type; | ||
634 | roccat_report.profile = kovaplus->actual_profile + 1; | ||
635 | |||
636 | if (roccat_report.type == KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_MACRO || | ||
637 | roccat_report.type == KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_SHORTCUT || | ||
638 | roccat_report.type == KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_QUICKLAUNCH || | ||
639 | roccat_report.type == KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_TIMER) | ||
640 | roccat_report.button = button_report->data1; | ||
641 | else | ||
642 | roccat_report.button = 0; | ||
643 | |||
644 | if (roccat_report.type == KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_CPI) | ||
645 | roccat_report.data1 = kovaplus_convert_event_cpi(button_report->data1); | ||
646 | else | ||
647 | roccat_report.data1 = button_report->data1; | ||
648 | |||
649 | roccat_report.data2 = button_report->data2; | ||
650 | |||
651 | roccat_report_event(kovaplus->chrdev_minor, | ||
652 | (uint8_t const *)&roccat_report); | ||
653 | } | ||
654 | |||
655 | static int kovaplus_raw_event(struct hid_device *hdev, | ||
656 | struct hid_report *report, u8 *data, int size) | ||
657 | { | ||
658 | struct usb_interface *intf = to_usb_interface(hdev->dev.parent); | ||
659 | struct kovaplus_device *kovaplus = hid_get_drvdata(hdev); | ||
660 | |||
661 | if (intf->cur_altsetting->desc.bInterfaceProtocol | ||
662 | != USB_INTERFACE_PROTOCOL_MOUSE) | ||
663 | return 0; | ||
664 | |||
665 | kovaplus_keep_values_up_to_date(kovaplus, data); | ||
666 | |||
667 | if (kovaplus->roccat_claimed) | ||
668 | kovaplus_report_to_chrdev(kovaplus, data); | ||
669 | |||
670 | return 0; | ||
671 | } | ||
672 | |||
673 | static const struct hid_device_id kovaplus_devices[] = { | ||
674 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KOVAPLUS) }, | ||
675 | { } | ||
676 | }; | ||
677 | |||
678 | MODULE_DEVICE_TABLE(hid, kovaplus_devices); | ||
679 | |||
680 | static struct hid_driver kovaplus_driver = { | ||
681 | .name = "kovaplus", | ||
682 | .id_table = kovaplus_devices, | ||
683 | .probe = kovaplus_probe, | ||
684 | .remove = kovaplus_remove, | ||
685 | .raw_event = kovaplus_raw_event | ||
686 | }; | ||
687 | |||
688 | static int __init kovaplus_init(void) | ||
689 | { | ||
690 | int retval; | ||
691 | |||
692 | kovaplus_class = class_create(THIS_MODULE, "kovaplus"); | ||
693 | if (IS_ERR(kovaplus_class)) | ||
694 | return PTR_ERR(kovaplus_class); | ||
695 | kovaplus_class->dev_attrs = kovaplus_attributes; | ||
696 | kovaplus_class->dev_bin_attrs = kovaplus_bin_attributes; | ||
697 | |||
698 | retval = hid_register_driver(&kovaplus_driver); | ||
699 | if (retval) | ||
700 | class_destroy(kovaplus_class); | ||
701 | return retval; | ||
702 | } | ||
703 | |||
704 | static void __exit kovaplus_exit(void) | ||
705 | { | ||
706 | hid_unregister_driver(&kovaplus_driver); | ||
707 | class_destroy(kovaplus_class); | ||
708 | } | ||
709 | |||
710 | module_init(kovaplus_init); | ||
711 | module_exit(kovaplus_exit); | ||
712 | |||
713 | MODULE_AUTHOR("Stefan Achatz"); | ||
714 | MODULE_DESCRIPTION("USB Roccat Kova[+] driver"); | ||
715 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/hid/hid-roccat-kovaplus.h b/drivers/hid/hid-roccat-kovaplus.h new file mode 100644 index 000000000000..ce40607d21c7 --- /dev/null +++ b/drivers/hid/hid-roccat-kovaplus.h | |||
@@ -0,0 +1,157 @@ | |||
1 | #ifndef __HID_ROCCAT_KOVAPLUS_H | ||
2 | #define __HID_ROCCAT_KOVAPLUS_H | ||
3 | |||
4 | /* | ||
5 | * Copyright (c) 2010 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 | struct kovaplus_control { | ||
18 | uint8_t command; /* KOVAPLUS_COMMAND_CONTROL */ | ||
19 | uint8_t value; | ||
20 | uint8_t request; | ||
21 | } __packed; | ||
22 | |||
23 | enum kovaplus_control_requests { | ||
24 | /* read after write; value = 1 */ | ||
25 | KOVAPLUS_CONTROL_REQUEST_STATUS = 0x0, | ||
26 | /* write; value = profile number range 0-4 */ | ||
27 | KOVAPLUS_CONTROL_REQUEST_PROFILE_SETTINGS = 0x10, | ||
28 | /* write; value = profile number range 0-4 */ | ||
29 | KOVAPLUS_CONTROL_REQUEST_PROFILE_BUTTONS = 0x20, | ||
30 | }; | ||
31 | |||
32 | enum kovaplus_control_values { | ||
33 | KOVAPLUS_CONTROL_REQUEST_STATUS_OVERLOAD = 0, /* supposed */ | ||
34 | KOVAPLUS_CONTROL_REQUEST_STATUS_OK = 1, | ||
35 | KOVAPLUS_CONTROL_REQUEST_STATUS_WAIT = 3, /* supposed */ | ||
36 | }; | ||
37 | |||
38 | struct kovaplus_actual_profile { | ||
39 | uint8_t command; /* KOVAPLUS_COMMAND_ACTUAL_PROFILE */ | ||
40 | uint8_t size; /* always 3 */ | ||
41 | uint8_t actual_profile; /* Range 0-4! */ | ||
42 | } __packed; | ||
43 | |||
44 | struct kovaplus_profile_settings { | ||
45 | uint8_t command; /* KOVAPLUS_COMMAND_PROFILE_SETTINGS */ | ||
46 | uint8_t size; /* 16 */ | ||
47 | uint8_t profile_index; /* range 0-4 */ | ||
48 | uint8_t unknown1; | ||
49 | uint8_t sensitivity_x; /* range 1-10 */ | ||
50 | uint8_t sensitivity_y; /* range 1-10 */ | ||
51 | uint8_t cpi_levels_enabled; | ||
52 | uint8_t cpi_startup_level; /* range 1-4 */ | ||
53 | uint8_t data[8]; | ||
54 | } __packed; | ||
55 | |||
56 | struct kovaplus_profile_buttons { | ||
57 | uint8_t command; /* KOVAPLUS_COMMAND_PROFILE_BUTTONS */ | ||
58 | uint8_t size; /* 23 */ | ||
59 | uint8_t profile_index; /* range 0-4 */ | ||
60 | uint8_t data[20]; | ||
61 | } __packed; | ||
62 | |||
63 | struct kovaplus_info { | ||
64 | uint8_t command; /* KOVAPLUS_COMMAND_INFO */ | ||
65 | uint8_t size; /* 6 */ | ||
66 | uint8_t firmware_version; | ||
67 | uint8_t unknown[3]; | ||
68 | } __packed; | ||
69 | |||
70 | /* writes 1 on plugin */ | ||
71 | struct kovaplus_a { | ||
72 | uint8_t command; /* KOVAPLUS_COMMAND_A */ | ||
73 | uint8_t size; /* 3 */ | ||
74 | uint8_t unknown; | ||
75 | } __packed; | ||
76 | |||
77 | enum kovaplus_commands { | ||
78 | KOVAPLUS_COMMAND_CONTROL = 0x4, | ||
79 | KOVAPLUS_COMMAND_ACTUAL_PROFILE = 0x5, | ||
80 | KOVAPLUS_COMMAND_PROFILE_SETTINGS = 0x6, | ||
81 | KOVAPLUS_COMMAND_PROFILE_BUTTONS = 0x7, | ||
82 | KOVAPLUS_COMMAND_INFO = 0x9, | ||
83 | KOVAPLUS_COMMAND_A = 0xa, | ||
84 | }; | ||
85 | |||
86 | enum kovaplus_usb_commands { | ||
87 | KOVAPLUS_USB_COMMAND_CONTROL = 0x304, | ||
88 | KOVAPLUS_USB_COMMAND_ACTUAL_PROFILE = 0x305, | ||
89 | KOVAPLUS_USB_COMMAND_PROFILE_SETTINGS = 0x306, | ||
90 | KOVAPLUS_USB_COMMAND_PROFILE_BUTTONS = 0x307, | ||
91 | KOVAPLUS_USB_COMMAND_INFO = 0x309, | ||
92 | KOVAPLUS_USB_COMMAND_A = 0x30a, | ||
93 | }; | ||
94 | |||
95 | enum kovaplus_mouse_report_numbers { | ||
96 | KOVAPLUS_MOUSE_REPORT_NUMBER_MOUSE = 1, | ||
97 | KOVAPLUS_MOUSE_REPORT_NUMBER_AUDIO = 2, | ||
98 | KOVAPLUS_MOUSE_REPORT_NUMBER_BUTTON = 3, | ||
99 | KOVAPLUS_MOUSE_REPORT_NUMBER_KBD = 4, | ||
100 | }; | ||
101 | |||
102 | struct kovaplus_mouse_report_button { | ||
103 | uint8_t report_number; /* KOVAPLUS_MOUSE_REPORT_NUMBER_BUTTON */ | ||
104 | uint8_t unknown1; | ||
105 | uint8_t type; | ||
106 | uint8_t data1; | ||
107 | uint8_t data2; | ||
108 | } __packed; | ||
109 | |||
110 | enum kovaplus_mouse_report_button_types { | ||
111 | /* data1 = profile_number range 1-5; no release event */ | ||
112 | KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE_1 = 0x20, | ||
113 | /* data1 = profile_number range 1-5; no release event */ | ||
114 | KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE_2 = 0x30, | ||
115 | /* data1 = button_number range 1-18; data2 = action */ | ||
116 | KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_MACRO = 0x40, | ||
117 | /* data1 = button_number range 1-18; data2 = action */ | ||
118 | KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_SHORTCUT = 0x50, | ||
119 | /* data1 = button_number range 1-18; data2 = action */ | ||
120 | KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_QUICKLAUNCH = 0x60, | ||
121 | /* data1 = button_number range 1-18; data2 = action */ | ||
122 | KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_TIMER = 0x80, | ||
123 | /* data1 = 1 = 400, 2 = 800, 4 = 1600, 7 = 3200; no release event */ | ||
124 | KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_CPI = 0xb0, | ||
125 | /* data1 + data2 = sense range 1-10; no release event */ | ||
126 | KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_SENSITIVITY = 0xc0, | ||
127 | /* data1 = type as in profile_buttons; data2 = action */ | ||
128 | KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_MULTIMEDIA = 0xf0, | ||
129 | }; | ||
130 | |||
131 | enum kovaplus_mouse_report_button_actions { | ||
132 | KOVAPLUS_MOUSE_REPORT_BUTTON_ACTION_PRESS = 0, | ||
133 | KOVAPLUS_MOUSE_REPORT_BUTTON_ACTION_RELEASE = 1, | ||
134 | }; | ||
135 | |||
136 | struct kovaplus_roccat_report { | ||
137 | uint8_t type; | ||
138 | uint8_t profile; | ||
139 | uint8_t button; | ||
140 | uint8_t data1; | ||
141 | uint8_t data2; | ||
142 | } __packed; | ||
143 | |||
144 | struct kovaplus_device { | ||
145 | int actual_profile; | ||
146 | int actual_cpi; | ||
147 | int actual_x_sensitivity; | ||
148 | int actual_y_sensitivity; | ||
149 | int roccat_claimed; | ||
150 | int chrdev_minor; | ||
151 | struct mutex kovaplus_lock; | ||
152 | struct kovaplus_info info; | ||
153 | struct kovaplus_profile_settings profile_settings[5]; | ||
154 | struct kovaplus_profile_buttons profile_buttons[5]; | ||
155 | }; | ||
156 | |||
157 | #endif | ||
diff --git a/drivers/hid/hid-roccat-pyra.c b/drivers/hid/hid-roccat-pyra.c new file mode 100644 index 000000000000..38280c055a19 --- /dev/null +++ b/drivers/hid/hid-roccat-pyra.c | |||
@@ -0,0 +1,698 @@ | |||
1 | /* | ||
2 | * Roccat Pyra driver for Linux | ||
3 | * | ||
4 | * Copyright (c) 2010 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 Pyra is a mobile gamer mouse which comes in wired and wireless | ||
16 | * variant. Wireless variant is not tested. | ||
17 | * Userland tools can be found at http://sourceforge.net/projects/roccat | ||
18 | */ | ||
19 | |||
20 | #include <linux/device.h> | ||
21 | #include <linux/input.h> | ||
22 | #include <linux/hid.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/slab.h> | ||
25 | #include <linux/hid-roccat.h> | ||
26 | #include "hid-ids.h" | ||
27 | #include "hid-roccat-common.h" | ||
28 | #include "hid-roccat-pyra.h" | ||
29 | |||
30 | static uint profile_numbers[5] = {0, 1, 2, 3, 4}; | ||
31 | |||
32 | /* pyra_class is used for creating sysfs attributes via roccat char device */ | ||
33 | static struct class *pyra_class; | ||
34 | |||
35 | static void profile_activated(struct pyra_device *pyra, | ||
36 | unsigned int new_profile) | ||
37 | { | ||
38 | pyra->actual_profile = new_profile; | ||
39 | pyra->actual_cpi = pyra->profile_settings[pyra->actual_profile].y_cpi; | ||
40 | } | ||
41 | |||
42 | static int pyra_send_control(struct usb_device *usb_dev, int value, | ||
43 | enum pyra_control_requests request) | ||
44 | { | ||
45 | struct pyra_control control; | ||
46 | |||
47 | if ((request == PYRA_CONTROL_REQUEST_PROFILE_SETTINGS || | ||
48 | request == PYRA_CONTROL_REQUEST_PROFILE_BUTTONS) && | ||
49 | (value < 0 || value > 4)) | ||
50 | return -EINVAL; | ||
51 | |||
52 | control.command = PYRA_COMMAND_CONTROL; | ||
53 | control.value = value; | ||
54 | control.request = request; | ||
55 | |||
56 | return roccat_common_send(usb_dev, PYRA_USB_COMMAND_CONTROL, | ||
57 | &control, sizeof(struct pyra_control)); | ||
58 | } | ||
59 | |||
60 | static int pyra_receive_control_status(struct usb_device *usb_dev) | ||
61 | { | ||
62 | int retval; | ||
63 | struct pyra_control control; | ||
64 | |||
65 | do { | ||
66 | msleep(10); | ||
67 | retval = roccat_common_receive(usb_dev, PYRA_USB_COMMAND_CONTROL, | ||
68 | &control, sizeof(struct pyra_control)); | ||
69 | |||
70 | /* requested too early, try again */ | ||
71 | } while (retval == -EPROTO); | ||
72 | |||
73 | if (!retval && control.command == PYRA_COMMAND_CONTROL && | ||
74 | control.request == PYRA_CONTROL_REQUEST_STATUS && | ||
75 | control.value == 1) | ||
76 | return 0; | ||
77 | else { | ||
78 | hid_err(usb_dev, "receive control status: unknown response 0x%x 0x%x\n", | ||
79 | control.request, control.value); | ||
80 | return retval ? retval : -EINVAL; | ||
81 | } | ||
82 | } | ||
83 | |||
84 | static int pyra_get_profile_settings(struct usb_device *usb_dev, | ||
85 | struct pyra_profile_settings *buf, int number) | ||
86 | { | ||
87 | int retval; | ||
88 | retval = pyra_send_control(usb_dev, number, | ||
89 | PYRA_CONTROL_REQUEST_PROFILE_SETTINGS); | ||
90 | if (retval) | ||
91 | return retval; | ||
92 | return roccat_common_receive(usb_dev, PYRA_USB_COMMAND_PROFILE_SETTINGS, | ||
93 | buf, sizeof(struct pyra_profile_settings)); | ||
94 | } | ||
95 | |||
96 | static int pyra_get_profile_buttons(struct usb_device *usb_dev, | ||
97 | struct pyra_profile_buttons *buf, int number) | ||
98 | { | ||
99 | int retval; | ||
100 | retval = pyra_send_control(usb_dev, number, | ||
101 | PYRA_CONTROL_REQUEST_PROFILE_BUTTONS); | ||
102 | if (retval) | ||
103 | return retval; | ||
104 | return roccat_common_receive(usb_dev, PYRA_USB_COMMAND_PROFILE_BUTTONS, | ||
105 | buf, sizeof(struct pyra_profile_buttons)); | ||
106 | } | ||
107 | |||
108 | static int pyra_get_settings(struct usb_device *usb_dev, | ||
109 | struct pyra_settings *buf) | ||
110 | { | ||
111 | return roccat_common_receive(usb_dev, PYRA_USB_COMMAND_SETTINGS, | ||
112 | buf, sizeof(struct pyra_settings)); | ||
113 | } | ||
114 | |||
115 | static int pyra_get_info(struct usb_device *usb_dev, struct pyra_info *buf) | ||
116 | { | ||
117 | return roccat_common_receive(usb_dev, PYRA_USB_COMMAND_INFO, | ||
118 | buf, sizeof(struct pyra_info)); | ||
119 | } | ||
120 | |||
121 | static int pyra_send(struct usb_device *usb_dev, uint command, | ||
122 | void const *buf, uint size) | ||
123 | { | ||
124 | int retval; | ||
125 | retval = roccat_common_send(usb_dev, command, buf, size); | ||
126 | if (retval) | ||
127 | return retval; | ||
128 | return pyra_receive_control_status(usb_dev); | ||
129 | } | ||
130 | |||
131 | static int pyra_set_profile_settings(struct usb_device *usb_dev, | ||
132 | struct pyra_profile_settings const *settings) | ||
133 | { | ||
134 | return pyra_send(usb_dev, PYRA_USB_COMMAND_PROFILE_SETTINGS, settings, | ||
135 | sizeof(struct pyra_profile_settings)); | ||
136 | } | ||
137 | |||
138 | static int pyra_set_profile_buttons(struct usb_device *usb_dev, | ||
139 | struct pyra_profile_buttons const *buttons) | ||
140 | { | ||
141 | return pyra_send(usb_dev, PYRA_USB_COMMAND_PROFILE_BUTTONS, buttons, | ||
142 | sizeof(struct pyra_profile_buttons)); | ||
143 | } | ||
144 | |||
145 | static int pyra_set_settings(struct usb_device *usb_dev, | ||
146 | struct pyra_settings const *settings) | ||
147 | { | ||
148 | int retval; | ||
149 | retval = roccat_common_send(usb_dev, PYRA_USB_COMMAND_SETTINGS, settings, | ||
150 | sizeof(struct pyra_settings)); | ||
151 | if (retval) | ||
152 | return retval; | ||
153 | return pyra_receive_control_status(usb_dev); | ||
154 | } | ||
155 | |||
156 | static ssize_t pyra_sysfs_read_profilex_settings(struct file *fp, | ||
157 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
158 | loff_t off, size_t count) | ||
159 | { | ||
160 | struct device *dev = | ||
161 | container_of(kobj, struct device, kobj)->parent->parent; | ||
162 | struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev)); | ||
163 | |||
164 | if (off >= sizeof(struct pyra_profile_settings)) | ||
165 | return 0; | ||
166 | |||
167 | if (off + count > sizeof(struct pyra_profile_settings)) | ||
168 | count = sizeof(struct pyra_profile_settings) - off; | ||
169 | |||
170 | mutex_lock(&pyra->pyra_lock); | ||
171 | memcpy(buf, ((char const *)&pyra->profile_settings[*(uint *)(attr->private)]) + off, | ||
172 | count); | ||
173 | mutex_unlock(&pyra->pyra_lock); | ||
174 | |||
175 | return count; | ||
176 | } | ||
177 | |||
178 | static ssize_t pyra_sysfs_read_profilex_buttons(struct file *fp, | ||
179 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
180 | loff_t off, size_t count) | ||
181 | { | ||
182 | struct device *dev = | ||
183 | container_of(kobj, struct device, kobj)->parent->parent; | ||
184 | struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev)); | ||
185 | |||
186 | if (off >= sizeof(struct pyra_profile_buttons)) | ||
187 | return 0; | ||
188 | |||
189 | if (off + count > sizeof(struct pyra_profile_buttons)) | ||
190 | count = sizeof(struct pyra_profile_buttons) - off; | ||
191 | |||
192 | mutex_lock(&pyra->pyra_lock); | ||
193 | memcpy(buf, ((char const *)&pyra->profile_buttons[*(uint *)(attr->private)]) + off, | ||
194 | count); | ||
195 | mutex_unlock(&pyra->pyra_lock); | ||
196 | |||
197 | return count; | ||
198 | } | ||
199 | |||
200 | static ssize_t pyra_sysfs_write_profile_settings(struct file *fp, | ||
201 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
202 | loff_t off, size_t count) | ||
203 | { | ||
204 | struct device *dev = | ||
205 | container_of(kobj, struct device, kobj)->parent->parent; | ||
206 | struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev)); | ||
207 | struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); | ||
208 | int retval = 0; | ||
209 | int difference; | ||
210 | int profile_number; | ||
211 | struct pyra_profile_settings *profile_settings; | ||
212 | |||
213 | if (off != 0 || count != sizeof(struct pyra_profile_settings)) | ||
214 | return -EINVAL; | ||
215 | |||
216 | profile_number = ((struct pyra_profile_settings const *)buf)->number; | ||
217 | profile_settings = &pyra->profile_settings[profile_number]; | ||
218 | |||
219 | mutex_lock(&pyra->pyra_lock); | ||
220 | difference = memcmp(buf, profile_settings, | ||
221 | sizeof(struct pyra_profile_settings)); | ||
222 | if (difference) { | ||
223 | retval = pyra_set_profile_settings(usb_dev, | ||
224 | (struct pyra_profile_settings const *)buf); | ||
225 | if (!retval) | ||
226 | memcpy(profile_settings, buf, | ||
227 | sizeof(struct pyra_profile_settings)); | ||
228 | } | ||
229 | mutex_unlock(&pyra->pyra_lock); | ||
230 | |||
231 | if (retval) | ||
232 | return retval; | ||
233 | |||
234 | return sizeof(struct pyra_profile_settings); | ||
235 | } | ||
236 | |||
237 | static ssize_t pyra_sysfs_write_profile_buttons(struct file *fp, | ||
238 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
239 | loff_t off, size_t count) | ||
240 | { | ||
241 | struct device *dev = | ||
242 | container_of(kobj, struct device, kobj)->parent->parent; | ||
243 | struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev)); | ||
244 | struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); | ||
245 | int retval = 0; | ||
246 | int difference; | ||
247 | int profile_number; | ||
248 | struct pyra_profile_buttons *profile_buttons; | ||
249 | |||
250 | if (off != 0 || count != sizeof(struct pyra_profile_buttons)) | ||
251 | return -EINVAL; | ||
252 | |||
253 | profile_number = ((struct pyra_profile_buttons const *)buf)->number; | ||
254 | profile_buttons = &pyra->profile_buttons[profile_number]; | ||
255 | |||
256 | mutex_lock(&pyra->pyra_lock); | ||
257 | difference = memcmp(buf, profile_buttons, | ||
258 | sizeof(struct pyra_profile_buttons)); | ||
259 | if (difference) { | ||
260 | retval = pyra_set_profile_buttons(usb_dev, | ||
261 | (struct pyra_profile_buttons const *)buf); | ||
262 | if (!retval) | ||
263 | memcpy(profile_buttons, buf, | ||
264 | sizeof(struct pyra_profile_buttons)); | ||
265 | } | ||
266 | mutex_unlock(&pyra->pyra_lock); | ||
267 | |||
268 | if (retval) | ||
269 | return retval; | ||
270 | |||
271 | return sizeof(struct pyra_profile_buttons); | ||
272 | } | ||
273 | |||
274 | static ssize_t pyra_sysfs_read_settings(struct file *fp, | ||
275 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
276 | loff_t off, size_t count) | ||
277 | { | ||
278 | struct device *dev = | ||
279 | container_of(kobj, struct device, kobj)->parent->parent; | ||
280 | struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev)); | ||
281 | |||
282 | if (off >= sizeof(struct pyra_settings)) | ||
283 | return 0; | ||
284 | |||
285 | if (off + count > sizeof(struct pyra_settings)) | ||
286 | count = sizeof(struct pyra_settings) - off; | ||
287 | |||
288 | mutex_lock(&pyra->pyra_lock); | ||
289 | memcpy(buf, ((char const *)&pyra->settings) + off, count); | ||
290 | mutex_unlock(&pyra->pyra_lock); | ||
291 | |||
292 | return count; | ||
293 | } | ||
294 | |||
295 | static ssize_t pyra_sysfs_write_settings(struct file *fp, | ||
296 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
297 | loff_t off, size_t count) | ||
298 | { | ||
299 | struct device *dev = | ||
300 | container_of(kobj, struct device, kobj)->parent->parent; | ||
301 | struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev)); | ||
302 | struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); | ||
303 | int retval = 0; | ||
304 | int difference; | ||
305 | |||
306 | if (off != 0 || count != sizeof(struct pyra_settings)) | ||
307 | return -EINVAL; | ||
308 | |||
309 | mutex_lock(&pyra->pyra_lock); | ||
310 | difference = memcmp(buf, &pyra->settings, sizeof(struct pyra_settings)); | ||
311 | if (difference) { | ||
312 | retval = pyra_set_settings(usb_dev, | ||
313 | (struct pyra_settings const *)buf); | ||
314 | if (!retval) | ||
315 | memcpy(&pyra->settings, buf, | ||
316 | sizeof(struct pyra_settings)); | ||
317 | } | ||
318 | mutex_unlock(&pyra->pyra_lock); | ||
319 | |||
320 | if (retval) | ||
321 | return retval; | ||
322 | |||
323 | profile_activated(pyra, pyra->settings.startup_profile); | ||
324 | |||
325 | return sizeof(struct pyra_settings); | ||
326 | } | ||
327 | |||
328 | |||
329 | static ssize_t pyra_sysfs_show_actual_cpi(struct device *dev, | ||
330 | struct device_attribute *attr, char *buf) | ||
331 | { | ||
332 | struct pyra_device *pyra = | ||
333 | hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); | ||
334 | return snprintf(buf, PAGE_SIZE, "%d\n", pyra->actual_cpi); | ||
335 | } | ||
336 | |||
337 | static ssize_t pyra_sysfs_show_actual_profile(struct device *dev, | ||
338 | struct device_attribute *attr, char *buf) | ||
339 | { | ||
340 | struct pyra_device *pyra = | ||
341 | hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); | ||
342 | return snprintf(buf, PAGE_SIZE, "%d\n", pyra->actual_profile); | ||
343 | } | ||
344 | |||
345 | static ssize_t pyra_sysfs_show_firmware_version(struct device *dev, | ||
346 | struct device_attribute *attr, char *buf) | ||
347 | { | ||
348 | struct pyra_device *pyra = | ||
349 | hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); | ||
350 | return snprintf(buf, PAGE_SIZE, "%d\n", pyra->firmware_version); | ||
351 | } | ||
352 | |||
353 | static ssize_t pyra_sysfs_show_startup_profile(struct device *dev, | ||
354 | struct device_attribute *attr, char *buf) | ||
355 | { | ||
356 | struct pyra_device *pyra = | ||
357 | hid_get_drvdata(dev_get_drvdata(dev->parent->parent)); | ||
358 | return snprintf(buf, PAGE_SIZE, "%d\n", pyra->settings.startup_profile); | ||
359 | } | ||
360 | |||
361 | static struct device_attribute pyra_attributes[] = { | ||
362 | __ATTR(actual_cpi, 0440, pyra_sysfs_show_actual_cpi, NULL), | ||
363 | __ATTR(actual_profile, 0440, pyra_sysfs_show_actual_profile, NULL), | ||
364 | __ATTR(firmware_version, 0440, | ||
365 | pyra_sysfs_show_firmware_version, NULL), | ||
366 | __ATTR(startup_profile, 0440, | ||
367 | pyra_sysfs_show_startup_profile, NULL), | ||
368 | __ATTR_NULL | ||
369 | }; | ||
370 | |||
371 | static struct bin_attribute pyra_bin_attributes[] = { | ||
372 | { | ||
373 | .attr = { .name = "profile_settings", .mode = 0220 }, | ||
374 | .size = sizeof(struct pyra_profile_settings), | ||
375 | .write = pyra_sysfs_write_profile_settings | ||
376 | }, | ||
377 | { | ||
378 | .attr = { .name = "profile1_settings", .mode = 0440 }, | ||
379 | .size = sizeof(struct pyra_profile_settings), | ||
380 | .read = pyra_sysfs_read_profilex_settings, | ||
381 | .private = &profile_numbers[0] | ||
382 | }, | ||
383 | { | ||
384 | .attr = { .name = "profile2_settings", .mode = 0440 }, | ||
385 | .size = sizeof(struct pyra_profile_settings), | ||
386 | .read = pyra_sysfs_read_profilex_settings, | ||
387 | .private = &profile_numbers[1] | ||
388 | }, | ||
389 | { | ||
390 | .attr = { .name = "profile3_settings", .mode = 0440 }, | ||
391 | .size = sizeof(struct pyra_profile_settings), | ||
392 | .read = pyra_sysfs_read_profilex_settings, | ||
393 | .private = &profile_numbers[2] | ||
394 | }, | ||
395 | { | ||
396 | .attr = { .name = "profile4_settings", .mode = 0440 }, | ||
397 | .size = sizeof(struct pyra_profile_settings), | ||
398 | .read = pyra_sysfs_read_profilex_settings, | ||
399 | .private = &profile_numbers[3] | ||
400 | }, | ||
401 | { | ||
402 | .attr = { .name = "profile5_settings", .mode = 0440 }, | ||
403 | .size = sizeof(struct pyra_profile_settings), | ||
404 | .read = pyra_sysfs_read_profilex_settings, | ||
405 | .private = &profile_numbers[4] | ||
406 | }, | ||
407 | { | ||
408 | .attr = { .name = "profile_buttons", .mode = 0220 }, | ||
409 | .size = sizeof(struct pyra_profile_buttons), | ||
410 | .write = pyra_sysfs_write_profile_buttons | ||
411 | }, | ||
412 | { | ||
413 | .attr = { .name = "profile1_buttons", .mode = 0440 }, | ||
414 | .size = sizeof(struct pyra_profile_buttons), | ||
415 | .read = pyra_sysfs_read_profilex_buttons, | ||
416 | .private = &profile_numbers[0] | ||
417 | }, | ||
418 | { | ||
419 | .attr = { .name = "profile2_buttons", .mode = 0440 }, | ||
420 | .size = sizeof(struct pyra_profile_buttons), | ||
421 | .read = pyra_sysfs_read_profilex_buttons, | ||
422 | .private = &profile_numbers[1] | ||
423 | }, | ||
424 | { | ||
425 | .attr = { .name = "profile3_buttons", .mode = 0440 }, | ||
426 | .size = sizeof(struct pyra_profile_buttons), | ||
427 | .read = pyra_sysfs_read_profilex_buttons, | ||
428 | .private = &profile_numbers[2] | ||
429 | }, | ||
430 | { | ||
431 | .attr = { .name = "profile4_buttons", .mode = 0440 }, | ||
432 | .size = sizeof(struct pyra_profile_buttons), | ||
433 | .read = pyra_sysfs_read_profilex_buttons, | ||
434 | .private = &profile_numbers[3] | ||
435 | }, | ||
436 | { | ||
437 | .attr = { .name = "profile5_buttons", .mode = 0440 }, | ||
438 | .size = sizeof(struct pyra_profile_buttons), | ||
439 | .read = pyra_sysfs_read_profilex_buttons, | ||
440 | .private = &profile_numbers[4] | ||
441 | }, | ||
442 | { | ||
443 | .attr = { .name = "settings", .mode = 0660 }, | ||
444 | .size = sizeof(struct pyra_settings), | ||
445 | .read = pyra_sysfs_read_settings, | ||
446 | .write = pyra_sysfs_write_settings | ||
447 | }, | ||
448 | __ATTR_NULL | ||
449 | }; | ||
450 | |||
451 | static int pyra_init_pyra_device_struct(struct usb_device *usb_dev, | ||
452 | struct pyra_device *pyra) | ||
453 | { | ||
454 | struct pyra_info info; | ||
455 | int retval, i; | ||
456 | |||
457 | mutex_init(&pyra->pyra_lock); | ||
458 | |||
459 | retval = pyra_get_info(usb_dev, &info); | ||
460 | if (retval) | ||
461 | return retval; | ||
462 | |||
463 | pyra->firmware_version = info.firmware_version; | ||
464 | |||
465 | retval = pyra_get_settings(usb_dev, &pyra->settings); | ||
466 | if (retval) | ||
467 | return retval; | ||
468 | |||
469 | for (i = 0; i < 5; ++i) { | ||
470 | retval = pyra_get_profile_settings(usb_dev, | ||
471 | &pyra->profile_settings[i], i); | ||
472 | if (retval) | ||
473 | return retval; | ||
474 | |||
475 | retval = pyra_get_profile_buttons(usb_dev, | ||
476 | &pyra->profile_buttons[i], i); | ||
477 | if (retval) | ||
478 | return retval; | ||
479 | } | ||
480 | |||
481 | profile_activated(pyra, pyra->settings.startup_profile); | ||
482 | |||
483 | return 0; | ||
484 | } | ||
485 | |||
486 | static int pyra_init_specials(struct hid_device *hdev) | ||
487 | { | ||
488 | struct usb_interface *intf = to_usb_interface(hdev->dev.parent); | ||
489 | struct usb_device *usb_dev = interface_to_usbdev(intf); | ||
490 | struct pyra_device *pyra; | ||
491 | int retval; | ||
492 | |||
493 | if (intf->cur_altsetting->desc.bInterfaceProtocol | ||
494 | == USB_INTERFACE_PROTOCOL_MOUSE) { | ||
495 | |||
496 | pyra = kzalloc(sizeof(*pyra), GFP_KERNEL); | ||
497 | if (!pyra) { | ||
498 | hid_err(hdev, "can't alloc device descriptor\n"); | ||
499 | return -ENOMEM; | ||
500 | } | ||
501 | hid_set_drvdata(hdev, pyra); | ||
502 | |||
503 | retval = pyra_init_pyra_device_struct(usb_dev, pyra); | ||
504 | if (retval) { | ||
505 | hid_err(hdev, "couldn't init struct pyra_device\n"); | ||
506 | goto exit_free; | ||
507 | } | ||
508 | |||
509 | retval = roccat_connect(pyra_class, hdev, | ||
510 | sizeof(struct pyra_roccat_report)); | ||
511 | if (retval < 0) { | ||
512 | hid_err(hdev, "couldn't init char dev\n"); | ||
513 | } else { | ||
514 | pyra->chrdev_minor = retval; | ||
515 | pyra->roccat_claimed = 1; | ||
516 | } | ||
517 | } else { | ||
518 | hid_set_drvdata(hdev, NULL); | ||
519 | } | ||
520 | |||
521 | return 0; | ||
522 | exit_free: | ||
523 | kfree(pyra); | ||
524 | return retval; | ||
525 | } | ||
526 | |||
527 | static void pyra_remove_specials(struct hid_device *hdev) | ||
528 | { | ||
529 | struct usb_interface *intf = to_usb_interface(hdev->dev.parent); | ||
530 | struct pyra_device *pyra; | ||
531 | |||
532 | if (intf->cur_altsetting->desc.bInterfaceProtocol | ||
533 | == USB_INTERFACE_PROTOCOL_MOUSE) { | ||
534 | pyra = hid_get_drvdata(hdev); | ||
535 | if (pyra->roccat_claimed) | ||
536 | roccat_disconnect(pyra->chrdev_minor); | ||
537 | kfree(hid_get_drvdata(hdev)); | ||
538 | } | ||
539 | } | ||
540 | |||
541 | static int pyra_probe(struct hid_device *hdev, const struct hid_device_id *id) | ||
542 | { | ||
543 | int retval; | ||
544 | |||
545 | retval = hid_parse(hdev); | ||
546 | if (retval) { | ||
547 | hid_err(hdev, "parse failed\n"); | ||
548 | goto exit; | ||
549 | } | ||
550 | |||
551 | retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT); | ||
552 | if (retval) { | ||
553 | hid_err(hdev, "hw start failed\n"); | ||
554 | goto exit; | ||
555 | } | ||
556 | |||
557 | retval = pyra_init_specials(hdev); | ||
558 | if (retval) { | ||
559 | hid_err(hdev, "couldn't install mouse\n"); | ||
560 | goto exit_stop; | ||
561 | } | ||
562 | return 0; | ||
563 | |||
564 | exit_stop: | ||
565 | hid_hw_stop(hdev); | ||
566 | exit: | ||
567 | return retval; | ||
568 | } | ||
569 | |||
570 | static void pyra_remove(struct hid_device *hdev) | ||
571 | { | ||
572 | pyra_remove_specials(hdev); | ||
573 | hid_hw_stop(hdev); | ||
574 | } | ||
575 | |||
576 | static void pyra_keep_values_up_to_date(struct pyra_device *pyra, | ||
577 | u8 const *data) | ||
578 | { | ||
579 | struct pyra_mouse_event_button const *button_event; | ||
580 | |||
581 | switch (data[0]) { | ||
582 | case PYRA_MOUSE_REPORT_NUMBER_BUTTON: | ||
583 | button_event = (struct pyra_mouse_event_button const *)data; | ||
584 | switch (button_event->type) { | ||
585 | case PYRA_MOUSE_EVENT_BUTTON_TYPE_PROFILE_2: | ||
586 | profile_activated(pyra, button_event->data1 - 1); | ||
587 | break; | ||
588 | case PYRA_MOUSE_EVENT_BUTTON_TYPE_CPI: | ||
589 | pyra->actual_cpi = button_event->data1; | ||
590 | break; | ||
591 | } | ||
592 | break; | ||
593 | } | ||
594 | } | ||
595 | |||
596 | static void pyra_report_to_chrdev(struct pyra_device const *pyra, | ||
597 | u8 const *data) | ||
598 | { | ||
599 | struct pyra_roccat_report roccat_report; | ||
600 | struct pyra_mouse_event_button const *button_event; | ||
601 | |||
602 | if (data[0] != PYRA_MOUSE_REPORT_NUMBER_BUTTON) | ||
603 | return; | ||
604 | |||
605 | button_event = (struct pyra_mouse_event_button const *)data; | ||
606 | |||
607 | switch (button_event->type) { | ||
608 | case PYRA_MOUSE_EVENT_BUTTON_TYPE_PROFILE_2: | ||
609 | case PYRA_MOUSE_EVENT_BUTTON_TYPE_CPI: | ||
610 | roccat_report.type = button_event->type; | ||
611 | roccat_report.value = button_event->data1; | ||
612 | roccat_report.key = 0; | ||
613 | roccat_report_event(pyra->chrdev_minor, | ||
614 | (uint8_t const *)&roccat_report); | ||
615 | break; | ||
616 | case PYRA_MOUSE_EVENT_BUTTON_TYPE_MACRO: | ||
617 | case PYRA_MOUSE_EVENT_BUTTON_TYPE_SHORTCUT: | ||
618 | case PYRA_MOUSE_EVENT_BUTTON_TYPE_QUICKLAUNCH: | ||
619 | if (button_event->data2 == PYRA_MOUSE_EVENT_BUTTON_PRESS) { | ||
620 | roccat_report.type = button_event->type; | ||
621 | roccat_report.key = button_event->data1; | ||
622 | /* | ||
623 | * pyra reports profile numbers with range 1-5. | ||
624 | * Keeping this behaviour. | ||
625 | */ | ||
626 | roccat_report.value = pyra->actual_profile + 1; | ||
627 | roccat_report_event(pyra->chrdev_minor, | ||
628 | (uint8_t const *)&roccat_report); | ||
629 | } | ||
630 | break; | ||
631 | } | ||
632 | } | ||
633 | |||
634 | static int pyra_raw_event(struct hid_device *hdev, struct hid_report *report, | ||
635 | u8 *data, int size) | ||
636 | { | ||
637 | struct usb_interface *intf = to_usb_interface(hdev->dev.parent); | ||
638 | struct pyra_device *pyra = hid_get_drvdata(hdev); | ||
639 | |||
640 | if (intf->cur_altsetting->desc.bInterfaceProtocol | ||
641 | != USB_INTERFACE_PROTOCOL_MOUSE) | ||
642 | return 0; | ||
643 | |||
644 | pyra_keep_values_up_to_date(pyra, data); | ||
645 | |||
646 | if (pyra->roccat_claimed) | ||
647 | pyra_report_to_chrdev(pyra, data); | ||
648 | |||
649 | return 0; | ||
650 | } | ||
651 | |||
652 | static const struct hid_device_id pyra_devices[] = { | ||
653 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, | ||
654 | USB_DEVICE_ID_ROCCAT_PYRA_WIRED) }, | ||
655 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, | ||
656 | USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS) }, | ||
657 | { } | ||
658 | }; | ||
659 | |||
660 | MODULE_DEVICE_TABLE(hid, pyra_devices); | ||
661 | |||
662 | static struct hid_driver pyra_driver = { | ||
663 | .name = "pyra", | ||
664 | .id_table = pyra_devices, | ||
665 | .probe = pyra_probe, | ||
666 | .remove = pyra_remove, | ||
667 | .raw_event = pyra_raw_event | ||
668 | }; | ||
669 | |||
670 | static int __init pyra_init(void) | ||
671 | { | ||
672 | int retval; | ||
673 | |||
674 | /* class name has to be same as driver name */ | ||
675 | pyra_class = class_create(THIS_MODULE, "pyra"); | ||
676 | if (IS_ERR(pyra_class)) | ||
677 | return PTR_ERR(pyra_class); | ||
678 | pyra_class->dev_attrs = pyra_attributes; | ||
679 | pyra_class->dev_bin_attrs = pyra_bin_attributes; | ||
680 | |||
681 | retval = hid_register_driver(&pyra_driver); | ||
682 | if (retval) | ||
683 | class_destroy(pyra_class); | ||
684 | return retval; | ||
685 | } | ||
686 | |||
687 | static void __exit pyra_exit(void) | ||
688 | { | ||
689 | hid_unregister_driver(&pyra_driver); | ||
690 | class_destroy(pyra_class); | ||
691 | } | ||
692 | |||
693 | module_init(pyra_init); | ||
694 | module_exit(pyra_exit); | ||
695 | |||
696 | MODULE_AUTHOR("Stefan Achatz"); | ||
697 | MODULE_DESCRIPTION("USB Roccat Pyra driver"); | ||
698 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/hid/hid-roccat-pyra.h b/drivers/hid/hid-roccat-pyra.h new file mode 100644 index 000000000000..14cbbe1621e0 --- /dev/null +++ b/drivers/hid/hid-roccat-pyra.h | |||
@@ -0,0 +1,181 @@ | |||
1 | #ifndef __HID_ROCCAT_PYRA_H | ||
2 | #define __HID_ROCCAT_PYRA_H | ||
3 | |||
4 | /* | ||
5 | * Copyright (c) 2010 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 | struct pyra_b { | ||
18 | uint8_t command; /* PYRA_COMMAND_B */ | ||
19 | uint8_t size; /* always 3 */ | ||
20 | uint8_t unknown; /* 1 */ | ||
21 | } __attribute__ ((__packed__)); | ||
22 | |||
23 | struct pyra_control { | ||
24 | uint8_t command; /* PYRA_COMMAND_CONTROL */ | ||
25 | /* | ||
26 | * value is profile number for request_settings and request_buttons | ||
27 | * 1 if status ok for request_status | ||
28 | */ | ||
29 | uint8_t value; /* Range 0-4 */ | ||
30 | uint8_t request; | ||
31 | } __attribute__ ((__packed__)); | ||
32 | |||
33 | enum pyra_control_requests { | ||
34 | PYRA_CONTROL_REQUEST_STATUS = 0x00, | ||
35 | PYRA_CONTROL_REQUEST_PROFILE_SETTINGS = 0x10, | ||
36 | PYRA_CONTROL_REQUEST_PROFILE_BUTTONS = 0x20 | ||
37 | }; | ||
38 | |||
39 | struct pyra_settings { | ||
40 | uint8_t command; /* PYRA_COMMAND_SETTINGS */ | ||
41 | uint8_t size; /* always 3 */ | ||
42 | uint8_t startup_profile; /* Range 0-4! */ | ||
43 | } __attribute__ ((__packed__)); | ||
44 | |||
45 | struct pyra_profile_settings { | ||
46 | uint8_t command; /* PYRA_COMMAND_PROFILE_SETTINGS */ | ||
47 | uint8_t size; /* always 0xd */ | ||
48 | uint8_t number; /* Range 0-4 */ | ||
49 | uint8_t xysync; | ||
50 | uint8_t x_sensitivity; /* 0x1-0xa */ | ||
51 | uint8_t y_sensitivity; | ||
52 | uint8_t x_cpi; /* unused */ | ||
53 | uint8_t y_cpi; /* this value is for x and y */ | ||
54 | uint8_t lightswitch; /* 0 = off, 1 = on */ | ||
55 | uint8_t light_effect; | ||
56 | uint8_t handedness; | ||
57 | uint16_t checksum; /* byte sum */ | ||
58 | } __attribute__ ((__packed__)); | ||
59 | |||
60 | struct pyra_profile_buttons { | ||
61 | uint8_t command; /* PYRA_COMMAND_PROFILE_BUTTONS */ | ||
62 | uint8_t size; /* always 0x13 */ | ||
63 | uint8_t number; /* Range 0-4 */ | ||
64 | uint8_t buttons[14]; | ||
65 | uint16_t checksum; /* byte sum */ | ||
66 | } __attribute__ ((__packed__)); | ||
67 | |||
68 | struct pyra_info { | ||
69 | uint8_t command; /* PYRA_COMMAND_INFO */ | ||
70 | uint8_t size; /* always 6 */ | ||
71 | uint8_t firmware_version; | ||
72 | uint8_t unknown1; /* always 0 */ | ||
73 | uint8_t unknown2; /* always 1 */ | ||
74 | uint8_t unknown3; /* always 0 */ | ||
75 | } __attribute__ ((__packed__)); | ||
76 | |||
77 | enum pyra_commands { | ||
78 | PYRA_COMMAND_CONTROL = 0x4, | ||
79 | PYRA_COMMAND_SETTINGS = 0x5, | ||
80 | PYRA_COMMAND_PROFILE_SETTINGS = 0x6, | ||
81 | PYRA_COMMAND_PROFILE_BUTTONS = 0x7, | ||
82 | PYRA_COMMAND_INFO = 0x9, | ||
83 | PYRA_COMMAND_B = 0xb | ||
84 | }; | ||
85 | |||
86 | enum pyra_usb_commands { | ||
87 | PYRA_USB_COMMAND_CONTROL = 0x304, | ||
88 | PYRA_USB_COMMAND_SETTINGS = 0x305, | ||
89 | PYRA_USB_COMMAND_PROFILE_SETTINGS = 0x306, | ||
90 | PYRA_USB_COMMAND_PROFILE_BUTTONS = 0x307, | ||
91 | PYRA_USB_COMMAND_INFO = 0x309, | ||
92 | PYRA_USB_COMMAND_B = 0x30b /* writes 3 bytes */ | ||
93 | }; | ||
94 | |||
95 | enum pyra_mouse_report_numbers { | ||
96 | PYRA_MOUSE_REPORT_NUMBER_HID = 1, | ||
97 | PYRA_MOUSE_REPORT_NUMBER_AUDIO = 2, | ||
98 | PYRA_MOUSE_REPORT_NUMBER_BUTTON = 3, | ||
99 | }; | ||
100 | |||
101 | struct pyra_mouse_event_button { | ||
102 | uint8_t report_number; /* always 3 */ | ||
103 | uint8_t unknown; /* always 0 */ | ||
104 | uint8_t type; | ||
105 | uint8_t data1; | ||
106 | uint8_t data2; | ||
107 | } __attribute__ ((__packed__)); | ||
108 | |||
109 | struct pyra_mouse_event_audio { | ||
110 | uint8_t report_number; /* always 2 */ | ||
111 | uint8_t type; | ||
112 | uint8_t unused; /* always 0 */ | ||
113 | } __attribute__ ((__packed__)); | ||
114 | |||
115 | /* hid audio controls */ | ||
116 | enum pyra_mouse_event_audio_types { | ||
117 | PYRA_MOUSE_EVENT_AUDIO_TYPE_MUTE = 0xe2, | ||
118 | PYRA_MOUSE_EVENT_AUDIO_TYPE_VOLUME_UP = 0xe9, | ||
119 | PYRA_MOUSE_EVENT_AUDIO_TYPE_VOLUME_DOWN = 0xea, | ||
120 | }; | ||
121 | |||
122 | enum pyra_mouse_event_button_types { | ||
123 | /* | ||
124 | * Mouse sends tilt events on report_number 1 and 3 | ||
125 | * Tilt events are sent repeatedly with 0.94s between first and second | ||
126 | * event and 0.22s on subsequent | ||
127 | */ | ||
128 | PYRA_MOUSE_EVENT_BUTTON_TYPE_TILT = 0x10, | ||
129 | |||
130 | /* | ||
131 | * These are sent sequentially | ||
132 | * data1 contains new profile number in range 1-5 | ||
133 | */ | ||
134 | PYRA_MOUSE_EVENT_BUTTON_TYPE_PROFILE_1 = 0x20, | ||
135 | PYRA_MOUSE_EVENT_BUTTON_TYPE_PROFILE_2 = 0x30, | ||
136 | |||
137 | /* | ||
138 | * data1 = button_number (rmp index) | ||
139 | * data2 = pressed/released | ||
140 | */ | ||
141 | PYRA_MOUSE_EVENT_BUTTON_TYPE_MACRO = 0x40, | ||
142 | PYRA_MOUSE_EVENT_BUTTON_TYPE_SHORTCUT = 0x50, | ||
143 | |||
144 | /* | ||
145 | * data1 = button_number (rmp index) | ||
146 | */ | ||
147 | PYRA_MOUSE_EVENT_BUTTON_TYPE_QUICKLAUNCH = 0x60, | ||
148 | |||
149 | /* data1 = new cpi */ | ||
150 | PYRA_MOUSE_EVENT_BUTTON_TYPE_CPI = 0xb0, | ||
151 | |||
152 | /* data1 and data2 = new sensitivity */ | ||
153 | PYRA_MOUSE_EVENT_BUTTON_TYPE_SENSITIVITY = 0xc0, | ||
154 | |||
155 | PYRA_MOUSE_EVENT_BUTTON_TYPE_MULTIMEDIA = 0xf0, | ||
156 | }; | ||
157 | |||
158 | enum { | ||
159 | PYRA_MOUSE_EVENT_BUTTON_PRESS = 0, | ||
160 | PYRA_MOUSE_EVENT_BUTTON_RELEASE = 1, | ||
161 | }; | ||
162 | |||
163 | struct pyra_roccat_report { | ||
164 | uint8_t type; | ||
165 | uint8_t value; | ||
166 | uint8_t key; | ||
167 | } __attribute__ ((__packed__)); | ||
168 | |||
169 | struct pyra_device { | ||
170 | int actual_profile; | ||
171 | int actual_cpi; | ||
172 | int firmware_version; | ||
173 | int roccat_claimed; | ||
174 | int chrdev_minor; | ||
175 | struct mutex pyra_lock; | ||
176 | struct pyra_settings settings; | ||
177 | struct pyra_profile_settings profile_settings[5]; | ||
178 | struct pyra_profile_buttons profile_buttons[5]; | ||
179 | }; | ||
180 | |||
181 | #endif | ||
diff --git a/drivers/hid/hid-roccat.c b/drivers/hid/hid-roccat.c index f6e80c7ca61e..5666e7587b18 100644 --- a/drivers/hid/hid-roccat.c +++ b/drivers/hid/hid-roccat.c | |||
@@ -21,11 +21,12 @@ | |||
21 | * It is inspired by hidraw, but uses only one circular buffer for all readers. | 21 | * It is inspired by hidraw, but uses only one circular buffer for all readers. |
22 | */ | 22 | */ |
23 | 23 | ||
24 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
25 | |||
24 | #include <linux/cdev.h> | 26 | #include <linux/cdev.h> |
25 | #include <linux/poll.h> | 27 | #include <linux/poll.h> |
26 | #include <linux/sched.h> | 28 | #include <linux/sched.h> |
27 | 29 | #include <linux/hid-roccat.h> | |
28 | #include "hid-roccat.h" | ||
29 | 30 | ||
30 | #define ROCCAT_FIRST_MINOR 0 | 31 | #define ROCCAT_FIRST_MINOR 0 |
31 | #define ROCCAT_MAX_DEVICES 8 | 32 | #define ROCCAT_MAX_DEVICES 8 |
@@ -35,11 +36,11 @@ | |||
35 | 36 | ||
36 | struct roccat_report { | 37 | struct roccat_report { |
37 | uint8_t *value; | 38 | uint8_t *value; |
38 | int len; | ||
39 | }; | 39 | }; |
40 | 40 | ||
41 | struct roccat_device { | 41 | struct roccat_device { |
42 | unsigned int minor; | 42 | unsigned int minor; |
43 | int report_size; | ||
43 | int open; | 44 | int open; |
44 | int exist; | 45 | int exist; |
45 | wait_queue_head_t wait; | 46 | wait_queue_head_t wait; |
@@ -65,7 +66,6 @@ struct roccat_reader { | |||
65 | }; | 66 | }; |
66 | 67 | ||
67 | static int roccat_major; | 68 | static int roccat_major; |
68 | static struct class *roccat_class; | ||
69 | static struct cdev roccat_cdev; | 69 | static struct cdev roccat_cdev; |
70 | 70 | ||
71 | static struct roccat_device *devices[ROCCAT_MAX_DEVICES]; | 71 | static struct roccat_device *devices[ROCCAT_MAX_DEVICES]; |
@@ -122,7 +122,7 @@ static ssize_t roccat_read(struct file *file, char __user *buffer, | |||
122 | * If report is larger than requested amount of data, rest of report | 122 | * If report is larger than requested amount of data, rest of report |
123 | * is lost! | 123 | * is lost! |
124 | */ | 124 | */ |
125 | len = report->len > count ? count : report->len; | 125 | len = device->report_size > count ? count : device->report_size; |
126 | 126 | ||
127 | if (copy_to_user(buffer, report->value, len)) { | 127 | if (copy_to_user(buffer, report->value, len)) { |
128 | retval = -EFAULT; | 128 | retval = -EFAULT; |
@@ -165,27 +165,22 @@ static int roccat_open(struct inode *inode, struct file *file) | |||
165 | mutex_lock(&device->readers_lock); | 165 | mutex_lock(&device->readers_lock); |
166 | 166 | ||
167 | if (!device) { | 167 | if (!device) { |
168 | printk(KERN_EMERG "roccat device with minor %d doesn't exist\n", | 168 | pr_emerg("roccat device with minor %d doesn't exist\n", minor); |
169 | minor); | ||
170 | error = -ENODEV; | 169 | error = -ENODEV; |
171 | goto exit_err; | 170 | goto exit_err; |
172 | } | 171 | } |
173 | 172 | ||
174 | if (!device->open++) { | 173 | if (!device->open++) { |
175 | /* power on device on adding first reader */ | 174 | /* power on device on adding first reader */ |
176 | if (device->hid->ll_driver->power) { | 175 | error = hid_hw_power(device->hid, PM_HINT_FULLON); |
177 | error = device->hid->ll_driver->power(device->hid, | 176 | if (error < 0) { |
178 | PM_HINT_FULLON); | 177 | --device->open; |
179 | if (error < 0) { | 178 | goto exit_err; |
180 | --device->open; | ||
181 | goto exit_err; | ||
182 | } | ||
183 | } | 179 | } |
184 | error = device->hid->ll_driver->open(device->hid); | 180 | |
181 | error = hid_hw_open(device->hid); | ||
185 | if (error < 0) { | 182 | if (error < 0) { |
186 | if (device->hid->ll_driver->power) | 183 | hid_hw_power(device->hid, PM_HINT_NORMAL); |
187 | device->hid->ll_driver->power(device->hid, | ||
188 | PM_HINT_NORMAL); | ||
189 | --device->open; | 184 | --device->open; |
190 | goto exit_err; | 185 | goto exit_err; |
191 | } | 186 | } |
@@ -218,8 +213,7 @@ static int roccat_release(struct inode *inode, struct file *file) | |||
218 | device = devices[minor]; | 213 | device = devices[minor]; |
219 | if (!device) { | 214 | if (!device) { |
220 | mutex_unlock(&devices_lock); | 215 | mutex_unlock(&devices_lock); |
221 | printk(KERN_EMERG "roccat device with minor %d doesn't exist\n", | 216 | pr_emerg("roccat device with minor %d doesn't exist\n", minor); |
222 | minor); | ||
223 | return -ENODEV; | 217 | return -ENODEV; |
224 | } | 218 | } |
225 | 219 | ||
@@ -231,10 +225,8 @@ static int roccat_release(struct inode *inode, struct file *file) | |||
231 | if (!--device->open) { | 225 | if (!--device->open) { |
232 | /* removing last reader */ | 226 | /* removing last reader */ |
233 | if (device->exist) { | 227 | if (device->exist) { |
234 | if (device->hid->ll_driver->power) | 228 | hid_hw_power(device->hid, PM_HINT_NORMAL); |
235 | device->hid->ll_driver->power(device->hid, | 229 | hid_hw_close(device->hid); |
236 | PM_HINT_NORMAL); | ||
237 | device->hid->ll_driver->close(device->hid); | ||
238 | } else { | 230 | } else { |
239 | kfree(device); | 231 | kfree(device); |
240 | } | 232 | } |
@@ -255,26 +247,25 @@ static int roccat_release(struct inode *inode, struct file *file) | |||
255 | * | 247 | * |
256 | * This is called from interrupt handler. | 248 | * This is called from interrupt handler. |
257 | */ | 249 | */ |
258 | int roccat_report_event(int minor, u8 const *data, int len) | 250 | int roccat_report_event(int minor, u8 const *data) |
259 | { | 251 | { |
260 | struct roccat_device *device; | 252 | struct roccat_device *device; |
261 | struct roccat_reader *reader; | 253 | struct roccat_reader *reader; |
262 | struct roccat_report *report; | 254 | struct roccat_report *report; |
263 | uint8_t *new_value; | 255 | uint8_t *new_value; |
264 | 256 | ||
265 | new_value = kmemdup(data, len, GFP_ATOMIC); | 257 | device = devices[minor]; |
258 | |||
259 | new_value = kmemdup(data, device->report_size, GFP_ATOMIC); | ||
266 | if (!new_value) | 260 | if (!new_value) |
267 | return -ENOMEM; | 261 | return -ENOMEM; |
268 | 262 | ||
269 | device = devices[minor]; | ||
270 | |||
271 | report = &device->cbuf[device->cbuf_end]; | 263 | report = &device->cbuf[device->cbuf_end]; |
272 | 264 | ||
273 | /* passing NULL is safe */ | 265 | /* passing NULL is safe */ |
274 | kfree(report->value); | 266 | kfree(report->value); |
275 | 267 | ||
276 | report->value = new_value; | 268 | report->value = new_value; |
277 | report->len = len; | ||
278 | device->cbuf_end = (device->cbuf_end + 1) % ROCCAT_CBUF_SIZE; | 269 | device->cbuf_end = (device->cbuf_end + 1) % ROCCAT_CBUF_SIZE; |
279 | 270 | ||
280 | list_for_each_entry(reader, &device->readers, node) { | 271 | list_for_each_entry(reader, &device->readers, node) { |
@@ -295,12 +286,14 @@ EXPORT_SYMBOL_GPL(roccat_report_event); | |||
295 | 286 | ||
296 | /* | 287 | /* |
297 | * roccat_connect() - create a char device for special event output | 288 | * roccat_connect() - create a char device for special event output |
289 | * @class: the class thats used to create the device. Meant to hold device | ||
290 | * specific sysfs attributes. | ||
298 | * @hid: the hid device the char device should be connected to. | 291 | * @hid: the hid device the char device should be connected to. |
299 | * | 292 | * |
300 | * Return value is minor device number in Range [0, ROCCAT_MAX_DEVICES] on | 293 | * Return value is minor device number in Range [0, ROCCAT_MAX_DEVICES] on |
301 | * success, a negative error code on failure. | 294 | * success, a negative error code on failure. |
302 | */ | 295 | */ |
303 | int roccat_connect(struct hid_device *hid) | 296 | int roccat_connect(struct class *klass, struct hid_device *hid, int report_size) |
304 | { | 297 | { |
305 | unsigned int minor; | 298 | unsigned int minor; |
306 | struct roccat_device *device; | 299 | struct roccat_device *device; |
@@ -326,7 +319,7 @@ int roccat_connect(struct hid_device *hid) | |||
326 | return -EINVAL; | 319 | return -EINVAL; |
327 | } | 320 | } |
328 | 321 | ||
329 | device->dev = device_create(roccat_class, &hid->dev, | 322 | device->dev = device_create(klass, &hid->dev, |
330 | MKDEV(roccat_major, minor), NULL, | 323 | MKDEV(roccat_major, minor), NULL, |
331 | "%s%s%d", "roccat", hid->driver->name, minor); | 324 | "%s%s%d", "roccat", hid->driver->name, minor); |
332 | 325 | ||
@@ -348,6 +341,7 @@ int roccat_connect(struct hid_device *hid) | |||
348 | device->hid = hid; | 341 | device->hid = hid; |
349 | device->exist = 1; | 342 | device->exist = 1; |
350 | device->cbuf_end = 0; | 343 | device->cbuf_end = 0; |
344 | device->report_size = report_size; | ||
351 | 345 | ||
352 | return minor; | 346 | return minor; |
353 | } | 347 | } |
@@ -362,15 +356,18 @@ void roccat_disconnect(int minor) | |||
362 | 356 | ||
363 | mutex_lock(&devices_lock); | 357 | mutex_lock(&devices_lock); |
364 | device = devices[minor]; | 358 | device = devices[minor]; |
365 | devices[minor] = NULL; | ||
366 | mutex_unlock(&devices_lock); | 359 | mutex_unlock(&devices_lock); |
367 | 360 | ||
368 | device->exist = 0; /* TODO exist maybe not needed */ | 361 | device->exist = 0; /* TODO exist maybe not needed */ |
369 | 362 | ||
370 | device_destroy(roccat_class, MKDEV(roccat_major, minor)); | 363 | device_destroy(device->dev->class, MKDEV(roccat_major, minor)); |
371 | 364 | ||
365 | mutex_lock(&devices_lock); | ||
366 | devices[minor] = NULL; | ||
367 | mutex_unlock(&devices_lock); | ||
368 | |||
372 | if (device->open) { | 369 | if (device->open) { |
373 | device->hid->ll_driver->close(device->hid); | 370 | hid_hw_close(device->hid); |
374 | wake_up_interruptible(&device->wait); | 371 | wake_up_interruptible(&device->wait); |
375 | } else { | 372 | } else { |
376 | kfree(device); | 373 | kfree(device); |
@@ -378,12 +375,42 @@ void roccat_disconnect(int minor) | |||
378 | } | 375 | } |
379 | EXPORT_SYMBOL_GPL(roccat_disconnect); | 376 | EXPORT_SYMBOL_GPL(roccat_disconnect); |
380 | 377 | ||
378 | static long roccat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||
379 | { | ||
380 | struct inode *inode = file->f_path.dentry->d_inode; | ||
381 | struct roccat_device *device; | ||
382 | unsigned int minor = iminor(inode); | ||
383 | long retval = 0; | ||
384 | |||
385 | mutex_lock(&devices_lock); | ||
386 | |||
387 | device = devices[minor]; | ||
388 | if (!device) { | ||
389 | retval = -ENODEV; | ||
390 | goto out; | ||
391 | } | ||
392 | |||
393 | switch (cmd) { | ||
394 | case ROCCATIOCGREPSIZE: | ||
395 | if (put_user(device->report_size, (int __user *)arg)) | ||
396 | retval = -EFAULT; | ||
397 | break; | ||
398 | default: | ||
399 | retval = -ENOTTY; | ||
400 | } | ||
401 | out: | ||
402 | mutex_unlock(&devices_lock); | ||
403 | return retval; | ||
404 | } | ||
405 | |||
381 | static const struct file_operations roccat_ops = { | 406 | static const struct file_operations roccat_ops = { |
382 | .owner = THIS_MODULE, | 407 | .owner = THIS_MODULE, |
383 | .read = roccat_read, | 408 | .read = roccat_read, |
384 | .poll = roccat_poll, | 409 | .poll = roccat_poll, |
385 | .open = roccat_open, | 410 | .open = roccat_open, |
386 | .release = roccat_release, | 411 | .release = roccat_release, |
412 | .llseek = noop_llseek, | ||
413 | .unlocked_ioctl = roccat_ioctl, | ||
387 | }; | 414 | }; |
388 | 415 | ||
389 | static int __init roccat_init(void) | 416 | static int __init roccat_init(void) |
@@ -397,14 +424,7 @@ static int __init roccat_init(void) | |||
397 | roccat_major = MAJOR(dev_id); | 424 | roccat_major = MAJOR(dev_id); |
398 | 425 | ||
399 | if (retval < 0) { | 426 | if (retval < 0) { |
400 | printk(KERN_WARNING "roccat: can't get major number\n"); | 427 | pr_warn("can't get major number\n"); |
401 | return retval; | ||
402 | } | ||
403 | |||
404 | roccat_class = class_create(THIS_MODULE, "roccat"); | ||
405 | if (IS_ERR(roccat_class)) { | ||
406 | retval = PTR_ERR(roccat_class); | ||
407 | unregister_chrdev_region(dev_id, ROCCAT_MAX_DEVICES); | ||
408 | return retval; | 428 | return retval; |
409 | } | 429 | } |
410 | 430 | ||
@@ -419,7 +439,6 @@ static void __exit roccat_exit(void) | |||
419 | dev_t dev_id = MKDEV(roccat_major, 0); | 439 | dev_t dev_id = MKDEV(roccat_major, 0); |
420 | 440 | ||
421 | cdev_del(&roccat_cdev); | 441 | cdev_del(&roccat_cdev); |
422 | class_destroy(roccat_class); | ||
423 | unregister_chrdev_region(dev_id, ROCCAT_MAX_DEVICES); | 442 | unregister_chrdev_region(dev_id, ROCCAT_MAX_DEVICES); |
424 | } | 443 | } |
425 | 444 | ||
diff --git a/drivers/hid/hid-roccat.h b/drivers/hid/hid-roccat.h deleted file mode 100644 index 09e864e9f79d..000000000000 --- a/drivers/hid/hid-roccat.h +++ /dev/null | |||
@@ -1,31 +0,0 @@ | |||
1 | #ifndef __HID_ROCCAT_H | ||
2 | #define __HID_ROCCAT_H | ||
3 | |||
4 | /* | ||
5 | * Copyright (c) 2010 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/hid.h> | ||
16 | #include <linux/types.h> | ||
17 | |||
18 | #if defined(CONFIG_HID_ROCCAT) || defined(CONFIG_HID_ROCCAT_MODULE) | ||
19 | int roccat_connect(struct hid_device *hid); | ||
20 | void roccat_disconnect(int minor); | ||
21 | int roccat_report_event(int minor, u8 const *data, int len); | ||
22 | #else | ||
23 | static inline int roccat_connect(struct hid_device *hid) { return -1; } | ||
24 | static inline void roccat_disconnect(int minor) {} | ||
25 | static inline int roccat_report_event(int minor, u8 const *data, int len) | ||
26 | { | ||
27 | return 0; | ||
28 | } | ||
29 | #endif | ||
30 | |||
31 | #endif | ||
diff --git a/drivers/hid/hid-samsung.c b/drivers/hid/hid-samsung.c index bda0fd60c98d..3c1fd8af5e0c 100644 --- a/drivers/hid/hid-samsung.c +++ b/drivers/hid/hid-samsung.c | |||
@@ -57,14 +57,14 @@ | |||
57 | static inline void samsung_irda_dev_trace(struct hid_device *hdev, | 57 | static inline void samsung_irda_dev_trace(struct hid_device *hdev, |
58 | unsigned int rsize) | 58 | unsigned int rsize) |
59 | { | 59 | { |
60 | dev_info(&hdev->dev, "fixing up Samsung IrDA %d byte report " | 60 | hid_info(hdev, "fixing up Samsung IrDA %d byte report descriptor\n", |
61 | "descriptor\n", rsize); | 61 | rsize); |
62 | } | 62 | } |
63 | 63 | ||
64 | static void samsung_irda_report_fixup(struct hid_device *hdev, __u8 *rdesc, | 64 | static __u8 *samsung_irda_report_fixup(struct hid_device *hdev, __u8 *rdesc, |
65 | unsigned int rsize) | 65 | unsigned int *rsize) |
66 | { | 66 | { |
67 | if (rsize == 184 && rdesc[175] == 0x25 && rdesc[176] == 0x40 && | 67 | if (*rsize == 184 && rdesc[175] == 0x25 && rdesc[176] == 0x40 && |
68 | rdesc[177] == 0x75 && rdesc[178] == 0x30 && | 68 | rdesc[177] == 0x75 && rdesc[178] == 0x30 && |
69 | rdesc[179] == 0x95 && rdesc[180] == 0x01 && | 69 | rdesc[179] == 0x95 && rdesc[180] == 0x01 && |
70 | rdesc[182] == 0x40) { | 70 | rdesc[182] == 0x40) { |
@@ -74,24 +74,25 @@ static void samsung_irda_report_fixup(struct hid_device *hdev, __u8 *rdesc, | |||
74 | rdesc[180] = 0x06; | 74 | rdesc[180] = 0x06; |
75 | rdesc[182] = 0x42; | 75 | rdesc[182] = 0x42; |
76 | } else | 76 | } else |
77 | if (rsize == 203 && rdesc[192] == 0x15 && rdesc[193] == 0x0 && | 77 | if (*rsize == 203 && rdesc[192] == 0x15 && rdesc[193] == 0x0 && |
78 | rdesc[194] == 0x25 && rdesc[195] == 0x12) { | 78 | rdesc[194] == 0x25 && rdesc[195] == 0x12) { |
79 | samsung_irda_dev_trace(hdev, 203); | 79 | samsung_irda_dev_trace(hdev, 203); |
80 | rdesc[193] = 0x1; | 80 | rdesc[193] = 0x1; |
81 | rdesc[195] = 0xf; | 81 | rdesc[195] = 0xf; |
82 | } else | 82 | } else |
83 | if (rsize == 135 && rdesc[124] == 0x15 && rdesc[125] == 0x0 && | 83 | if (*rsize == 135 && rdesc[124] == 0x15 && rdesc[125] == 0x0 && |
84 | rdesc[126] == 0x25 && rdesc[127] == 0x11) { | 84 | rdesc[126] == 0x25 && rdesc[127] == 0x11) { |
85 | samsung_irda_dev_trace(hdev, 135); | 85 | samsung_irda_dev_trace(hdev, 135); |
86 | rdesc[125] = 0x1; | 86 | rdesc[125] = 0x1; |
87 | rdesc[127] = 0xe; | 87 | rdesc[127] = 0xe; |
88 | } else | 88 | } else |
89 | if (rsize == 171 && rdesc[160] == 0x15 && rdesc[161] == 0x0 && | 89 | if (*rsize == 171 && rdesc[160] == 0x15 && rdesc[161] == 0x0 && |
90 | rdesc[162] == 0x25 && rdesc[163] == 0x01) { | 90 | rdesc[162] == 0x25 && rdesc[163] == 0x01) { |
91 | samsung_irda_dev_trace(hdev, 171); | 91 | samsung_irda_dev_trace(hdev, 171); |
92 | rdesc[161] = 0x1; | 92 | rdesc[161] = 0x1; |
93 | rdesc[163] = 0x3; | 93 | rdesc[163] = 0x3; |
94 | } | 94 | } |
95 | return rdesc; | ||
95 | } | 96 | } |
96 | 97 | ||
97 | #define samsung_kbd_mouse_map_key_clear(c) \ | 98 | #define samsung_kbd_mouse_map_key_clear(c) \ |
@@ -130,11 +131,12 @@ static int samsung_kbd_mouse_input_mapping(struct hid_device *hdev, | |||
130 | return 1; | 131 | return 1; |
131 | } | 132 | } |
132 | 133 | ||
133 | static void samsung_report_fixup(struct hid_device *hdev, __u8 *rdesc, | 134 | static __u8 *samsung_report_fixup(struct hid_device *hdev, __u8 *rdesc, |
134 | unsigned int rsize) | 135 | unsigned int *rsize) |
135 | { | 136 | { |
136 | if (USB_DEVICE_ID_SAMSUNG_IR_REMOTE == hdev->product) | 137 | if (USB_DEVICE_ID_SAMSUNG_IR_REMOTE == hdev->product) |
137 | samsung_irda_report_fixup(hdev, rdesc, rsize); | 138 | rdesc = samsung_irda_report_fixup(hdev, rdesc, rsize); |
139 | return rdesc; | ||
138 | } | 140 | } |
139 | 141 | ||
140 | static int samsung_input_mapping(struct hid_device *hdev, struct hid_input *hi, | 142 | static int samsung_input_mapping(struct hid_device *hdev, struct hid_input *hi, |
@@ -158,7 +160,7 @@ static int samsung_probe(struct hid_device *hdev, | |||
158 | 160 | ||
159 | ret = hid_parse(hdev); | 161 | ret = hid_parse(hdev); |
160 | if (ret) { | 162 | if (ret) { |
161 | dev_err(&hdev->dev, "parse failed\n"); | 163 | hid_err(hdev, "parse failed\n"); |
162 | goto err_free; | 164 | goto err_free; |
163 | } | 165 | } |
164 | 166 | ||
@@ -172,7 +174,7 @@ static int samsung_probe(struct hid_device *hdev, | |||
172 | 174 | ||
173 | ret = hid_hw_start(hdev, cmask); | 175 | ret = hid_hw_start(hdev, cmask); |
174 | if (ret) { | 176 | if (ret) { |
175 | dev_err(&hdev->dev, "hw start failed\n"); | 177 | hid_err(hdev, "hw start failed\n"); |
176 | goto err_free; | 178 | goto err_free; |
177 | } | 179 | } |
178 | 180 | ||
diff --git a/drivers/hid/hid-sjoy.c b/drivers/hid/hid-sjoy.c index e10a7687ebf2..16f7cafc9695 100644 --- a/drivers/hid/hid-sjoy.c +++ b/drivers/hid/hid-sjoy.c | |||
@@ -74,26 +74,25 @@ static int sjoyff_init(struct hid_device *hid) | |||
74 | int error; | 74 | int error; |
75 | 75 | ||
76 | if (list_empty(report_list)) { | 76 | if (list_empty(report_list)) { |
77 | dev_err(&hid->dev, "no output reports found\n"); | 77 | hid_err(hid, "no output reports found\n"); |
78 | return -ENODEV; | 78 | return -ENODEV; |
79 | } | 79 | } |
80 | 80 | ||
81 | report_ptr = report_ptr->next; | 81 | report_ptr = report_ptr->next; |
82 | 82 | ||
83 | if (report_ptr == report_list) { | 83 | if (report_ptr == report_list) { |
84 | dev_err(&hid->dev, "required output report is " | 84 | hid_err(hid, "required output report is missing\n"); |
85 | "missing\n"); | ||
86 | return -ENODEV; | 85 | return -ENODEV; |
87 | } | 86 | } |
88 | 87 | ||
89 | report = list_entry(report_ptr, struct hid_report, list); | 88 | report = list_entry(report_ptr, struct hid_report, list); |
90 | if (report->maxfield < 1) { | 89 | if (report->maxfield < 1) { |
91 | dev_err(&hid->dev, "no fields in the report\n"); | 90 | hid_err(hid, "no fields in the report\n"); |
92 | return -ENODEV; | 91 | return -ENODEV; |
93 | } | 92 | } |
94 | 93 | ||
95 | if (report->field[0]->report_count < 3) { | 94 | if (report->field[0]->report_count < 3) { |
96 | dev_err(&hid->dev, "not enough values in the field\n"); | 95 | hid_err(hid, "not enough values in the field\n"); |
97 | return -ENODEV; | 96 | return -ENODEV; |
98 | } | 97 | } |
99 | 98 | ||
@@ -117,8 +116,7 @@ static int sjoyff_init(struct hid_device *hid) | |||
117 | sjoyff->report->field[0]->value[2] = 0x00; | 116 | sjoyff->report->field[0]->value[2] = 0x00; |
118 | usbhid_submit_report(hid, sjoyff->report, USB_DIR_OUT); | 117 | usbhid_submit_report(hid, sjoyff->report, USB_DIR_OUT); |
119 | 118 | ||
120 | dev_info(&hid->dev, | 119 | hid_info(hid, "Force feedback for SmartJoy PLUS PS2/USB adapter\n"); |
121 | "Force feedback for SmartJoy PLUS PS2/USB adapter\n"); | ||
122 | 120 | ||
123 | return 0; | 121 | return 0; |
124 | } | 122 | } |
@@ -135,13 +133,13 @@ static int sjoy_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
135 | 133 | ||
136 | ret = hid_parse(hdev); | 134 | ret = hid_parse(hdev); |
137 | if (ret) { | 135 | if (ret) { |
138 | dev_err(&hdev->dev, "parse failed\n"); | 136 | hid_err(hdev, "parse failed\n"); |
139 | goto err; | 137 | goto err; |
140 | } | 138 | } |
141 | 139 | ||
142 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); | 140 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); |
143 | if (ret) { | 141 | if (ret) { |
144 | dev_err(&hdev->dev, "hw start failed\n"); | 142 | hid_err(hdev, "hw start failed\n"); |
145 | goto err; | 143 | goto err; |
146 | } | 144 | } |
147 | 145 | ||
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 402d5574b574..936c911fdca6 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c | |||
@@ -24,24 +24,65 @@ | |||
24 | 24 | ||
25 | #include "hid-ids.h" | 25 | #include "hid-ids.h" |
26 | 26 | ||
27 | #define VAIO_RDESC_CONSTANT 0x0001 | 27 | #define VAIO_RDESC_CONSTANT (1 << 0) |
28 | #define SIXAXIS_CONTROLLER_USB (1 << 1) | ||
29 | #define SIXAXIS_CONTROLLER_BT (1 << 2) | ||
28 | 30 | ||
29 | struct sony_sc { | 31 | struct sony_sc { |
30 | unsigned long quirks; | 32 | unsigned long quirks; |
31 | }; | 33 | }; |
32 | 34 | ||
33 | /* Sony Vaio VGX has wrongly mouse pointer declared as constant */ | 35 | /* Sony Vaio VGX has wrongly mouse pointer declared as constant */ |
34 | static void sony_report_fixup(struct hid_device *hdev, __u8 *rdesc, | 36 | static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc, |
35 | unsigned int rsize) | 37 | unsigned int *rsize) |
36 | { | 38 | { |
37 | struct sony_sc *sc = hid_get_drvdata(hdev); | 39 | struct sony_sc *sc = hid_get_drvdata(hdev); |
38 | 40 | ||
39 | if ((sc->quirks & VAIO_RDESC_CONSTANT) && | 41 | if ((sc->quirks & VAIO_RDESC_CONSTANT) && |
40 | rsize >= 56 && rdesc[54] == 0x81 && rdesc[55] == 0x07) { | 42 | *rsize >= 56 && rdesc[54] == 0x81 && rdesc[55] == 0x07) { |
41 | dev_info(&hdev->dev, "Fixing up Sony Vaio VGX report " | 43 | hid_info(hdev, "Fixing up Sony Vaio VGX report descriptor\n"); |
42 | "descriptor\n"); | ||
43 | rdesc[55] = 0x06; | 44 | rdesc[55] = 0x06; |
44 | } | 45 | } |
46 | return rdesc; | ||
47 | } | ||
48 | |||
49 | /* | ||
50 | * The Sony Sixaxis does not handle HID Output Reports on the Interrupt EP | ||
51 | * like it should according to usbhid/hid-core.c::usbhid_output_raw_report() | ||
52 | * so we need to override that forcing HID Output Reports on the Control EP. | ||
53 | * | ||
54 | * There is also another issue about HID Output Reports via USB, the Sixaxis | ||
55 | * does not want the report_id as part of the data packet, so we have to | ||
56 | * discard buf[0] when sending the actual control message, even for numbered | ||
57 | * reports, humpf! | ||
58 | */ | ||
59 | static int sixaxis_usb_output_raw_report(struct hid_device *hid, __u8 *buf, | ||
60 | size_t count, unsigned char report_type) | ||
61 | { | ||
62 | struct usb_interface *intf = to_usb_interface(hid->dev.parent); | ||
63 | struct usb_device *dev = interface_to_usbdev(intf); | ||
64 | struct usb_host_interface *interface = intf->cur_altsetting; | ||
65 | int report_id = buf[0]; | ||
66 | int ret; | ||
67 | |||
68 | if (report_type == HID_OUTPUT_REPORT) { | ||
69 | /* Don't send the Report ID */ | ||
70 | buf++; | ||
71 | count--; | ||
72 | } | ||
73 | |||
74 | ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | ||
75 | HID_REQ_SET_REPORT, | ||
76 | USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, | ||
77 | ((report_type + 1) << 8) | report_id, | ||
78 | interface->desc.bInterfaceNumber, buf, count, | ||
79 | USB_CTRL_SET_TIMEOUT); | ||
80 | |||
81 | /* Count also the Report ID, in case of an Output report. */ | ||
82 | if (ret > 0 && report_type == HID_OUTPUT_REPORT) | ||
83 | ret++; | ||
84 | |||
85 | return ret; | ||
45 | } | 86 | } |
46 | 87 | ||
47 | /* | 88 | /* |
@@ -49,7 +90,7 @@ static void sony_report_fixup(struct hid_device *hdev, __u8 *rdesc, | |||
49 | * to "operational". Without this, the ps3 controller will not report any | 90 | * to "operational". Without this, the ps3 controller will not report any |
50 | * events. | 91 | * events. |
51 | */ | 92 | */ |
52 | static int sony_set_operational_usb(struct hid_device *hdev) | 93 | static int sixaxis_set_operational_usb(struct hid_device *hdev) |
53 | { | 94 | { |
54 | struct usb_interface *intf = to_usb_interface(hdev->dev.parent); | 95 | struct usb_interface *intf = to_usb_interface(hdev->dev.parent); |
55 | struct usb_device *dev = interface_to_usbdev(intf); | 96 | struct usb_device *dev = interface_to_usbdev(intf); |
@@ -67,14 +108,14 @@ static int sony_set_operational_usb(struct hid_device *hdev) | |||
67 | (3 << 8) | 0xf2, ifnum, buf, 17, | 108 | (3 << 8) | 0xf2, ifnum, buf, 17, |
68 | USB_CTRL_GET_TIMEOUT); | 109 | USB_CTRL_GET_TIMEOUT); |
69 | if (ret < 0) | 110 | if (ret < 0) |
70 | dev_err(&hdev->dev, "can't set operational mode\n"); | 111 | hid_err(hdev, "can't set operational mode\n"); |
71 | 112 | ||
72 | kfree(buf); | 113 | kfree(buf); |
73 | 114 | ||
74 | return ret; | 115 | return ret; |
75 | } | 116 | } |
76 | 117 | ||
77 | static int sony_set_operational_bt(struct hid_device *hdev) | 118 | static int sixaxis_set_operational_bt(struct hid_device *hdev) |
78 | { | 119 | { |
79 | unsigned char buf[] = { 0xf4, 0x42, 0x03, 0x00, 0x00 }; | 120 | unsigned char buf[] = { 0xf4, 0x42, 0x03, 0x00, 0x00 }; |
80 | return hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT); | 121 | return hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT); |
@@ -88,7 +129,7 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
88 | 129 | ||
89 | sc = kzalloc(sizeof(*sc), GFP_KERNEL); | 130 | sc = kzalloc(sizeof(*sc), GFP_KERNEL); |
90 | if (sc == NULL) { | 131 | if (sc == NULL) { |
91 | dev_err(&hdev->dev, "can't alloc sony descriptor\n"); | 132 | hid_err(hdev, "can't alloc sony descriptor\n"); |
92 | return -ENOMEM; | 133 | return -ENOMEM; |
93 | } | 134 | } |
94 | 135 | ||
@@ -97,27 +138,25 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
97 | 138 | ||
98 | ret = hid_parse(hdev); | 139 | ret = hid_parse(hdev); |
99 | if (ret) { | 140 | if (ret) { |
100 | dev_err(&hdev->dev, "parse failed\n"); | 141 | hid_err(hdev, "parse failed\n"); |
101 | goto err_free; | 142 | goto err_free; |
102 | } | 143 | } |
103 | 144 | ||
104 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT | | 145 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT | |
105 | HID_CONNECT_HIDDEV_FORCE); | 146 | HID_CONNECT_HIDDEV_FORCE); |
106 | if (ret) { | 147 | if (ret) { |
107 | dev_err(&hdev->dev, "hw start failed\n"); | 148 | hid_err(hdev, "hw start failed\n"); |
108 | goto err_free; | 149 | goto err_free; |
109 | } | 150 | } |
110 | 151 | ||
111 | switch (hdev->bus) { | 152 | if (sc->quirks & SIXAXIS_CONTROLLER_USB) { |
112 | case BUS_USB: | 153 | hdev->hid_output_raw_report = sixaxis_usb_output_raw_report; |
113 | ret = sony_set_operational_usb(hdev); | 154 | ret = sixaxis_set_operational_usb(hdev); |
114 | break; | ||
115 | case BUS_BLUETOOTH: | ||
116 | ret = sony_set_operational_bt(hdev); | ||
117 | break; | ||
118 | default: | ||
119 | ret = 0; | ||
120 | } | 155 | } |
156 | else if (sc->quirks & SIXAXIS_CONTROLLER_BT) | ||
157 | ret = sixaxis_set_operational_bt(hdev); | ||
158 | else | ||
159 | ret = 0; | ||
121 | 160 | ||
122 | if (ret < 0) | 161 | if (ret < 0) |
123 | goto err_stop; | 162 | goto err_stop; |
@@ -137,8 +176,12 @@ static void sony_remove(struct hid_device *hdev) | |||
137 | } | 176 | } |
138 | 177 | ||
139 | static const struct hid_device_id sony_devices[] = { | 178 | static const struct hid_device_id sony_devices[] = { |
140 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, | 179 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER), |
141 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, | 180 | .driver_data = SIXAXIS_CONTROLLER_USB }, |
181 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER), | ||
182 | .driver_data = SIXAXIS_CONTROLLER_USB }, | ||
183 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER), | ||
184 | .driver_data = SIXAXIS_CONTROLLER_BT }, | ||
142 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE), | 185 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE), |
143 | .driver_data = VAIO_RDESC_CONSTANT }, | 186 | .driver_data = VAIO_RDESC_CONSTANT }, |
144 | { } | 187 | { } |
diff --git a/drivers/hid/hid-stantum.c b/drivers/hid/hid-stantum.c deleted file mode 100644 index 90df886c5e04..000000000000 --- a/drivers/hid/hid-stantum.c +++ /dev/null | |||
@@ -1,284 +0,0 @@ | |||
1 | /* | ||
2 | * HID driver for Stantum multitouch panels | ||
3 | * | ||
4 | * Copyright (c) 2009 Stephane Chatty <chatty@enac.fr> | ||
5 | * | ||
6 | */ | ||
7 | |||
8 | /* | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the Free | ||
11 | * Software Foundation; either version 2 of the License, or (at your option) | ||
12 | * any later version. | ||
13 | */ | ||
14 | |||
15 | #include <linux/device.h> | ||
16 | #include <linux/hid.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/slab.h> | ||
19 | |||
20 | MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>"); | ||
21 | MODULE_DESCRIPTION("Stantum HID multitouch panels"); | ||
22 | MODULE_LICENSE("GPL"); | ||
23 | |||
24 | #include "hid-ids.h" | ||
25 | |||
26 | struct stantum_data { | ||
27 | __s32 x, y, z, w, h; /* x, y, pressure, width, height */ | ||
28 | __u16 id; /* touch id */ | ||
29 | bool valid; /* valid finger data, or just placeholder? */ | ||
30 | bool first; /* first finger in the HID packet? */ | ||
31 | bool activity; /* at least one active finger so far? */ | ||
32 | }; | ||
33 | |||
34 | static int stantum_input_mapping(struct hid_device *hdev, struct hid_input *hi, | ||
35 | struct hid_field *field, struct hid_usage *usage, | ||
36 | unsigned long **bit, int *max) | ||
37 | { | ||
38 | switch (usage->hid & HID_USAGE_PAGE) { | ||
39 | |||
40 | case HID_UP_GENDESK: | ||
41 | switch (usage->hid) { | ||
42 | case HID_GD_X: | ||
43 | hid_map_usage(hi, usage, bit, max, | ||
44 | EV_ABS, ABS_MT_POSITION_X); | ||
45 | /* touchscreen emulation */ | ||
46 | input_set_abs_params(hi->input, ABS_X, | ||
47 | field->logical_minimum, | ||
48 | field->logical_maximum, 0, 0); | ||
49 | return 1; | ||
50 | case HID_GD_Y: | ||
51 | hid_map_usage(hi, usage, bit, max, | ||
52 | EV_ABS, ABS_MT_POSITION_Y); | ||
53 | /* touchscreen emulation */ | ||
54 | input_set_abs_params(hi->input, ABS_Y, | ||
55 | field->logical_minimum, | ||
56 | field->logical_maximum, 0, 0); | ||
57 | return 1; | ||
58 | } | ||
59 | return 0; | ||
60 | |||
61 | case HID_UP_DIGITIZER: | ||
62 | switch (usage->hid) { | ||
63 | case HID_DG_INRANGE: | ||
64 | case HID_DG_CONFIDENCE: | ||
65 | case HID_DG_INPUTMODE: | ||
66 | case HID_DG_DEVICEINDEX: | ||
67 | case HID_DG_CONTACTCOUNT: | ||
68 | case HID_DG_CONTACTMAX: | ||
69 | return -1; | ||
70 | |||
71 | case HID_DG_TIPSWITCH: | ||
72 | /* touchscreen emulation */ | ||
73 | hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); | ||
74 | return 1; | ||
75 | |||
76 | case HID_DG_WIDTH: | ||
77 | hid_map_usage(hi, usage, bit, max, | ||
78 | EV_ABS, ABS_MT_TOUCH_MAJOR); | ||
79 | return 1; | ||
80 | case HID_DG_HEIGHT: | ||
81 | hid_map_usage(hi, usage, bit, max, | ||
82 | EV_ABS, ABS_MT_TOUCH_MINOR); | ||
83 | input_set_abs_params(hi->input, ABS_MT_ORIENTATION, | ||
84 | 1, 1, 0, 0); | ||
85 | return 1; | ||
86 | case HID_DG_TIPPRESSURE: | ||
87 | hid_map_usage(hi, usage, bit, max, | ||
88 | EV_ABS, ABS_MT_PRESSURE); | ||
89 | return 1; | ||
90 | |||
91 | case HID_DG_CONTACTID: | ||
92 | hid_map_usage(hi, usage, bit, max, | ||
93 | EV_ABS, ABS_MT_TRACKING_ID); | ||
94 | return 1; | ||
95 | |||
96 | } | ||
97 | return 0; | ||
98 | |||
99 | case 0xff000000: | ||
100 | /* no input-oriented meaning */ | ||
101 | return -1; | ||
102 | } | ||
103 | |||
104 | return 0; | ||
105 | } | ||
106 | |||
107 | static int stantum_input_mapped(struct hid_device *hdev, struct hid_input *hi, | ||
108 | struct hid_field *field, struct hid_usage *usage, | ||
109 | unsigned long **bit, int *max) | ||
110 | { | ||
111 | if (usage->type == EV_KEY || usage->type == EV_ABS) | ||
112 | clear_bit(usage->code, *bit); | ||
113 | |||
114 | return 0; | ||
115 | } | ||
116 | |||
117 | /* | ||
118 | * this function is called when a whole finger has been parsed, | ||
119 | * so that it can decide what to send to the input layer. | ||
120 | */ | ||
121 | static void stantum_filter_event(struct stantum_data *sd, | ||
122 | struct input_dev *input) | ||
123 | { | ||
124 | bool wide; | ||
125 | |||
126 | if (!sd->valid) { | ||
127 | /* | ||
128 | * touchscreen emulation: if the first finger is not valid and | ||
129 | * there previously was finger activity, this is a release | ||
130 | */ | ||
131 | if (sd->first && sd->activity) { | ||
132 | input_event(input, EV_KEY, BTN_TOUCH, 0); | ||
133 | sd->activity = false; | ||
134 | } | ||
135 | return; | ||
136 | } | ||
137 | |||
138 | input_event(input, EV_ABS, ABS_MT_TRACKING_ID, sd->id); | ||
139 | input_event(input, EV_ABS, ABS_MT_POSITION_X, sd->x); | ||
140 | input_event(input, EV_ABS, ABS_MT_POSITION_Y, sd->y); | ||
141 | |||
142 | wide = (sd->w > sd->h); | ||
143 | input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide); | ||
144 | input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, wide ? sd->w : sd->h); | ||
145 | input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, wide ? sd->h : sd->w); | ||
146 | |||
147 | input_event(input, EV_ABS, ABS_MT_PRESSURE, sd->z); | ||
148 | |||
149 | input_mt_sync(input); | ||
150 | sd->valid = false; | ||
151 | |||
152 | /* touchscreen emulation */ | ||
153 | if (sd->first) { | ||
154 | if (!sd->activity) { | ||
155 | input_event(input, EV_KEY, BTN_TOUCH, 1); | ||
156 | sd->activity = true; | ||
157 | } | ||
158 | input_event(input, EV_ABS, ABS_X, sd->x); | ||
159 | input_event(input, EV_ABS, ABS_Y, sd->y); | ||
160 | } | ||
161 | sd->first = false; | ||
162 | } | ||
163 | |||
164 | |||
165 | static int stantum_event(struct hid_device *hid, struct hid_field *field, | ||
166 | struct hid_usage *usage, __s32 value) | ||
167 | { | ||
168 | struct stantum_data *sd = hid_get_drvdata(hid); | ||
169 | |||
170 | if (hid->claimed & HID_CLAIMED_INPUT) { | ||
171 | struct input_dev *input = field->hidinput->input; | ||
172 | |||
173 | switch (usage->hid) { | ||
174 | case HID_DG_INRANGE: | ||
175 | /* this is the last field in a finger */ | ||
176 | stantum_filter_event(sd, input); | ||
177 | break; | ||
178 | case HID_DG_WIDTH: | ||
179 | sd->w = value; | ||
180 | break; | ||
181 | case HID_DG_HEIGHT: | ||
182 | sd->h = value; | ||
183 | break; | ||
184 | case HID_GD_X: | ||
185 | sd->x = value; | ||
186 | break; | ||
187 | case HID_GD_Y: | ||
188 | sd->y = value; | ||
189 | break; | ||
190 | case HID_DG_TIPPRESSURE: | ||
191 | sd->z = value; | ||
192 | break; | ||
193 | case HID_DG_CONTACTID: | ||
194 | sd->id = value; | ||
195 | break; | ||
196 | case HID_DG_CONFIDENCE: | ||
197 | sd->valid = !!value; | ||
198 | break; | ||
199 | case 0xff000002: | ||
200 | /* this comes only before the first finger */ | ||
201 | sd->first = true; | ||
202 | break; | ||
203 | |||
204 | default: | ||
205 | /* ignore the others */ | ||
206 | return 1; | ||
207 | } | ||
208 | } | ||
209 | |||
210 | /* we have handled the hidinput part, now remains hiddev */ | ||
211 | if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event) | ||
212 | hid->hiddev_hid_event(hid, field, usage, value); | ||
213 | |||
214 | return 1; | ||
215 | } | ||
216 | |||
217 | static int stantum_probe(struct hid_device *hdev, | ||
218 | const struct hid_device_id *id) | ||
219 | { | ||
220 | int ret; | ||
221 | struct stantum_data *sd; | ||
222 | |||
223 | sd = kmalloc(sizeof(struct stantum_data), GFP_KERNEL); | ||
224 | if (!sd) { | ||
225 | dev_err(&hdev->dev, "cannot allocate Stantum data\n"); | ||
226 | return -ENOMEM; | ||
227 | } | ||
228 | sd->valid = false; | ||
229 | sd->first = false; | ||
230 | sd->activity = false; | ||
231 | hid_set_drvdata(hdev, sd); | ||
232 | |||
233 | ret = hid_parse(hdev); | ||
234 | if (!ret) | ||
235 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); | ||
236 | |||
237 | if (ret) | ||
238 | kfree(sd); | ||
239 | |||
240 | return ret; | ||
241 | } | ||
242 | |||
243 | static void stantum_remove(struct hid_device *hdev) | ||
244 | { | ||
245 | hid_hw_stop(hdev); | ||
246 | kfree(hid_get_drvdata(hdev)); | ||
247 | hid_set_drvdata(hdev, NULL); | ||
248 | } | ||
249 | |||
250 | static const struct hid_device_id stantum_devices[] = { | ||
251 | { HID_USB_DEVICE(USB_VENDOR_ID_STANTUM, USB_DEVICE_ID_MTP) }, | ||
252 | { } | ||
253 | }; | ||
254 | MODULE_DEVICE_TABLE(hid, stantum_devices); | ||
255 | |||
256 | static const struct hid_usage_id stantum_grabbed_usages[] = { | ||
257 | { HID_ANY_ID, HID_ANY_ID, HID_ANY_ID }, | ||
258 | { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1} | ||
259 | }; | ||
260 | |||
261 | static struct hid_driver stantum_driver = { | ||
262 | .name = "stantum", | ||
263 | .id_table = stantum_devices, | ||
264 | .probe = stantum_probe, | ||
265 | .remove = stantum_remove, | ||
266 | .input_mapping = stantum_input_mapping, | ||
267 | .input_mapped = stantum_input_mapped, | ||
268 | .usage_table = stantum_grabbed_usages, | ||
269 | .event = stantum_event, | ||
270 | }; | ||
271 | |||
272 | static int __init stantum_init(void) | ||
273 | { | ||
274 | return hid_register_driver(&stantum_driver); | ||
275 | } | ||
276 | |||
277 | static void __exit stantum_exit(void) | ||
278 | { | ||
279 | hid_unregister_driver(&stantum_driver); | ||
280 | } | ||
281 | |||
282 | module_init(stantum_init); | ||
283 | module_exit(stantum_exit); | ||
284 | |||
diff --git a/drivers/hid/hid-sunplus.c b/drivers/hid/hid-sunplus.c index 438107d9f1b2..d484a0043dd4 100644 --- a/drivers/hid/hid-sunplus.c +++ b/drivers/hid/hid-sunplus.c | |||
@@ -22,16 +22,16 @@ | |||
22 | 22 | ||
23 | #include "hid-ids.h" | 23 | #include "hid-ids.h" |
24 | 24 | ||
25 | static void sp_report_fixup(struct hid_device *hdev, __u8 *rdesc, | 25 | static __u8 *sp_report_fixup(struct hid_device *hdev, __u8 *rdesc, |
26 | unsigned int rsize) | 26 | unsigned int *rsize) |
27 | { | 27 | { |
28 | if (rsize >= 107 && rdesc[104] == 0x26 && rdesc[105] == 0x80 && | 28 | if (*rsize >= 107 && rdesc[104] == 0x26 && rdesc[105] == 0x80 && |
29 | rdesc[106] == 0x03) { | 29 | rdesc[106] == 0x03) { |
30 | dev_info(&hdev->dev, "fixing up Sunplus Wireless Desktop " | 30 | hid_info(hdev, "fixing up Sunplus Wireless Desktop report descriptor\n"); |
31 | "report descriptor\n"); | ||
32 | rdesc[105] = rdesc[110] = 0x03; | 31 | rdesc[105] = rdesc[110] = 0x03; |
33 | rdesc[106] = rdesc[111] = 0x21; | 32 | rdesc[106] = rdesc[111] = 0x21; |
34 | } | 33 | } |
34 | return rdesc; | ||
35 | } | 35 | } |
36 | 36 | ||
37 | #define sp_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ | 37 | #define sp_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ |
diff --git a/drivers/hid/hid-tmff.c b/drivers/hid/hid-tmff.c index 15434c814793..575862b0688e 100644 --- a/drivers/hid/hid-tmff.c +++ b/drivers/hid/hid-tmff.c | |||
@@ -151,28 +151,23 @@ static int tmff_init(struct hid_device *hid, const signed short *ff_bits) | |||
151 | switch (field->usage[0].hid) { | 151 | switch (field->usage[0].hid) { |
152 | case THRUSTMASTER_USAGE_FF: | 152 | case THRUSTMASTER_USAGE_FF: |
153 | if (field->report_count < 2) { | 153 | if (field->report_count < 2) { |
154 | dev_warn(&hid->dev, "ignoring FF field " | 154 | hid_warn(hid, "ignoring FF field with report_count < 2\n"); |
155 | "with report_count < 2\n"); | ||
156 | continue; | 155 | continue; |
157 | } | 156 | } |
158 | 157 | ||
159 | if (field->logical_maximum == | 158 | if (field->logical_maximum == |
160 | field->logical_minimum) { | 159 | field->logical_minimum) { |
161 | dev_warn(&hid->dev, "ignoring FF field " | 160 | hid_warn(hid, "ignoring FF field with logical_maximum == logical_minimum\n"); |
162 | "with logical_maximum " | ||
163 | "== logical_minimum\n"); | ||
164 | continue; | 161 | continue; |
165 | } | 162 | } |
166 | 163 | ||
167 | if (tmff->report && tmff->report != report) { | 164 | if (tmff->report && tmff->report != report) { |
168 | dev_warn(&hid->dev, "ignoring FF field " | 165 | hid_warn(hid, "ignoring FF field in other report\n"); |
169 | "in other report\n"); | ||
170 | continue; | 166 | continue; |
171 | } | 167 | } |
172 | 168 | ||
173 | if (tmff->ff_field && tmff->ff_field != field) { | 169 | if (tmff->ff_field && tmff->ff_field != field) { |
174 | dev_warn(&hid->dev, "ignoring " | 170 | hid_warn(hid, "ignoring duplicate FF field\n"); |
175 | "duplicate FF field\n"); | ||
176 | continue; | 171 | continue; |
177 | } | 172 | } |
178 | 173 | ||
@@ -185,16 +180,15 @@ static int tmff_init(struct hid_device *hid, const signed short *ff_bits) | |||
185 | break; | 180 | break; |
186 | 181 | ||
187 | default: | 182 | default: |
188 | dev_warn(&hid->dev, "ignoring unknown output " | 183 | hid_warn(hid, "ignoring unknown output usage %08x\n", |
189 | "usage %08x\n", | 184 | field->usage[0].hid); |
190 | field->usage[0].hid); | ||
191 | continue; | 185 | continue; |
192 | } | 186 | } |
193 | } | 187 | } |
194 | } | 188 | } |
195 | 189 | ||
196 | if (!tmff->report) { | 190 | if (!tmff->report) { |
197 | dev_err(&hid->dev, "can't find FF field in output reports\n"); | 191 | hid_err(hid, "can't find FF field in output reports\n"); |
198 | error = -ENODEV; | 192 | error = -ENODEV; |
199 | goto fail; | 193 | goto fail; |
200 | } | 194 | } |
@@ -203,8 +197,7 @@ static int tmff_init(struct hid_device *hid, const signed short *ff_bits) | |||
203 | if (error) | 197 | if (error) |
204 | goto fail; | 198 | goto fail; |
205 | 199 | ||
206 | dev_info(&hid->dev, "force feedback for ThrustMaster devices by Zinx " | 200 | hid_info(hid, "force feedback for ThrustMaster devices by Zinx Verituse <zinx@epicsol.org>\n"); |
207 | "Verituse <zinx@epicsol.org>"); | ||
208 | return 0; | 201 | return 0; |
209 | 202 | ||
210 | fail: | 203 | fail: |
@@ -224,13 +217,13 @@ static int tm_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
224 | 217 | ||
225 | ret = hid_parse(hdev); | 218 | ret = hid_parse(hdev); |
226 | if (ret) { | 219 | if (ret) { |
227 | dev_err(&hdev->dev, "parse failed\n"); | 220 | hid_err(hdev, "parse failed\n"); |
228 | goto err; | 221 | goto err; |
229 | } | 222 | } |
230 | 223 | ||
231 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); | 224 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); |
232 | if (ret) { | 225 | if (ret) { |
233 | dev_err(&hdev->dev, "hw start failed\n"); | 226 | hid_err(hdev, "hw start failed\n"); |
234 | goto err; | 227 | goto err; |
235 | } | 228 | } |
236 | 229 | ||
@@ -256,6 +249,8 @@ static const struct hid_device_id tm_devices[] = { | |||
256 | .driver_data = (unsigned long)ff_joystick }, | 249 | .driver_data = (unsigned long)ff_joystick }, |
257 | { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb654), /* FGT Force Feedback Wheel */ | 250 | { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb654), /* FGT Force Feedback Wheel */ |
258 | .driver_data = (unsigned long)ff_joystick }, | 251 | .driver_data = (unsigned long)ff_joystick }, |
252 | { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb65a), /* F430 Force Feedback Wheel */ | ||
253 | .driver_data = (unsigned long)ff_joystick }, | ||
259 | { } | 254 | { } |
260 | }; | 255 | }; |
261 | MODULE_DEVICE_TABLE(hid, tm_devices); | 256 | MODULE_DEVICE_TABLE(hid, tm_devices); |
diff --git a/drivers/hid/hid-topseed.c b/drivers/hid/hid-topseed.c index 956ed9ac19d4..613ff7b1d746 100644 --- a/drivers/hid/hid-topseed.c +++ b/drivers/hid/hid-topseed.c | |||
@@ -66,6 +66,7 @@ static const struct hid_device_id ts_devices[] = { | |||
66 | { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) }, | 66 | { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) }, |
67 | { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) }, | 67 | { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) }, |
68 | { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED2, USB_DEVICE_ID_TOPSEED2_RF_COMBO) }, | 68 | { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED2, USB_DEVICE_ID_TOPSEED2_RF_COMBO) }, |
69 | { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS) }, | ||
69 | { } | 70 | { } |
70 | }; | 71 | }; |
71 | MODULE_DEVICE_TABLE(hid, ts_devices); | 72 | MODULE_DEVICE_TABLE(hid, ts_devices); |
diff --git a/drivers/hid/hid-uclogic.c b/drivers/hid/hid-uclogic.c new file mode 100644 index 000000000000..05fdc85a76e5 --- /dev/null +++ b/drivers/hid/hid-uclogic.c | |||
@@ -0,0 +1,623 @@ | |||
1 | /* | ||
2 | * HID driver for UC-Logic devices not fully compliant with HID standard | ||
3 | * | ||
4 | * Copyright (c) 2010 Nikolai Kondrashov | ||
5 | */ | ||
6 | |||
7 | /* | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the Free | ||
10 | * Software Foundation; either version 2 of the License, or (at your option) | ||
11 | * any later version. | ||
12 | */ | ||
13 | |||
14 | #include <linux/device.h> | ||
15 | #include <linux/hid.h> | ||
16 | #include <linux/module.h> | ||
17 | |||
18 | #include "hid-ids.h" | ||
19 | |||
20 | /* | ||
21 | * The original descriptors of WPXXXXU tablets have three report IDs, of | ||
22 | * which only two are used (8 and 9), and the remaining (7) seems to have | ||
23 | * the originally intended pen description which was abandoned for some | ||
24 | * reason. From this unused description it is possible to extract the | ||
25 | * actual physical extents and resolution. All the models use the same | ||
26 | * descriptor with different extents for the unused report ID. | ||
27 | * | ||
28 | * Here it is: | ||
29 | * | ||
30 | * Usage Page (Digitizer), ; Digitizer (0Dh) | ||
31 | * Usage (Pen), ; Pen (02h, application collection) | ||
32 | * Collection (Application), | ||
33 | * Report ID (7), | ||
34 | * Usage (Stylus), ; Stylus (20h, logical collection) | ||
35 | * Collection (Physical), | ||
36 | * Usage (Tip Switch), ; Tip switch (42h, momentary control) | ||
37 | * Usage (Barrel Switch), ; Barrel switch (44h, momentary control) | ||
38 | * Usage (Eraser), ; Eraser (45h, momentary control) | ||
39 | * Logical Minimum (0), | ||
40 | * Logical Maximum (1), | ||
41 | * Report Size (1), | ||
42 | * Report Count (3), | ||
43 | * Input (Variable), | ||
44 | * Report Count (3), | ||
45 | * Input (Constant, Variable), | ||
46 | * Usage (In Range), ; In range (32h, momentary control) | ||
47 | * Report Count (1), | ||
48 | * Input (Variable), | ||
49 | * Report Count (1), | ||
50 | * Input (Constant, Variable), | ||
51 | * Usage Page (Desktop), ; Generic desktop controls (01h) | ||
52 | * Usage (X), ; X (30h, dynamic value) | ||
53 | * Report Size (16), | ||
54 | * Report Count (1), | ||
55 | * Push, | ||
56 | * Unit Exponent (13), | ||
57 | * Unit (Inch^3), | ||
58 | * Physical Minimum (0), | ||
59 | * Physical Maximum (Xpm), | ||
60 | * Logical Maximum (Xlm), | ||
61 | * Input (Variable), | ||
62 | * Usage (Y), ; Y (31h, dynamic value) | ||
63 | * Physical Maximum (Ypm), | ||
64 | * Logical Maximum (Ylm), | ||
65 | * Input (Variable), | ||
66 | * Pop, | ||
67 | * Usage Page (Digitizer), ; Digitizer (0Dh) | ||
68 | * Usage (Tip Pressure), ; Tip pressure (30h, dynamic value) | ||
69 | * Logical Maximum (1023), | ||
70 | * Input (Variable), | ||
71 | * Report Size (16), | ||
72 | * End Collection, | ||
73 | * End Collection, | ||
74 | * Usage Page (Desktop), ; Generic desktop controls (01h) | ||
75 | * Usage (Mouse), ; Mouse (02h, application collection) | ||
76 | * Collection (Application), | ||
77 | * Report ID (8), | ||
78 | * Usage (Pointer), ; Pointer (01h, physical collection) | ||
79 | * Collection (Physical), | ||
80 | * Usage Page (Button), ; Button (09h) | ||
81 | * Usage Minimum (01h), | ||
82 | * Usage Maximum (03h), | ||
83 | * Logical Minimum (0), | ||
84 | * Logical Maximum (1), | ||
85 | * Report Count (3), | ||
86 | * Report Size (1), | ||
87 | * Input (Variable), | ||
88 | * Report Count (5), | ||
89 | * Input (Constant), | ||
90 | * Usage Page (Desktop), ; Generic desktop controls (01h) | ||
91 | * Usage (X), ; X (30h, dynamic value) | ||
92 | * Usage (Y), ; Y (31h, dynamic value) | ||
93 | * Usage (Wheel), ; Wheel (38h, dynamic value) | ||
94 | * Usage (00h), | ||
95 | * Logical Minimum (-127), | ||
96 | * Logical Maximum (127), | ||
97 | * Report Size (8), | ||
98 | * Report Count (4), | ||
99 | * Input (Variable, Relative), | ||
100 | * End Collection, | ||
101 | * End Collection, | ||
102 | * Usage Page (Desktop), ; Generic desktop controls (01h) | ||
103 | * Usage (Mouse), ; Mouse (02h, application collection) | ||
104 | * Collection (Application), | ||
105 | * Report ID (9), | ||
106 | * Usage (Pointer), ; Pointer (01h, physical collection) | ||
107 | * Collection (Physical), | ||
108 | * Usage Page (Button), ; Button (09h) | ||
109 | * Usage Minimum (01h), | ||
110 | * Usage Maximum (03h), | ||
111 | * Logical Minimum (0), | ||
112 | * Logical Maximum (1), | ||
113 | * Report Count (3), | ||
114 | * Report Size (1), | ||
115 | * Input (Variable), | ||
116 | * Report Count (5), | ||
117 | * Input (Constant), | ||
118 | * Usage Page (Desktop), ; Generic desktop controls (01h) | ||
119 | * Usage (X), ; X (30h, dynamic value) | ||
120 | * Usage (Y), ; Y (31h, dynamic value) | ||
121 | * Logical Minimum (0), | ||
122 | * Logical Maximum (32767), | ||
123 | * Physical Minimum (0), | ||
124 | * Physical Maximum (32767), | ||
125 | * Report Count (2), | ||
126 | * Report Size (16), | ||
127 | * Input (Variable), | ||
128 | * Usage Page (Digitizer), ; Digitizer (0Dh) | ||
129 | * Usage (Tip Pressure), ; Tip pressure (30h, dynamic value) | ||
130 | * Logical Maximum (1023), | ||
131 | * Report Count (1), | ||
132 | * Report Size (16), | ||
133 | * Input (Variable), | ||
134 | * End Collection, | ||
135 | * End Collection | ||
136 | * | ||
137 | * Here are the extents values for the WPXXXXU models: | ||
138 | * | ||
139 | * Xpm Xlm Ypm Ylm | ||
140 | * WP4030U 4000 8000 3000 6000 | ||
141 | * WP5540U 5500 11000 4000 8000 | ||
142 | * WP8060U 8000 16000 6000 12000 | ||
143 | * | ||
144 | * This suggests that all of them have 2000 LPI resolution, as advertised. | ||
145 | */ | ||
146 | |||
147 | /* Size of the original descriptor of WPXXXXU tablets */ | ||
148 | #define WPXXXXU_RDESC_ORIG_SIZE 212 | ||
149 | |||
150 | /* | ||
151 | * Fixed WP4030U report descriptor. | ||
152 | * Although the hardware might actually support it, the mouse description | ||
153 | * has been removed, since there seems to be no devices having one and it | ||
154 | * wouldn't make much sense because of the working area size. | ||
155 | */ | ||
156 | static __u8 wp4030u_rdesc_fixed[] = { | ||
157 | 0x05, 0x0D, /* Usage Page (Digitizer), */ | ||
158 | 0x09, 0x02, /* Usage (Pen), */ | ||
159 | 0xA1, 0x01, /* Collection (Application), */ | ||
160 | 0x85, 0x09, /* Report ID (9), */ | ||
161 | 0x09, 0x20, /* Usage (Stylus), */ | ||
162 | 0xA0, /* Collection (Physical), */ | ||
163 | 0x75, 0x01, /* Report Size (1), */ | ||
164 | 0x09, 0x42, /* Usage (Tip Switch), */ | ||
165 | 0x09, 0x44, /* Usage (Barrel Switch), */ | ||
166 | 0x09, 0x46, /* Usage (Tablet Pick), */ | ||
167 | 0x14, /* Logical Minimum (0), */ | ||
168 | 0x25, 0x01, /* Logical Maximum (1), */ | ||
169 | 0x95, 0x03, /* Report Count (3), */ | ||
170 | 0x81, 0x02, /* Input (Variable), */ | ||
171 | 0x95, 0x05, /* Report Count (5), */ | ||
172 | 0x81, 0x01, /* Input (Constant), */ | ||
173 | 0x75, 0x10, /* Report Size (16), */ | ||
174 | 0x95, 0x01, /* Report Count (1), */ | ||
175 | 0x14, /* Logical Minimum (0), */ | ||
176 | 0xA4, /* Push, */ | ||
177 | 0x05, 0x01, /* Usage Page (Desktop), */ | ||
178 | 0x55, 0xFD, /* Unit Exponent (-3), */ | ||
179 | 0x65, 0x13, /* Unit (Inch), */ | ||
180 | 0x34, /* Physical Minimum (0), */ | ||
181 | 0x09, 0x30, /* Usage (X), */ | ||
182 | 0x46, 0xA0, 0x0F, /* Physical Maximum (4000), */ | ||
183 | 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ | ||
184 | 0x81, 0x02, /* Input (Variable), */ | ||
185 | 0x09, 0x31, /* Usage (Y), */ | ||
186 | 0x46, 0xB8, 0x0B, /* Physical Maximum (3000), */ | ||
187 | 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ | ||
188 | 0x81, 0x02, /* Input (Variable), */ | ||
189 | 0xB4, /* Pop, */ | ||
190 | 0x09, 0x30, /* Usage (Tip Pressure), */ | ||
191 | 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ | ||
192 | 0x81, 0x02, /* Input (Variable), */ | ||
193 | 0xC0, /* End Collection, */ | ||
194 | 0xC0 /* End Collection */ | ||
195 | }; | ||
196 | |||
197 | /* Fixed WP5540U report descriptor */ | ||
198 | static __u8 wp5540u_rdesc_fixed[] = { | ||
199 | 0x05, 0x0D, /* Usage Page (Digitizer), */ | ||
200 | 0x09, 0x02, /* Usage (Pen), */ | ||
201 | 0xA1, 0x01, /* Collection (Application), */ | ||
202 | 0x85, 0x09, /* Report ID (9), */ | ||
203 | 0x09, 0x20, /* Usage (Stylus), */ | ||
204 | 0xA0, /* Collection (Physical), */ | ||
205 | 0x75, 0x01, /* Report Size (1), */ | ||
206 | 0x09, 0x42, /* Usage (Tip Switch), */ | ||
207 | 0x09, 0x44, /* Usage (Barrel Switch), */ | ||
208 | 0x09, 0x46, /* Usage (Tablet Pick), */ | ||
209 | 0x14, /* Logical Minimum (0), */ | ||
210 | 0x25, 0x01, /* Logical Maximum (1), */ | ||
211 | 0x95, 0x03, /* Report Count (3), */ | ||
212 | 0x81, 0x02, /* Input (Variable), */ | ||
213 | 0x95, 0x05, /* Report Count (5), */ | ||
214 | 0x81, 0x01, /* Input (Constant), */ | ||
215 | 0x75, 0x10, /* Report Size (16), */ | ||
216 | 0x95, 0x01, /* Report Count (1), */ | ||
217 | 0x14, /* Logical Minimum (0), */ | ||
218 | 0xA4, /* Push, */ | ||
219 | 0x05, 0x01, /* Usage Page (Desktop), */ | ||
220 | 0x55, 0xFD, /* Unit Exponent (-3), */ | ||
221 | 0x65, 0x13, /* Unit (Inch), */ | ||
222 | 0x34, /* Physical Minimum (0), */ | ||
223 | 0x09, 0x30, /* Usage (X), */ | ||
224 | 0x46, 0x7C, 0x15, /* Physical Maximum (5500), */ | ||
225 | 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ | ||
226 | 0x81, 0x02, /* Input (Variable), */ | ||
227 | 0x09, 0x31, /* Usage (Y), */ | ||
228 | 0x46, 0xA0, 0x0F, /* Physical Maximum (4000), */ | ||
229 | 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ | ||
230 | 0x81, 0x02, /* Input (Variable), */ | ||
231 | 0xB4, /* Pop, */ | ||
232 | 0x09, 0x30, /* Usage (Tip Pressure), */ | ||
233 | 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ | ||
234 | 0x81, 0x02, /* Input (Variable), */ | ||
235 | 0xC0, /* End Collection, */ | ||
236 | 0xC0, /* End Collection, */ | ||
237 | 0x05, 0x01, /* Usage Page (Desktop), */ | ||
238 | 0x09, 0x02, /* Usage (Mouse), */ | ||
239 | 0xA1, 0x01, /* Collection (Application), */ | ||
240 | 0x85, 0x08, /* Report ID (8), */ | ||
241 | 0x09, 0x01, /* Usage (Pointer), */ | ||
242 | 0xA0, /* Collection (Physical), */ | ||
243 | 0x75, 0x01, /* Report Size (1), */ | ||
244 | 0x05, 0x09, /* Usage Page (Button), */ | ||
245 | 0x19, 0x01, /* Usage Minimum (01h), */ | ||
246 | 0x29, 0x03, /* Usage Maximum (03h), */ | ||
247 | 0x14, /* Logical Minimum (0), */ | ||
248 | 0x25, 0x01, /* Logical Maximum (1), */ | ||
249 | 0x95, 0x03, /* Report Count (3), */ | ||
250 | 0x81, 0x02, /* Input (Variable), */ | ||
251 | 0x95, 0x05, /* Report Count (5), */ | ||
252 | 0x81, 0x01, /* Input (Constant), */ | ||
253 | 0x05, 0x01, /* Usage Page (Desktop), */ | ||
254 | 0x75, 0x08, /* Report Size (8), */ | ||
255 | 0x09, 0x30, /* Usage (X), */ | ||
256 | 0x09, 0x31, /* Usage (Y), */ | ||
257 | 0x15, 0x81, /* Logical Minimum (-127), */ | ||
258 | 0x25, 0x7F, /* Logical Maximum (127), */ | ||
259 | 0x95, 0x02, /* Report Count (2), */ | ||
260 | 0x81, 0x06, /* Input (Variable, Relative), */ | ||
261 | 0x09, 0x38, /* Usage (Wheel), */ | ||
262 | 0x15, 0xFF, /* Logical Minimum (-1), */ | ||
263 | 0x25, 0x01, /* Logical Maximum (1), */ | ||
264 | 0x95, 0x01, /* Report Count (1), */ | ||
265 | 0x81, 0x06, /* Input (Variable, Relative), */ | ||
266 | 0x81, 0x01, /* Input (Constant), */ | ||
267 | 0xC0, /* End Collection, */ | ||
268 | 0xC0 /* End Collection */ | ||
269 | }; | ||
270 | |||
271 | /* Fixed WP8060U report descriptor */ | ||
272 | static __u8 wp8060u_rdesc_fixed[] = { | ||
273 | 0x05, 0x0D, /* Usage Page (Digitizer), */ | ||
274 | 0x09, 0x02, /* Usage (Pen), */ | ||
275 | 0xA1, 0x01, /* Collection (Application), */ | ||
276 | 0x85, 0x09, /* Report ID (9), */ | ||
277 | 0x09, 0x20, /* Usage (Stylus), */ | ||
278 | 0xA0, /* Collection (Physical), */ | ||
279 | 0x75, 0x01, /* Report Size (1), */ | ||
280 | 0x09, 0x42, /* Usage (Tip Switch), */ | ||
281 | 0x09, 0x44, /* Usage (Barrel Switch), */ | ||
282 | 0x09, 0x46, /* Usage (Tablet Pick), */ | ||
283 | 0x14, /* Logical Minimum (0), */ | ||
284 | 0x25, 0x01, /* Logical Maximum (1), */ | ||
285 | 0x95, 0x03, /* Report Count (3), */ | ||
286 | 0x81, 0x02, /* Input (Variable), */ | ||
287 | 0x95, 0x05, /* Report Count (5), */ | ||
288 | 0x81, 0x01, /* Input (Constant), */ | ||
289 | 0x75, 0x10, /* Report Size (16), */ | ||
290 | 0x95, 0x01, /* Report Count (1), */ | ||
291 | 0x14, /* Logical Minimum (0), */ | ||
292 | 0xA4, /* Push, */ | ||
293 | 0x05, 0x01, /* Usage Page (Desktop), */ | ||
294 | 0x55, 0xFD, /* Unit Exponent (-3), */ | ||
295 | 0x65, 0x13, /* Unit (Inch), */ | ||
296 | 0x34, /* Physical Minimum (0), */ | ||
297 | 0x09, 0x30, /* Usage (X), */ | ||
298 | 0x46, 0x40, 0x1F, /* Physical Maximum (8000), */ | ||
299 | 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ | ||
300 | 0x81, 0x02, /* Input (Variable), */ | ||
301 | 0x09, 0x31, /* Usage (Y), */ | ||
302 | 0x46, 0x70, 0x17, /* Physical Maximum (6000), */ | ||
303 | 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ | ||
304 | 0x81, 0x02, /* Input (Variable), */ | ||
305 | 0xB4, /* Pop, */ | ||
306 | 0x09, 0x30, /* Usage (Tip Pressure), */ | ||
307 | 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ | ||
308 | 0x81, 0x02, /* Input (Variable), */ | ||
309 | 0xC0, /* End Collection, */ | ||
310 | 0xC0, /* End Collection, */ | ||
311 | 0x05, 0x01, /* Usage Page (Desktop), */ | ||
312 | 0x09, 0x02, /* Usage (Mouse), */ | ||
313 | 0xA1, 0x01, /* Collection (Application), */ | ||
314 | 0x85, 0x08, /* Report ID (8), */ | ||
315 | 0x09, 0x01, /* Usage (Pointer), */ | ||
316 | 0xA0, /* Collection (Physical), */ | ||
317 | 0x75, 0x01, /* Report Size (1), */ | ||
318 | 0x05, 0x09, /* Usage Page (Button), */ | ||
319 | 0x19, 0x01, /* Usage Minimum (01h), */ | ||
320 | 0x29, 0x03, /* Usage Maximum (03h), */ | ||
321 | 0x14, /* Logical Minimum (0), */ | ||
322 | 0x25, 0x01, /* Logical Maximum (1), */ | ||
323 | 0x95, 0x03, /* Report Count (3), */ | ||
324 | 0x81, 0x02, /* Input (Variable), */ | ||
325 | 0x95, 0x05, /* Report Count (5), */ | ||
326 | 0x81, 0x01, /* Input (Constant), */ | ||
327 | 0x05, 0x01, /* Usage Page (Desktop), */ | ||
328 | 0x75, 0x08, /* Report Size (8), */ | ||
329 | 0x09, 0x30, /* Usage (X), */ | ||
330 | 0x09, 0x31, /* Usage (Y), */ | ||
331 | 0x15, 0x81, /* Logical Minimum (-127), */ | ||
332 | 0x25, 0x7F, /* Logical Maximum (127), */ | ||
333 | 0x95, 0x02, /* Report Count (2), */ | ||
334 | 0x81, 0x06, /* Input (Variable, Relative), */ | ||
335 | 0x09, 0x38, /* Usage (Wheel), */ | ||
336 | 0x15, 0xFF, /* Logical Minimum (-1), */ | ||
337 | 0x25, 0x01, /* Logical Maximum (1), */ | ||
338 | 0x95, 0x01, /* Report Count (1), */ | ||
339 | 0x81, 0x06, /* Input (Variable, Relative), */ | ||
340 | 0x81, 0x01, /* Input (Constant), */ | ||
341 | 0xC0, /* End Collection, */ | ||
342 | 0xC0 /* End Collection */ | ||
343 | }; | ||
344 | |||
345 | /* | ||
346 | * Original PF1209 report descriptor. | ||
347 | * | ||
348 | * The descriptor is similar to WPXXXXU descriptors, with an addition of a | ||
349 | * feature report (ID 4) of unknown purpose. | ||
350 | * | ||
351 | * Although the advertised resolution is 4000 LPI the unused report ID | ||
352 | * (taken from WPXXXXU, it seems) states 2000 LPI, but it is probably | ||
353 | * incorrect and is a result of blind copying without understanding. Anyway | ||
354 | * the real logical extents are always scaled to 0..32767, which IMHO spoils | ||
355 | * the precision. | ||
356 | * | ||
357 | * Usage Page (Digitizer), ; Digitizer (0Dh) | ||
358 | * Usage (Pen), ; Pen (02h, application collection) | ||
359 | * Collection (Application), | ||
360 | * Report ID (7), | ||
361 | * Usage (Stylus), ; Stylus (20h, logical collection) | ||
362 | * Collection (Physical), | ||
363 | * Usage (Tip Switch), ; Tip switch (42h, momentary control) | ||
364 | * Usage (Barrel Switch), ; Barrel switch (44h, momentary control) | ||
365 | * Usage (Eraser), ; Eraser (45h, momentary control) | ||
366 | * Logical Minimum (0), | ||
367 | * Logical Maximum (1), | ||
368 | * Report Size (1), | ||
369 | * Report Count (3), | ||
370 | * Input (Variable), | ||
371 | * Report Count (3), | ||
372 | * Input (Constant, Variable), | ||
373 | * Usage (In Range), ; In range (32h, momentary control) | ||
374 | * Report Count (1), | ||
375 | * Input (Variable), | ||
376 | * Report Count (1), | ||
377 | * Input (Constant, Variable), | ||
378 | * Usage Page (Desktop), ; Generic desktop controls (01h) | ||
379 | * Usage (X), ; X (30h, dynamic value) | ||
380 | * Report Size (16), | ||
381 | * Report Count (1), | ||
382 | * Push, | ||
383 | * Unit Exponent (13), | ||
384 | * Unit (Inch^3), | ||
385 | * Physical Minimum (0), | ||
386 | * Physical Maximum (12000), | ||
387 | * Logical Maximum (24000), | ||
388 | * Input (Variable), | ||
389 | * Usage (Y), ; Y (31h, dynamic value) | ||
390 | * Physical Maximum (9000), | ||
391 | * Logical Maximum (18000), | ||
392 | * Input (Variable), | ||
393 | * Pop, | ||
394 | * Usage Page (Digitizer), ; Digitizer (0Dh) | ||
395 | * Usage (Tip Pressure), ; Tip pressure (30h, dynamic value) | ||
396 | * Logical Maximum (1023), | ||
397 | * Input (Variable), | ||
398 | * Report Size (16), | ||
399 | * End Collection, | ||
400 | * End Collection, | ||
401 | * Usage Page (Desktop), ; Generic desktop controls (01h) | ||
402 | * Usage (Mouse), ; Mouse (02h, application collection) | ||
403 | * Collection (Application), | ||
404 | * Report ID (8), | ||
405 | * Usage (Pointer), ; Pointer (01h, physical collection) | ||
406 | * Collection (Physical), | ||
407 | * Usage Page (Button), ; Button (09h) | ||
408 | * Usage Minimum (01h), | ||
409 | * Usage Maximum (03h), | ||
410 | * Logical Minimum (0), | ||
411 | * Logical Maximum (1), | ||
412 | * Report Count (3), | ||
413 | * Report Size (1), | ||
414 | * Input (Variable), | ||
415 | * Report Count (5), | ||
416 | * Input (Constant), | ||
417 | * Usage Page (Desktop), ; Generic desktop controls (01h) | ||
418 | * Usage (X), ; X (30h, dynamic value) | ||
419 | * Usage (Y), ; Y (31h, dynamic value) | ||
420 | * Usage (Wheel), ; Wheel (38h, dynamic value) | ||
421 | * Usage (00h), | ||
422 | * Logical Minimum (-127), | ||
423 | * Logical Maximum (127), | ||
424 | * Report Size (8), | ||
425 | * Report Count (4), | ||
426 | * Input (Variable, Relative), | ||
427 | * End Collection, | ||
428 | * End Collection, | ||
429 | * Usage Page (Desktop), ; Generic desktop controls (01h) | ||
430 | * Usage (Mouse), ; Mouse (02h, application collection) | ||
431 | * Collection (Application), | ||
432 | * Report ID (9), | ||
433 | * Usage (Pointer), ; Pointer (01h, physical collection) | ||
434 | * Collection (Physical), | ||
435 | * Usage Page (Button), ; Button (09h) | ||
436 | * Usage Minimum (01h), | ||
437 | * Usage Maximum (03h), | ||
438 | * Logical Minimum (0), | ||
439 | * Logical Maximum (1), | ||
440 | * Report Count (3), | ||
441 | * Report Size (1), | ||
442 | * Input (Variable), | ||
443 | * Report Count (5), | ||
444 | * Input (Constant), | ||
445 | * Usage Page (Desktop), ; Generic desktop controls (01h) | ||
446 | * Usage (X), ; X (30h, dynamic value) | ||
447 | * Usage (Y), ; Y (31h, dynamic value) | ||
448 | * Logical Minimum (0), | ||
449 | * Logical Maximum (32767), | ||
450 | * Physical Minimum (0), | ||
451 | * Physical Maximum (32767), | ||
452 | * Report Count (2), | ||
453 | * Report Size (16), | ||
454 | * Input (Variable), | ||
455 | * Usage Page (Digitizer), ; Digitizer (0Dh) | ||
456 | * Usage (Tip Pressure), ; Tip pressure (30h, dynamic value) | ||
457 | * Logical Maximum (1023), | ||
458 | * Report Count (1), | ||
459 | * Report Size (16), | ||
460 | * Input (Variable), | ||
461 | * End Collection, | ||
462 | * End Collection, | ||
463 | * Usage Page (Desktop), ; Generic desktop controls (01h) | ||
464 | * Usage (00h), | ||
465 | * Collection (Application), | ||
466 | * Report ID (4), | ||
467 | * Logical Minimum (0), | ||
468 | * Logical Maximum (255), | ||
469 | * Usage (00h), | ||
470 | * Report Size (8), | ||
471 | * Report Count (3), | ||
472 | * Feature (Variable), | ||
473 | * End Collection | ||
474 | */ | ||
475 | |||
476 | /* Size of the original descriptor of PF1209 tablet */ | ||
477 | #define PF1209_RDESC_ORIG_SIZE 234 | ||
478 | |||
479 | /* | ||
480 | * Fixed PF1209 report descriptor | ||
481 | * | ||
482 | * The descriptor is fixed similarly to WP5540U and WP8060U, plus the | ||
483 | * feature report is removed, because its purpose is unknown and it is of no | ||
484 | * use to the generic HID driver anyway for now. | ||
485 | */ | ||
486 | static __u8 pf1209_rdesc_fixed[] = { | ||
487 | 0x05, 0x0D, /* Usage Page (Digitizer), */ | ||
488 | 0x09, 0x02, /* Usage (Pen), */ | ||
489 | 0xA1, 0x01, /* Collection (Application), */ | ||
490 | 0x85, 0x09, /* Report ID (9), */ | ||
491 | 0x09, 0x20, /* Usage (Stylus), */ | ||
492 | 0xA0, /* Collection (Physical), */ | ||
493 | 0x75, 0x01, /* Report Size (1), */ | ||
494 | 0x09, 0x42, /* Usage (Tip Switch), */ | ||
495 | 0x09, 0x44, /* Usage (Barrel Switch), */ | ||
496 | 0x09, 0x46, /* Usage (Tablet Pick), */ | ||
497 | 0x14, /* Logical Minimum (0), */ | ||
498 | 0x25, 0x01, /* Logical Maximum (1), */ | ||
499 | 0x95, 0x03, /* Report Count (3), */ | ||
500 | 0x81, 0x02, /* Input (Variable), */ | ||
501 | 0x95, 0x05, /* Report Count (5), */ | ||
502 | 0x81, 0x01, /* Input (Constant), */ | ||
503 | 0x75, 0x10, /* Report Size (16), */ | ||
504 | 0x95, 0x01, /* Report Count (1), */ | ||
505 | 0x14, /* Logical Minimum (0), */ | ||
506 | 0xA4, /* Push, */ | ||
507 | 0x05, 0x01, /* Usage Page (Desktop), */ | ||
508 | 0x55, 0xFD, /* Unit Exponent (-3), */ | ||
509 | 0x65, 0x13, /* Unit (Inch), */ | ||
510 | 0x34, /* Physical Minimum (0), */ | ||
511 | 0x09, 0x30, /* Usage (X), */ | ||
512 | 0x46, 0xE0, 0x2E, /* Physical Maximum (12000), */ | ||
513 | 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ | ||
514 | 0x81, 0x02, /* Input (Variable), */ | ||
515 | 0x09, 0x31, /* Usage (Y), */ | ||
516 | 0x46, 0x28, 0x23, /* Physical Maximum (9000), */ | ||
517 | 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ | ||
518 | 0x81, 0x02, /* Input (Variable), */ | ||
519 | 0xB4, /* Pop, */ | ||
520 | 0x09, 0x30, /* Usage (Tip Pressure), */ | ||
521 | 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ | ||
522 | 0x81, 0x02, /* Input (Variable), */ | ||
523 | 0xC0, /* End Collection, */ | ||
524 | 0xC0, /* End Collection, */ | ||
525 | 0x05, 0x01, /* Usage Page (Desktop), */ | ||
526 | 0x09, 0x02, /* Usage (Mouse), */ | ||
527 | 0xA1, 0x01, /* Collection (Application), */ | ||
528 | 0x85, 0x08, /* Report ID (8), */ | ||
529 | 0x09, 0x01, /* Usage (Pointer), */ | ||
530 | 0xA0, /* Collection (Physical), */ | ||
531 | 0x75, 0x01, /* Report Size (1), */ | ||
532 | 0x05, 0x09, /* Usage Page (Button), */ | ||
533 | 0x19, 0x01, /* Usage Minimum (01h), */ | ||
534 | 0x29, 0x03, /* Usage Maximum (03h), */ | ||
535 | 0x14, /* Logical Minimum (0), */ | ||
536 | 0x25, 0x01, /* Logical Maximum (1), */ | ||
537 | 0x95, 0x03, /* Report Count (3), */ | ||
538 | 0x81, 0x02, /* Input (Variable), */ | ||
539 | 0x95, 0x05, /* Report Count (5), */ | ||
540 | 0x81, 0x01, /* Input (Constant), */ | ||
541 | 0x05, 0x01, /* Usage Page (Desktop), */ | ||
542 | 0x75, 0x08, /* Report Size (8), */ | ||
543 | 0x09, 0x30, /* Usage (X), */ | ||
544 | 0x09, 0x31, /* Usage (Y), */ | ||
545 | 0x15, 0x81, /* Logical Minimum (-127), */ | ||
546 | 0x25, 0x7F, /* Logical Maximum (127), */ | ||
547 | 0x95, 0x02, /* Report Count (2), */ | ||
548 | 0x81, 0x06, /* Input (Variable, Relative), */ | ||
549 | 0x09, 0x38, /* Usage (Wheel), */ | ||
550 | 0x15, 0xFF, /* Logical Minimum (-1), */ | ||
551 | 0x25, 0x01, /* Logical Maximum (1), */ | ||
552 | 0x95, 0x01, /* Report Count (1), */ | ||
553 | 0x81, 0x06, /* Input (Variable, Relative), */ | ||
554 | 0x81, 0x01, /* Input (Constant), */ | ||
555 | 0xC0, /* End Collection, */ | ||
556 | 0xC0 /* End Collection */ | ||
557 | }; | ||
558 | |||
559 | static __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc, | ||
560 | unsigned int *rsize) | ||
561 | { | ||
562 | switch (hdev->product) { | ||
563 | case USB_DEVICE_ID_UCLOGIC_TABLET_PF1209: | ||
564 | if (*rsize == PF1209_RDESC_ORIG_SIZE) { | ||
565 | rdesc = pf1209_rdesc_fixed; | ||
566 | *rsize = sizeof(pf1209_rdesc_fixed); | ||
567 | } | ||
568 | break; | ||
569 | case USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U: | ||
570 | if (*rsize == WPXXXXU_RDESC_ORIG_SIZE) { | ||
571 | rdesc = wp4030u_rdesc_fixed; | ||
572 | *rsize = sizeof(wp4030u_rdesc_fixed); | ||
573 | } | ||
574 | break; | ||
575 | case USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U: | ||
576 | if (*rsize == WPXXXXU_RDESC_ORIG_SIZE) { | ||
577 | rdesc = wp5540u_rdesc_fixed; | ||
578 | *rsize = sizeof(wp5540u_rdesc_fixed); | ||
579 | } | ||
580 | break; | ||
581 | case USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U: | ||
582 | if (*rsize == WPXXXXU_RDESC_ORIG_SIZE) { | ||
583 | rdesc = wp8060u_rdesc_fixed; | ||
584 | *rsize = sizeof(wp8060u_rdesc_fixed); | ||
585 | } | ||
586 | break; | ||
587 | } | ||
588 | |||
589 | return rdesc; | ||
590 | } | ||
591 | |||
592 | static const struct hid_device_id uclogic_devices[] = { | ||
593 | { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, | ||
594 | USB_DEVICE_ID_UCLOGIC_TABLET_PF1209) }, | ||
595 | { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, | ||
596 | USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U) }, | ||
597 | { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, | ||
598 | USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U) }, | ||
599 | { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, | ||
600 | USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U) }, | ||
601 | { } | ||
602 | }; | ||
603 | MODULE_DEVICE_TABLE(hid, uclogic_devices); | ||
604 | |||
605 | static struct hid_driver uclogic_driver = { | ||
606 | .name = "uclogic", | ||
607 | .id_table = uclogic_devices, | ||
608 | .report_fixup = uclogic_report_fixup, | ||
609 | }; | ||
610 | |||
611 | static int __init uclogic_init(void) | ||
612 | { | ||
613 | return hid_register_driver(&uclogic_driver); | ||
614 | } | ||
615 | |||
616 | static void __exit uclogic_exit(void) | ||
617 | { | ||
618 | hid_unregister_driver(&uclogic_driver); | ||
619 | } | ||
620 | |||
621 | module_init(uclogic_init); | ||
622 | module_exit(uclogic_exit); | ||
623 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/hid/hid-wacom.c b/drivers/hid/hid-wacom.c index 724f46ed612f..06888323828c 100644 --- a/drivers/hid/hid-wacom.c +++ b/drivers/hid/hid-wacom.c | |||
@@ -18,6 +18,8 @@ | |||
18 | * any later version. | 18 | * any later version. |
19 | */ | 19 | */ |
20 | 20 | ||
21 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
22 | |||
21 | #include <linux/device.h> | 23 | #include <linux/device.h> |
22 | #include <linux/hid.h> | 24 | #include <linux/hid.h> |
23 | #include <linux/module.h> | 25 | #include <linux/module.h> |
@@ -141,8 +143,8 @@ static void wacom_poke(struct hid_device *hdev, u8 speed) | |||
141 | * Note that if the raw queries fail, it's not a hard failure and it | 143 | * Note that if the raw queries fail, it's not a hard failure and it |
142 | * is safe to continue | 144 | * is safe to continue |
143 | */ | 145 | */ |
144 | dev_warn(&hdev->dev, "failed to poke device, command %d, err %d\n", | 146 | hid_warn(hdev, "failed to poke device, command %d, err %d\n", |
145 | rep_data[0], ret); | 147 | rep_data[0], ret); |
146 | return; | 148 | return; |
147 | } | 149 | } |
148 | 150 | ||
@@ -172,7 +174,7 @@ static ssize_t wacom_store_speed(struct device *dev, | |||
172 | return -EINVAL; | 174 | return -EINVAL; |
173 | } | 175 | } |
174 | 176 | ||
175 | static DEVICE_ATTR(speed, S_IRUGO | S_IWUGO, | 177 | static DEVICE_ATTR(speed, S_IRUGO | S_IWUSR | S_IWGRP, |
176 | wacom_show_speed, wacom_store_speed); | 178 | wacom_show_speed, wacom_store_speed); |
177 | 179 | ||
178 | static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report, | 180 | static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report, |
@@ -312,7 +314,7 @@ static int wacom_probe(struct hid_device *hdev, | |||
312 | 314 | ||
313 | wdata = kzalloc(sizeof(*wdata), GFP_KERNEL); | 315 | wdata = kzalloc(sizeof(*wdata), GFP_KERNEL); |
314 | if (wdata == NULL) { | 316 | if (wdata == NULL) { |
315 | dev_err(&hdev->dev, "can't alloc wacom descriptor\n"); | 317 | hid_err(hdev, "can't alloc wacom descriptor\n"); |
316 | return -ENOMEM; | 318 | return -ENOMEM; |
317 | } | 319 | } |
318 | 320 | ||
@@ -321,20 +323,20 @@ static int wacom_probe(struct hid_device *hdev, | |||
321 | /* Parse the HID report now */ | 323 | /* Parse the HID report now */ |
322 | ret = hid_parse(hdev); | 324 | ret = hid_parse(hdev); |
323 | if (ret) { | 325 | if (ret) { |
324 | dev_err(&hdev->dev, "parse failed\n"); | 326 | hid_err(hdev, "parse failed\n"); |
325 | goto err_free; | 327 | goto err_free; |
326 | } | 328 | } |
327 | 329 | ||
328 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); | 330 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); |
329 | if (ret) { | 331 | if (ret) { |
330 | dev_err(&hdev->dev, "hw start failed\n"); | 332 | hid_err(hdev, "hw start failed\n"); |
331 | goto err_free; | 333 | goto err_free; |
332 | } | 334 | } |
333 | 335 | ||
334 | ret = device_create_file(&hdev->dev, &dev_attr_speed); | 336 | ret = device_create_file(&hdev->dev, &dev_attr_speed); |
335 | if (ret) | 337 | if (ret) |
336 | dev_warn(&hdev->dev, | 338 | hid_warn(hdev, |
337 | "can't create sysfs speed attribute err: %d\n", ret); | 339 | "can't create sysfs speed attribute err: %d\n", ret); |
338 | 340 | ||
339 | /* Set Wacom mode 2 with high reporting speed */ | 341 | /* Set Wacom mode 2 with high reporting speed */ |
340 | wacom_poke(hdev, 1); | 342 | wacom_poke(hdev, 1); |
@@ -349,8 +351,8 @@ static int wacom_probe(struct hid_device *hdev, | |||
349 | 351 | ||
350 | ret = power_supply_register(&hdev->dev, &wdata->battery); | 352 | ret = power_supply_register(&hdev->dev, &wdata->battery); |
351 | if (ret) { | 353 | if (ret) { |
352 | dev_warn(&hdev->dev, | 354 | hid_warn(hdev, "can't create sysfs battery attribute, err: %d\n", |
353 | "can't create sysfs battery attribute, err: %d\n", ret); | 355 | ret); |
354 | /* | 356 | /* |
355 | * battery attribute is not critical for the tablet, but if it | 357 | * battery attribute is not critical for the tablet, but if it |
356 | * failed then there is no need to create ac attribute | 358 | * failed then there is no need to create ac attribute |
@@ -367,8 +369,8 @@ static int wacom_probe(struct hid_device *hdev, | |||
367 | 369 | ||
368 | ret = power_supply_register(&hdev->dev, &wdata->ac); | 370 | ret = power_supply_register(&hdev->dev, &wdata->ac); |
369 | if (ret) { | 371 | if (ret) { |
370 | dev_warn(&hdev->dev, | 372 | hid_warn(hdev, |
371 | "can't create ac battery attribute, err: %d\n", ret); | 373 | "can't create ac battery attribute, err: %d\n", ret); |
372 | /* | 374 | /* |
373 | * ac attribute is not critical for the tablet, but if it | 375 | * ac attribute is not critical for the tablet, but if it |
374 | * failed then we don't want to battery attribute to exist | 376 | * failed then we don't want to battery attribute to exist |
@@ -454,7 +456,7 @@ static int __init wacom_init(void) | |||
454 | 456 | ||
455 | ret = hid_register_driver(&wacom_driver); | 457 | ret = hid_register_driver(&wacom_driver); |
456 | if (ret) | 458 | if (ret) |
457 | printk(KERN_ERR "can't register wacom driver\n"); | 459 | pr_err("can't register wacom driver\n"); |
458 | return ret; | 460 | return ret; |
459 | } | 461 | } |
460 | 462 | ||
diff --git a/drivers/hid/hid-waltop.c b/drivers/hid/hid-waltop.c new file mode 100644 index 000000000000..b3a4163f2e67 --- /dev/null +++ b/drivers/hid/hid-waltop.c | |||
@@ -0,0 +1,1099 @@ | |||
1 | /* | ||
2 | * HID driver for Waltop devices not fully compliant with HID standard | ||
3 | * | ||
4 | * Copyright (c) 2010 Nikolai Kondrashov | ||
5 | */ | ||
6 | |||
7 | /* | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the Free | ||
10 | * Software Foundation; either version 2 of the License, or (at your option) | ||
11 | * any later version. | ||
12 | */ | ||
13 | |||
14 | #include <linux/device.h> | ||
15 | #include <linux/hid.h> | ||
16 | #include <linux/module.h> | ||
17 | |||
18 | #include "hid-ids.h" | ||
19 | |||
20 | /* | ||
21 | * There exists an official driver on the manufacturer's website, which | ||
22 | * wasn't submitted to the kernel, for some reason. The official driver | ||
23 | * doesn't seem to support extra features of some tablets, like wheels. | ||
24 | * | ||
25 | * It shows that the feature report ID 2 could be used to control any waltop | ||
26 | * tablet input mode, switching it between "default", "tablet" and "ink". | ||
27 | * | ||
28 | * This driver only uses "default" mode for all the supported tablets. This | ||
29 | * mode tries to be HID-compatible (not very successfully), but cripples the | ||
30 | * resolution of some tablets. | ||
31 | * | ||
32 | * The "tablet" mode uses some proprietary, yet decipherable protocol, which | ||
33 | * represents the correct resolution, but is possibly HID-incompatible (i.e. | ||
34 | * indescribable by a report descriptor). | ||
35 | * | ||
36 | * The purpose of the "ink" mode is unknown. | ||
37 | * | ||
38 | * The feature reports needed for switching to each mode are these: | ||
39 | * | ||
40 | * 02 16 00 default | ||
41 | * 02 16 01 tablet | ||
42 | * 02 16 02 ink | ||
43 | */ | ||
44 | |||
45 | /* | ||
46 | * Original Slim Tablet 5.8 inch report descriptor. | ||
47 | * | ||
48 | * All the reports except the report with ID 16 (the stylus) are unused, | ||
49 | * possibly because the tablet is not configured to, or because they were | ||
50 | * just copied from a more capable model. The full purpose of features | ||
51 | * described for report ID 2 is unknown. | ||
52 | * | ||
53 | * The stylus buttons are described as three bit fields, whereas actually | ||
54 | * it's an "array", i.e. they're reported as button numbers (1, 2 and 3). | ||
55 | * The "eraser" field is not used. There is also a "push" without a "pop" in | ||
56 | * the stylus description. | ||
57 | * | ||
58 | * Usage Page (Desktop), ; Generic desktop controls (01h) | ||
59 | * Usage (Mouse), ; Mouse (02h, application collection) | ||
60 | * Collection (Application), | ||
61 | * Report ID (1), | ||
62 | * Usage (Pointer), ; Pointer (01h, physical collection) | ||
63 | * Collection (Physical), | ||
64 | * Usage Page (Button), ; Button (09h) | ||
65 | * Usage Minimum (01h), | ||
66 | * Usage Maximum (05h), | ||
67 | * Logical Minimum (0), | ||
68 | * Logical Maximum (1), | ||
69 | * Report Size (1), | ||
70 | * Report Count (5), | ||
71 | * Input (Variable), | ||
72 | * Report Size (3), | ||
73 | * Report Count (1), | ||
74 | * Input (Constant, Variable), | ||
75 | * Usage Page (Desktop), ; Generic desktop controls (01h) | ||
76 | * Usage (X), ; X (30h, dynamic value) | ||
77 | * Usage (Y), ; Y (31h, dynamic value) | ||
78 | * Usage (Wheel), ; Wheel (38h, dynamic value) | ||
79 | * Logical Minimum (-127), | ||
80 | * Logical Maximum (127), | ||
81 | * Report Size (8), | ||
82 | * Report Count (3), | ||
83 | * Input (Variable, Relative), | ||
84 | * End Collection, | ||
85 | * End Collection, | ||
86 | * Usage Page (Digitizer), ; Digitizer (0Dh) | ||
87 | * Usage (Pen), ; Pen (02h, application collection) | ||
88 | * Collection (Application), | ||
89 | * Report ID (2), | ||
90 | * Usage (Stylus), ; Stylus (20h, logical collection) | ||
91 | * Collection (Physical), | ||
92 | * Usage (00h), | ||
93 | * Logical Minimum (0), | ||
94 | * Logical Maximum (255), | ||
95 | * Report Size (8), | ||
96 | * Report Count (7), | ||
97 | * Input (Variable), | ||
98 | * Usage (Azimuth), ; Azimuth (3Fh, dynamic value) | ||
99 | * Usage (Altitude), ; Altitude (40h, dynamic value) | ||
100 | * Logical Minimum (0), | ||
101 | * Logical Maximum (255), | ||
102 | * Report Size (8), | ||
103 | * Report Count (2), | ||
104 | * Feature (Variable), | ||
105 | * End Collection, | ||
106 | * Report ID (5), | ||
107 | * Usage Page (Digitizer), ; Digitizer (0Dh) | ||
108 | * Usage (Stylus), ; Stylus (20h, logical collection) | ||
109 | * Collection (Physical), | ||
110 | * Usage (00h), | ||
111 | * Logical Minimum (0), | ||
112 | * Logical Maximum (255), | ||
113 | * Report Size (8), | ||
114 | * Report Count (7), | ||
115 | * Input (Variable), | ||
116 | * End Collection, | ||
117 | * Report ID (10), | ||
118 | * Usage Page (Digitizer), ; Digitizer (0Dh) | ||
119 | * Usage (Stylus), ; Stylus (20h, logical collection) | ||
120 | * Collection (Physical), | ||
121 | * Usage (00h), | ||
122 | * Logical Minimum (0), | ||
123 | * Logical Maximum (255), | ||
124 | * Report Size (8), | ||
125 | * Report Count (3), | ||
126 | * Input (Variable), | ||
127 | * End Collection, | ||
128 | * Report ID (16), | ||
129 | * Usage (Stylus), ; Stylus (20h, logical collection) | ||
130 | * Collection (Physical), | ||
131 | * Usage (Tip Switch), ; Tip switch (42h, momentary control) | ||
132 | * Usage (Barrel Switch), ; Barrel switch (44h, momentary control) | ||
133 | * Usage (Invert), ; Invert (3Ch, momentary control) | ||
134 | * Usage (Eraser), ; Eraser (45h, momentary control) | ||
135 | * Usage (In Range), ; In range (32h, momentary control) | ||
136 | * Logical Minimum (0), | ||
137 | * Logical Maximum (1), | ||
138 | * Report Size (1), | ||
139 | * Report Count (5), | ||
140 | * Input (Variable), | ||
141 | * Report Count (3), | ||
142 | * Input (Constant, Variable), | ||
143 | * Usage Page (Desktop), ; Generic desktop controls (01h) | ||
144 | * Usage (X), ; X (30h, dynamic value) | ||
145 | * Report Size (16), | ||
146 | * Report Count (1), | ||
147 | * Push, | ||
148 | * Unit Exponent (13), | ||
149 | * Unit (Inch^3), | ||
150 | * Logical Minimum (0), | ||
151 | * Logical Maximum (10000), | ||
152 | * Physical Minimum (0), | ||
153 | * Physical Maximum (10000), | ||
154 | * Input (Variable), | ||
155 | * Usage (Y), ; Y (31h, dynamic value) | ||
156 | * Logical Maximum (6000), | ||
157 | * Physical Maximum (6000), | ||
158 | * Input (Variable), | ||
159 | * Usage Page (Digitizer), ; Digitizer (0Dh) | ||
160 | * Usage (Tip Pressure), ; Tip pressure (30h, dynamic value) | ||
161 | * Logical Minimum (0), | ||
162 | * Logical Maximum (1023), | ||
163 | * Physical Minimum (0), | ||
164 | * Physical Maximum (1023), | ||
165 | * Input (Variable), | ||
166 | * End Collection, | ||
167 | * End Collection | ||
168 | */ | ||
169 | |||
170 | /* Size of the original report descriptor of Slim Tablet 5.8 inch */ | ||
171 | #define SLIM_TABLET_5_8_INCH_RDESC_ORIG_SIZE 222 | ||
172 | |||
173 | /* | ||
174 | * Fixed Slim Tablet 5.8 inch descriptor. | ||
175 | * | ||
176 | * All the reports except the stylus report (ID 16) were removed as unused. | ||
177 | * The stylus buttons description was fixed. | ||
178 | */ | ||
179 | static __u8 slim_tablet_5_8_inch_rdesc_fixed[] = { | ||
180 | 0x05, 0x0D, /* Usage Page (Digitizer), */ | ||
181 | 0x09, 0x02, /* Usage (Pen), */ | ||
182 | 0xA1, 0x01, /* Collection (Application), */ | ||
183 | 0x85, 0x10, /* Report ID (16), */ | ||
184 | 0x09, 0x20, /* Usage (Stylus), */ | ||
185 | 0xA0, /* Collection (Physical), */ | ||
186 | 0x09, 0x42, /* Usage (Tip Switch), */ | ||
187 | 0x09, 0x44, /* Usage (Barrel Switch), */ | ||
188 | 0x09, 0x46, /* Usage (Tablet Pick), */ | ||
189 | 0x15, 0x01, /* Logical Minimum (1), */ | ||
190 | 0x25, 0x03, /* Logical Maximum (3), */ | ||
191 | 0x75, 0x04, /* Report Size (4), */ | ||
192 | 0x95, 0x01, /* Report Count (1), */ | ||
193 | 0x80, /* Input, */ | ||
194 | 0x09, 0x32, /* Usage (In Range), */ | ||
195 | 0x14, /* Logical Minimum (0), */ | ||
196 | 0x25, 0x01, /* Logical Maximum (1), */ | ||
197 | 0x75, 0x01, /* Report Size (1), */ | ||
198 | 0x95, 0x01, /* Report Count (1), */ | ||
199 | 0x81, 0x02, /* Input (Variable), */ | ||
200 | 0x95, 0x03, /* Report Count (3), */ | ||
201 | 0x81, 0x03, /* Input (Constant, Variable), */ | ||
202 | 0x75, 0x10, /* Report Size (16), */ | ||
203 | 0x95, 0x01, /* Report Count (1), */ | ||
204 | 0x14, /* Logical Minimum (0), */ | ||
205 | 0xA4, /* Push, */ | ||
206 | 0x05, 0x01, /* Usage Page (Desktop), */ | ||
207 | 0x65, 0x13, /* Unit (Inch), */ | ||
208 | 0x55, 0xFD, /* Unit Exponent (-3), */ | ||
209 | 0x34, /* Physical Minimum (0), */ | ||
210 | 0x09, 0x30, /* Usage (X), */ | ||
211 | 0x46, 0x88, 0x13, /* Physical Maximum (5000), */ | ||
212 | 0x26, 0x10, 0x27, /* Logical Maximum (10000), */ | ||
213 | 0x81, 0x02, /* Input (Variable), */ | ||
214 | 0x09, 0x31, /* Usage (Y), */ | ||
215 | 0x46, 0xB8, 0x0B, /* Physical Maximum (3000), */ | ||
216 | 0x26, 0x70, 0x17, /* Logical Maximum (6000), */ | ||
217 | 0x81, 0x02, /* Input (Variable), */ | ||
218 | 0xB4, /* Pop, */ | ||
219 | 0x09, 0x30, /* Usage (Tip Pressure), */ | ||
220 | 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ | ||
221 | 0x81, 0x02, /* Input (Variable), */ | ||
222 | 0xC0, /* End Collection, */ | ||
223 | 0xC0 /* End Collection */ | ||
224 | }; | ||
225 | |||
226 | /* | ||
227 | * Original Slim Tablet 12.1 inch report descriptor. | ||
228 | * | ||
229 | * The descriptor is similar to the Slim Tablet 5.8 inch descriptor with the | ||
230 | * addition of a keyboard report, seemingly unused. It may have get here | ||
231 | * from a Media Tablet - probably an unimplemented feature. | ||
232 | * | ||
233 | * Usage Page (Desktop), ; Generic desktop controls (01h) | ||
234 | * Usage (Mouse), ; Mouse (02h, application collection) | ||
235 | * Collection (Application), | ||
236 | * Report ID (1), | ||
237 | * Usage (Pointer), ; Pointer (01h, physical collection) | ||
238 | * Collection (Physical), | ||
239 | * Usage Page (Button), ; Button (09h) | ||
240 | * Usage Minimum (01h), | ||
241 | * Usage Maximum (05h), | ||
242 | * Logical Minimum (0), | ||
243 | * Logical Maximum (1), | ||
244 | * Report Size (1), | ||
245 | * Report Count (5), | ||
246 | * Input (Variable), | ||
247 | * Report Size (3), | ||
248 | * Report Count (1), | ||
249 | * Input (Constant, Variable), | ||
250 | * Usage Page (Desktop), ; Generic desktop controls (01h) | ||
251 | * Usage (X), ; X (30h, dynamic value) | ||
252 | * Usage (Y), ; Y (31h, dynamic value) | ||
253 | * Usage (Wheel), ; Wheel (38h, dynamic value) | ||
254 | * Logical Minimum (-127), | ||
255 | * Logical Maximum (127), | ||
256 | * Report Size (8), | ||
257 | * Report Count (3), | ||
258 | * Input (Variable, Relative), | ||
259 | * End Collection, | ||
260 | * End Collection, | ||
261 | * Usage Page (Digitizer), ; Digitizer (0Dh) | ||
262 | * Usage (Pen), ; Pen (02h, application collection) | ||
263 | * Collection (Application), | ||
264 | * Report ID (2), | ||
265 | * Usage (Stylus), ; Stylus (20h, logical collection) | ||
266 | * Collection (Physical), | ||
267 | * Usage (00h), | ||
268 | * Logical Minimum (0), | ||
269 | * Logical Maximum (255), | ||
270 | * Report Size (8), | ||
271 | * Report Count (7), | ||
272 | * Input (Variable), | ||
273 | * Usage (Azimuth), ; Azimuth (3Fh, dynamic value) | ||
274 | * Usage (Altitude), ; Altitude (40h, dynamic value) | ||
275 | * Logical Minimum (0), | ||
276 | * Logical Maximum (255), | ||
277 | * Report Size (8), | ||
278 | * Report Count (2), | ||
279 | * Feature (Variable), | ||
280 | * End Collection, | ||
281 | * Report ID (5), | ||
282 | * Usage Page (Digitizer), ; Digitizer (0Dh) | ||
283 | * Usage (Stylus), ; Stylus (20h, logical collection) | ||
284 | * Collection (Physical), | ||
285 | * Usage (00h), | ||
286 | * Logical Minimum (0), | ||
287 | * Logical Maximum (255), | ||
288 | * Report Size (8), | ||
289 | * Report Count (7), | ||
290 | * Input (Variable), | ||
291 | * End Collection, | ||
292 | * Report ID (10), | ||
293 | * Usage Page (Digitizer), ; Digitizer (0Dh) | ||
294 | * Usage (Stylus), ; Stylus (20h, logical collection) | ||
295 | * Collection (Physical), | ||
296 | * Usage (00h), | ||
297 | * Logical Minimum (0), | ||
298 | * Logical Maximum (255), | ||
299 | * Report Size (8), | ||
300 | * Report Count (3), | ||
301 | * Input (Variable), | ||
302 | * End Collection, | ||
303 | * Report ID (16), | ||
304 | * Usage (Stylus), ; Stylus (20h, logical collection) | ||
305 | * Collection (Physical), | ||
306 | * Usage (Tip Switch), ; Tip switch (42h, momentary control) | ||
307 | * Usage (Barrel Switch), ; Barrel switch (44h, momentary control) | ||
308 | * Usage (Invert), ; Invert (3Ch, momentary control) | ||
309 | * Usage (Eraser), ; Eraser (45h, momentary control) | ||
310 | * Usage (In Range), ; In range (32h, momentary control) | ||
311 | * Logical Minimum (0), | ||
312 | * Logical Maximum (1), | ||
313 | * Report Size (1), | ||
314 | * Report Count (5), | ||
315 | * Input (Variable), | ||
316 | * Report Count (3), | ||
317 | * Input (Constant, Variable), | ||
318 | * Usage Page (Desktop), ; Generic desktop controls (01h) | ||
319 | * Usage (X), ; X (30h, dynamic value) | ||
320 | * Report Size (16), | ||
321 | * Report Count (1), | ||
322 | * Push, | ||
323 | * Unit Exponent (13), | ||
324 | * Unit (Inch^3), | ||
325 | * Logical Minimum (0), | ||
326 | * Logical Maximum (20000), | ||
327 | * Physical Minimum (0), | ||
328 | * Physical Maximum (20000), | ||
329 | * Input (Variable), | ||
330 | * Usage (Y), ; Y (31h, dynamic value) | ||
331 | * Logical Maximum (12500), | ||
332 | * Physical Maximum (12500), | ||
333 | * Input (Variable), | ||
334 | * Usage Page (Digitizer), ; Digitizer (0Dh) | ||
335 | * Usage (Tip Pressure), ; Tip pressure (30h, dynamic value) | ||
336 | * Logical Minimum (0), | ||
337 | * Logical Maximum (1023), | ||
338 | * Physical Minimum (0), | ||
339 | * Physical Maximum (1023), | ||
340 | * Input (Variable), | ||
341 | * End Collection, | ||
342 | * End Collection, | ||
343 | * Usage Page (Desktop), ; Generic desktop controls (01h) | ||
344 | * Usage (Keyboard), ; Keyboard (06h, application collection) | ||
345 | * Collection (Application), | ||
346 | * Report ID (13), | ||
347 | * Usage Page (Keyboard), ; Keyboard/keypad (07h) | ||
348 | * Usage Minimum (KB Leftcontrol), ; Keyboard left control | ||
349 | * ; (E0h, dynamic value) | ||
350 | * Usage Maximum (KB Right GUI), ; Keyboard right GUI (E7h, dynamic value) | ||
351 | * Logical Minimum (0), | ||
352 | * Logical Maximum (1), | ||
353 | * Report Size (1), | ||
354 | * Report Count (8), | ||
355 | * Input (Variable), | ||
356 | * Report Size (8), | ||
357 | * Report Count (1), | ||
358 | * Input (Constant), | ||
359 | * Usage Page (Keyboard), ; Keyboard/keypad (07h) | ||
360 | * Usage Minimum (None), ; No event (00h, selector) | ||
361 | * Usage Maximum (KB Application), ; Keyboard Application (65h, selector) | ||
362 | * Logical Minimum (0), | ||
363 | * Logical Maximum (101), | ||
364 | * Report Size (8), | ||
365 | * Report Count (5), | ||
366 | * Input, | ||
367 | * End Collection | ||
368 | */ | ||
369 | |||
370 | /* Size of the original report descriptor of Slim Tablet 12.1 inch */ | ||
371 | #define SLIM_TABLET_12_1_INCH_RDESC_ORIG_SIZE 269 | ||
372 | |||
373 | /* | ||
374 | * Fixed Slim Tablet 12.1 inch descriptor. | ||
375 | * | ||
376 | * All the reports except the stylus report (ID 16) were removed as unused. | ||
377 | * The stylus buttons description was fixed. | ||
378 | */ | ||
379 | static __u8 slim_tablet_12_1_inch_rdesc_fixed[] = { | ||
380 | 0x05, 0x0D, /* Usage Page (Digitizer), */ | ||
381 | 0x09, 0x02, /* Usage (Pen), */ | ||
382 | 0xA1, 0x01, /* Collection (Application), */ | ||
383 | 0x85, 0x10, /* Report ID (16), */ | ||
384 | 0x09, 0x20, /* Usage (Stylus), */ | ||
385 | 0xA0, /* Collection (Physical), */ | ||
386 | 0x09, 0x42, /* Usage (Tip Switch), */ | ||
387 | 0x09, 0x44, /* Usage (Barrel Switch), */ | ||
388 | 0x09, 0x46, /* Usage (Tablet Pick), */ | ||
389 | 0x15, 0x01, /* Logical Minimum (1), */ | ||
390 | 0x25, 0x03, /* Logical Maximum (3), */ | ||
391 | 0x75, 0x04, /* Report Size (4), */ | ||
392 | 0x95, 0x01, /* Report Count (1), */ | ||
393 | 0x80, /* Input, */ | ||
394 | 0x09, 0x32, /* Usage (In Range), */ | ||
395 | 0x14, /* Logical Minimum (0), */ | ||
396 | 0x25, 0x01, /* Logical Maximum (1), */ | ||
397 | 0x75, 0x01, /* Report Size (1), */ | ||
398 | 0x95, 0x01, /* Report Count (1), */ | ||
399 | 0x81, 0x02, /* Input (Variable), */ | ||
400 | 0x95, 0x03, /* Report Count (3), */ | ||
401 | 0x81, 0x03, /* Input (Constant, Variable), */ | ||
402 | 0x75, 0x10, /* Report Size (16), */ | ||
403 | 0x95, 0x01, /* Report Count (1), */ | ||
404 | 0x14, /* Logical Minimum (0), */ | ||
405 | 0xA4, /* Push, */ | ||
406 | 0x05, 0x01, /* Usage Page (Desktop), */ | ||
407 | 0x65, 0x13, /* Unit (Inch), */ | ||
408 | 0x55, 0xFD, /* Unit Exponent (-3), */ | ||
409 | 0x34, /* Physical Minimum (0), */ | ||
410 | 0x09, 0x30, /* Usage (X), */ | ||
411 | 0x46, 0x10, 0x27, /* Physical Maximum (10000), */ | ||
412 | 0x26, 0x20, 0x4E, /* Logical Maximum (20000), */ | ||
413 | 0x81, 0x02, /* Input (Variable), */ | ||
414 | 0x09, 0x31, /* Usage (Y), */ | ||
415 | 0x46, 0x6A, 0x18, /* Physical Maximum (6250), */ | ||
416 | 0x26, 0xD4, 0x30, /* Logical Maximum (12500), */ | ||
417 | 0x81, 0x02, /* Input (Variable), */ | ||
418 | 0xB4, /* Pop, */ | ||
419 | 0x09, 0x30, /* Usage (Tip Pressure), */ | ||
420 | 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ | ||
421 | 0x81, 0x02, /* Input (Variable), */ | ||
422 | 0xC0, /* End Collection, */ | ||
423 | 0xC0 /* End Collection */ | ||
424 | }; | ||
425 | |||
426 | /* | ||
427 | * Original Media Tablet 10.6 inch report descriptor. | ||
428 | * | ||
429 | * There are at least two versions of this model in the wild. They are | ||
430 | * represented by Genius G-Pen M609 (older version) and Genius G-Pen M609X | ||
431 | * (newer version). | ||
432 | * | ||
433 | * Both versions have the usual pen with two barrel buttons and two | ||
434 | * identical wheels with center buttons in the top corners of the tablet | ||
435 | * base. They also have buttons on the top, between the wheels, for | ||
436 | * selecting the wheels' functions and wide/standard mode. In the wide mode | ||
437 | * the whole working surface is sensed, in the standard mode a narrower area | ||
438 | * is sensed, but the logical report extents remain the same. These modes | ||
439 | * correspond roughly to 16:9 and 4:3 aspect ratios respectively. | ||
440 | * | ||
441 | * The older version has three wheel function buttons ("scroll", "zoom" and | ||
442 | * "volume") and two separate buttons for wide and standard mode. The newer | ||
443 | * version has four wheel function buttons (plus "brush") and only one | ||
444 | * button is used for selecting wide/standard mode. So, the total number of | ||
445 | * buttons remains the same, but one of the mode buttons is repurposed as a | ||
446 | * wheels' function button in the newer version. | ||
447 | * | ||
448 | * The wheel functions are: | ||
449 | * scroll - the wheels act as scroll wheels, the center buttons switch | ||
450 | * between vertical and horizontal scrolling; | ||
451 | * zoom - the wheels zoom in/out, the buttons supposedly reset to 100%; | ||
452 | * volume - the wheels control the sound volume, the buttons mute; | ||
453 | * brush - the wheels are supposed to control brush width in a graphics | ||
454 | * editor, the buttons do nothing. | ||
455 | * | ||
456 | * Below is the newer version's report descriptor. It may very well be that | ||
457 | * the older version's descriptor is different and thus it won't be | ||
458 | * supported. | ||
459 | * | ||
460 | * The mouse report (ID 1) only uses the wheel field for reporting the tablet | ||
461 | * wheels' scroll mode. The keyboard report (ID 13) is used to report the | ||
462 | * wheels' zoom and brush control functions as key presses. The report ID 12 | ||
463 | * is used to report the wheels' volume control functions. The stylus report | ||
464 | * (ID 16) has the same problems as the Slim Tablet 5.8 inch report has. | ||
465 | * | ||
466 | * The rest of the reports are unused, at least in the default configuration. | ||
467 | * The purpose of the features is unknown. | ||
468 | * | ||
469 | * Usage Page (Desktop), | ||
470 | * Usage (Mouse), | ||
471 | * Collection (Application), | ||
472 | * Report ID (1), | ||
473 | * Usage (Pointer), | ||
474 | * Collection (Physical), | ||
475 | * Usage Page (Button), | ||
476 | * Usage Minimum (01h), | ||
477 | * Usage Maximum (05h), | ||
478 | * Logical Minimum (0), | ||
479 | * Logical Maximum (1), | ||
480 | * Report Size (1), | ||
481 | * Report Count (5), | ||
482 | * Input (Variable), | ||
483 | * Report Size (3), | ||
484 | * Report Count (1), | ||
485 | * Input (Constant, Variable), | ||
486 | * Usage Page (Desktop), | ||
487 | * Usage (X), | ||
488 | * Usage (Y), | ||
489 | * Usage (Wheel), | ||
490 | * Logical Minimum (-127), | ||
491 | * Logical Maximum (127), | ||
492 | * Report Size (8), | ||
493 | * Report Count (3), | ||
494 | * Input (Variable, Relative), | ||
495 | * End Collection, | ||
496 | * End Collection, | ||
497 | * Usage Page (Digitizer), | ||
498 | * Usage (Pen), | ||
499 | * Collection (Application), | ||
500 | * Report ID (2), | ||
501 | * Usage (Stylus), | ||
502 | * Collection (Physical), | ||
503 | * Usage (00h), | ||
504 | * Logical Minimum (0), | ||
505 | * Logical Maximum (255), | ||
506 | * Report Size (8), | ||
507 | * Report Count (7), | ||
508 | * Input (Variable), | ||
509 | * Usage (Azimuth), | ||
510 | * Usage (Altitude), | ||
511 | * Logical Minimum (0), | ||
512 | * Logical Maximum (255), | ||
513 | * Report Size (8), | ||
514 | * Report Count (2), | ||
515 | * Feature (Variable), | ||
516 | * End Collection, | ||
517 | * Report ID (5), | ||
518 | * Usage Page (Digitizer), | ||
519 | * Usage (Stylus), | ||
520 | * Collection (Physical), | ||
521 | * Usage (00h), | ||
522 | * Logical Minimum (0), | ||
523 | * Logical Maximum (255), | ||
524 | * Report Size (8), | ||
525 | * Report Count (7), | ||
526 | * Input (Variable), | ||
527 | * End Collection, | ||
528 | * Report ID (10), | ||
529 | * Usage Page (Digitizer), | ||
530 | * Usage (Stylus), | ||
531 | * Collection (Physical), | ||
532 | * Usage (00h), | ||
533 | * Logical Minimum (0), | ||
534 | * Logical Maximum (255), | ||
535 | * Report Size (8), | ||
536 | * Report Count (7), | ||
537 | * Input (Variable), | ||
538 | * End Collection, | ||
539 | * Report ID (16), | ||
540 | * Usage (Stylus), | ||
541 | * Collection (Physical), | ||
542 | * Usage (Tip Switch), | ||
543 | * Usage (Barrel Switch), | ||
544 | * Usage (Invert), | ||
545 | * Usage (Eraser), | ||
546 | * Usage (In Range), | ||
547 | * Logical Minimum (0), | ||
548 | * Logical Maximum (1), | ||
549 | * Report Size (1), | ||
550 | * Report Count (5), | ||
551 | * Input (Variable), | ||
552 | * Report Count (3), | ||
553 | * Input (Constant, Variable), | ||
554 | * Usage Page (Desktop), | ||
555 | * Usage (X), | ||
556 | * Report Size (16), | ||
557 | * Report Count (1), | ||
558 | * Push, | ||
559 | * Unit Exponent (13), | ||
560 | * Unit (Inch^3), | ||
561 | * Logical Minimum (0), | ||
562 | * Logical Maximum (18000), | ||
563 | * Physical Minimum (0), | ||
564 | * Physical Maximum (18000), | ||
565 | * Input (Variable), | ||
566 | * Usage (Y), | ||
567 | * Logical Maximum (11000), | ||
568 | * Physical Maximum (11000), | ||
569 | * Input (Variable), | ||
570 | * Usage Page (Digitizer), | ||
571 | * Usage (Tip Pressure), | ||
572 | * Logical Minimum (0), | ||
573 | * Logical Maximum (1023), | ||
574 | * Physical Minimum (0), | ||
575 | * Physical Maximum (1023), | ||
576 | * Input (Variable), | ||
577 | * End Collection, | ||
578 | * End Collection, | ||
579 | * Usage Page (Desktop), | ||
580 | * Usage (Keyboard), | ||
581 | * Collection (Application), | ||
582 | * Report ID (13), | ||
583 | * Usage Page (Keyboard), | ||
584 | * Usage Minimum (KB Leftcontrol), | ||
585 | * Usage Maximum (KB Right GUI), | ||
586 | * Logical Minimum (0), | ||
587 | * Logical Maximum (1), | ||
588 | * Report Size (1), | ||
589 | * Report Count (8), | ||
590 | * Input (Variable), | ||
591 | * Report Size (8), | ||
592 | * Report Count (1), | ||
593 | * Input (Constant), | ||
594 | * Usage Page (Keyboard), | ||
595 | * Usage Minimum (None), | ||
596 | * Usage Maximum (KB Application), | ||
597 | * Logical Minimum (0), | ||
598 | * Logical Maximum (101), | ||
599 | * Report Size (8), | ||
600 | * Report Count (5), | ||
601 | * Input, | ||
602 | * End Collection, | ||
603 | * Usage Page (Consumer), | ||
604 | * Usage (Consumer Control), | ||
605 | * Collection (Application), | ||
606 | * Report ID (12), | ||
607 | * Usage (Volume Inc), | ||
608 | * Usage (Volume Dec), | ||
609 | * Usage (Mute), | ||
610 | * Logical Minimum (0), | ||
611 | * Logical Maximum (1), | ||
612 | * Report Size (1), | ||
613 | * Report Count (3), | ||
614 | * Input (Variable, Relative), | ||
615 | * Report Size (5), | ||
616 | * Report Count (1), | ||
617 | * Input (Constant, Variable, Relative), | ||
618 | * End Collection | ||
619 | */ | ||
620 | |||
621 | /* Size of the original report descriptor of Media Tablet 10.6 inch */ | ||
622 | #define MEDIA_TABLET_10_6_INCH_RDESC_ORIG_SIZE 300 | ||
623 | |||
624 | /* | ||
625 | * Fixed Media Tablet 10.6 inch descriptor. | ||
626 | * | ||
627 | * The descriptions of reports unused in the default configuration are | ||
628 | * removed. The stylus report (ID 16) is fixed similarly to Slim Tablet 5.8 | ||
629 | * inch. The unused mouse report (ID 1) fields are replaced with constant | ||
630 | * padding. | ||
631 | * | ||
632 | * The keyboard report (ID 13) is hacked to instead have an "array" field | ||
633 | * reporting consumer page controls, and all the unused bits are masked out | ||
634 | * with constant padding. The "brush" wheels' function is represented as "Scan | ||
635 | * Previous/Next Track" controls due to the lack of brush controls in the | ||
636 | * usage tables specification. | ||
637 | */ | ||
638 | static __u8 media_tablet_10_6_inch_rdesc_fixed[] = { | ||
639 | 0x05, 0x0D, /* Usage Page (Digitizer), */ | ||
640 | 0x09, 0x02, /* Usage (Pen), */ | ||
641 | 0xA1, 0x01, /* Collection (Application), */ | ||
642 | 0x85, 0x10, /* Report ID (16), */ | ||
643 | 0x09, 0x20, /* Usage (Stylus), */ | ||
644 | 0xA0, /* Collection (Physical), */ | ||
645 | 0x09, 0x42, /* Usage (Tip Switch), */ | ||
646 | 0x09, 0x44, /* Usage (Barrel Switch), */ | ||
647 | 0x09, 0x46, /* Usage (Tablet Pick), */ | ||
648 | 0x15, 0x01, /* Logical Minimum (1), */ | ||
649 | 0x25, 0x03, /* Logical Maximum (3), */ | ||
650 | 0x75, 0x04, /* Report Size (4), */ | ||
651 | 0x95, 0x01, /* Report Count (1), */ | ||
652 | 0x80, /* Input, */ | ||
653 | 0x75, 0x01, /* Report Size (1), */ | ||
654 | 0x09, 0x32, /* Usage (In Range), */ | ||
655 | 0x14, /* Logical Minimum (0), */ | ||
656 | 0x25, 0x01, /* Logical Maximum (1), */ | ||
657 | 0x95, 0x01, /* Report Count (1), */ | ||
658 | 0x81, 0x02, /* Input (Variable), */ | ||
659 | 0x95, 0x03, /* Report Count (3), */ | ||
660 | 0x81, 0x03, /* Input (Constant, Variable), */ | ||
661 | 0x75, 0x10, /* Report Size (16), */ | ||
662 | 0x95, 0x01, /* Report Count (1), */ | ||
663 | 0x14, /* Logical Minimum (0), */ | ||
664 | 0xA4, /* Push, */ | ||
665 | 0x05, 0x01, /* Usage Page (Desktop), */ | ||
666 | 0x65, 0x13, /* Unit (Inch), */ | ||
667 | 0x55, 0xFD, /* Unit Exponent (-3), */ | ||
668 | 0x34, /* Physical Minimum (0), */ | ||
669 | 0x09, 0x30, /* Usage (X), */ | ||
670 | 0x46, 0x28, 0x23, /* Physical Maximum (9000), */ | ||
671 | 0x26, 0x50, 0x46, /* Logical Maximum (18000), */ | ||
672 | 0x81, 0x02, /* Input (Variable), */ | ||
673 | 0x09, 0x31, /* Usage (Y), */ | ||
674 | 0x46, 0x7C, 0x15, /* Physical Maximum (5500), */ | ||
675 | 0x26, 0xF8, 0x2A, /* Logical Maximum (11000), */ | ||
676 | 0x81, 0x02, /* Input (Variable), */ | ||
677 | 0xB4, /* Pop, */ | ||
678 | 0x09, 0x30, /* Usage (Tip Pressure), */ | ||
679 | 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ | ||
680 | 0x81, 0x02, /* Input (Variable), */ | ||
681 | 0xC0, /* End Collection, */ | ||
682 | 0xC0, /* End Collection, */ | ||
683 | 0x05, 0x01, /* Usage Page (Desktop), */ | ||
684 | 0x09, 0x02, /* Usage (Mouse), */ | ||
685 | 0xA1, 0x01, /* Collection (Application), */ | ||
686 | 0x85, 0x01, /* Report ID (1), */ | ||
687 | 0x09, 0x01, /* Usage (Pointer), */ | ||
688 | 0xA0, /* Collection (Physical), */ | ||
689 | 0x75, 0x08, /* Report Size (8), */ | ||
690 | 0x95, 0x03, /* Report Count (3), */ | ||
691 | 0x81, 0x03, /* Input (Constant, Variable), */ | ||
692 | 0x95, 0x02, /* Report Count (2), */ | ||
693 | 0x15, 0xFF, /* Logical Minimum (-1), */ | ||
694 | 0x25, 0x01, /* Logical Maximum (1), */ | ||
695 | 0x09, 0x38, /* Usage (Wheel), */ | ||
696 | 0x0B, 0x38, 0x02, /* Usage (Consumer AC Pan), */ | ||
697 | 0x0C, 0x00, | ||
698 | 0x81, 0x06, /* Input (Variable, Relative), */ | ||
699 | 0x95, 0x02, /* Report Count (2), */ | ||
700 | 0x81, 0x03, /* Input (Constant, Variable), */ | ||
701 | 0xC0, /* End Collection, */ | ||
702 | 0xC0, /* End Collection, */ | ||
703 | 0x05, 0x0C, /* Usage Page (Consumer), */ | ||
704 | 0x09, 0x01, /* Usage (Consumer Control), */ | ||
705 | 0xA1, 0x01, /* Collection (Application), */ | ||
706 | 0x85, 0x0D, /* Report ID (13), */ | ||
707 | 0x95, 0x01, /* Report Count (1), */ | ||
708 | 0x75, 0x10, /* Report Size (16), */ | ||
709 | 0x81, 0x03, /* Input (Constant, Variable), */ | ||
710 | 0x0A, 0x2F, 0x02, /* Usage (AC Zoom), */ | ||
711 | 0x0A, 0x2E, 0x02, /* Usage (AC Zoom Out), */ | ||
712 | 0x0A, 0x2D, 0x02, /* Usage (AC Zoom In), */ | ||
713 | 0x09, 0xB6, /* Usage (Scan Previous Track), */ | ||
714 | 0x09, 0xB5, /* Usage (Scan Next Track), */ | ||
715 | 0x08, /* Usage (00h), */ | ||
716 | 0x08, /* Usage (00h), */ | ||
717 | 0x08, /* Usage (00h), */ | ||
718 | 0x08, /* Usage (00h), */ | ||
719 | 0x08, /* Usage (00h), */ | ||
720 | 0x0A, 0x2E, 0x02, /* Usage (AC Zoom Out), */ | ||
721 | 0x0A, 0x2D, 0x02, /* Usage (AC Zoom In), */ | ||
722 | 0x15, 0x0C, /* Logical Minimum (12), */ | ||
723 | 0x25, 0x17, /* Logical Maximum (23), */ | ||
724 | 0x75, 0x05, /* Report Size (5), */ | ||
725 | 0x80, /* Input, */ | ||
726 | 0x75, 0x03, /* Report Size (3), */ | ||
727 | 0x81, 0x03, /* Input (Constant, Variable), */ | ||
728 | 0x75, 0x20, /* Report Size (32), */ | ||
729 | 0x81, 0x03, /* Input (Constant, Variable), */ | ||
730 | 0xC0, /* End Collection, */ | ||
731 | 0x09, 0x01, /* Usage (Consumer Control), */ | ||
732 | 0xA1, 0x01, /* Collection (Application), */ | ||
733 | 0x85, 0x0C, /* Report ID (12), */ | ||
734 | 0x75, 0x01, /* Report Size (1), */ | ||
735 | 0x09, 0xE9, /* Usage (Volume Inc), */ | ||
736 | 0x09, 0xEA, /* Usage (Volume Dec), */ | ||
737 | 0x09, 0xE2, /* Usage (Mute), */ | ||
738 | 0x14, /* Logical Minimum (0), */ | ||
739 | 0x25, 0x01, /* Logical Maximum (1), */ | ||
740 | 0x95, 0x03, /* Report Count (3), */ | ||
741 | 0x81, 0x06, /* Input (Variable, Relative), */ | ||
742 | 0x95, 0x35, /* Report Count (53), */ | ||
743 | 0x81, 0x03, /* Input (Constant, Variable), */ | ||
744 | 0xC0 /* End Collection */ | ||
745 | }; | ||
746 | |||
747 | /* | ||
748 | * Original Media Tablet 14.1 inch report descriptor. | ||
749 | * | ||
750 | * There are at least two versions of this model in the wild. They are | ||
751 | * represented by Genius G-Pen M712 (older version) and Genius G-Pen M712X | ||
752 | * (newer version). The hardware difference between these versions is the same | ||
753 | * as between older and newer versions of Media Tablet 10.6 inch. The report | ||
754 | * descriptors are identical for both versions. | ||
755 | * | ||
756 | * The function, behavior and report descriptor of this tablet is similar to | ||
757 | * that of Media Tablet 10.6 inch. However, there is one more field (with | ||
758 | * Consumer AC Pan usage) in the mouse description. Then the tablet X and Y | ||
759 | * logical extents both get scaled to 0..16383 range (a hardware limit?), | ||
760 | * which kind of defeats the advertised 4000 LPI resolution, considering the | ||
761 | * physical extents of 12x7.25 inches. Plus, reports 5, 10 and 255 are used | ||
762 | * sometimes (while moving the pen) with unknown purpose. Also, the key codes | ||
763 | * generated for zoom in/out are different. | ||
764 | * | ||
765 | * Usage Page (Desktop), | ||
766 | * Usage (Mouse), | ||
767 | * Collection (Application), | ||
768 | * Report ID (1), | ||
769 | * Usage (Pointer), | ||
770 | * Collection (Physical), | ||
771 | * Usage Page (Button), | ||
772 | * Usage Minimum (01h), | ||
773 | * Usage Maximum (05h), | ||
774 | * Logical Minimum (0), | ||
775 | * Logical Maximum (1), | ||
776 | * Report Size (1), | ||
777 | * Report Count (5), | ||
778 | * Input (Variable), | ||
779 | * Report Size (3), | ||
780 | * Report Count (1), | ||
781 | * Input (Constant, Variable), | ||
782 | * Usage Page (Desktop), | ||
783 | * Usage (X), | ||
784 | * Usage (Y), | ||
785 | * Usage (Wheel), | ||
786 | * Logical Minimum (-127), | ||
787 | * Logical Maximum (127), | ||
788 | * Report Size (8), | ||
789 | * Report Count (3), | ||
790 | * Input (Variable, Relative), | ||
791 | * Usage Page (Consumer), | ||
792 | * Logical Minimum (-127), | ||
793 | * Logical Maximum (127), | ||
794 | * Report Size (8), | ||
795 | * Report Count (1), | ||
796 | * Usage (AC Pan), | ||
797 | * Input (Variable, Relative), | ||
798 | * End Collection, | ||
799 | * End Collection, | ||
800 | * Usage Page (Digitizer), | ||
801 | * Usage (Pen), | ||
802 | * Collection (Application), | ||
803 | * Report ID (2), | ||
804 | * Usage (Stylus), | ||
805 | * Collection (Physical), | ||
806 | * Usage (00h), | ||
807 | * Logical Minimum (0), | ||
808 | * Logical Maximum (255), | ||
809 | * Report Size (8), | ||
810 | * Report Count (7), | ||
811 | * Input (Variable), | ||
812 | * Usage (Azimuth), | ||
813 | * Usage (Altitude), | ||
814 | * Logical Minimum (0), | ||
815 | * Logical Maximum (255), | ||
816 | * Report Size (8), | ||
817 | * Report Count (2), | ||
818 | * Feature (Variable), | ||
819 | * End Collection, | ||
820 | * Report ID (5), | ||
821 | * Usage Page (Digitizer), | ||
822 | * Usage (Stylus), | ||
823 | * Collection (Physical), | ||
824 | * Usage (00h), | ||
825 | * Logical Minimum (0), | ||
826 | * Logical Maximum (255), | ||
827 | * Report Size (8), | ||
828 | * Report Count (7), | ||
829 | * Input (Variable), | ||
830 | * End Collection, | ||
831 | * Report ID (10), | ||
832 | * Usage Page (Digitizer), | ||
833 | * Usage (Stylus), | ||
834 | * Collection (Physical), | ||
835 | * Usage (00h), | ||
836 | * Logical Minimum (0), | ||
837 | * Logical Maximum (255), | ||
838 | * Report Size (8), | ||
839 | * Report Count (7), | ||
840 | * Input (Variable), | ||
841 | * End Collection, | ||
842 | * Report ID (16), | ||
843 | * Usage (Stylus), | ||
844 | * Collection (Physical), | ||
845 | * Usage (Tip Switch), | ||
846 | * Usage (Barrel Switch), | ||
847 | * Usage (Invert), | ||
848 | * Usage (Eraser), | ||
849 | * Usage (In Range), | ||
850 | * Logical Minimum (0), | ||
851 | * Logical Maximum (1), | ||
852 | * Report Size (1), | ||
853 | * Report Count (5), | ||
854 | * Input (Variable), | ||
855 | * Report Count (3), | ||
856 | * Input (Constant, Variable), | ||
857 | * Usage Page (Desktop), | ||
858 | * Usage (X), | ||
859 | * Report Size (16), | ||
860 | * Report Count (1), | ||
861 | * Push, | ||
862 | * Unit Exponent (13), | ||
863 | * Unit (Inch^3), | ||
864 | * Logical Minimum (0), | ||
865 | * Logical Maximum (16383), | ||
866 | * Physical Minimum (0), | ||
867 | * Physical Maximum (16383), | ||
868 | * Input (Variable), | ||
869 | * Usage (Y), | ||
870 | * Input (Variable), | ||
871 | * Usage Page (Digitizer), | ||
872 | * Usage (Tip Pressure), | ||
873 | * Logical Minimum (0), | ||
874 | * Logical Maximum (1023), | ||
875 | * Physical Minimum (0), | ||
876 | * Physical Maximum (1023), | ||
877 | * Input (Variable), | ||
878 | * End Collection, | ||
879 | * End Collection, | ||
880 | * Usage Page (Desktop), | ||
881 | * Usage (Keyboard), | ||
882 | * Collection (Application), | ||
883 | * Report ID (13), | ||
884 | * Usage Page (Keyboard), | ||
885 | * Usage Minimum (KB Leftcontrol), | ||
886 | * Usage Maximum (KB Right GUI), | ||
887 | * Logical Minimum (0), | ||
888 | * Logical Maximum (1), | ||
889 | * Report Size (1), | ||
890 | * Report Count (8), | ||
891 | * Input (Variable), | ||
892 | * Report Size (8), | ||
893 | * Report Count (1), | ||
894 | * Input (Constant), | ||
895 | * Usage Page (Keyboard), | ||
896 | * Usage Minimum (None), | ||
897 | * Usage Maximum (KB Application), | ||
898 | * Logical Minimum (0), | ||
899 | * Logical Maximum (101), | ||
900 | * Report Size (8), | ||
901 | * Report Count (5), | ||
902 | * Input, | ||
903 | * End Collection, | ||
904 | * Usage Page (Consumer), | ||
905 | * Usage (Consumer Control), | ||
906 | * Collection (Application), | ||
907 | * Report ID (12), | ||
908 | * Usage (Volume Inc), | ||
909 | * Usage (Volume Dec), | ||
910 | * Usage (Mute), | ||
911 | * Logical Minimum (0), | ||
912 | * Logical Maximum (1), | ||
913 | * Report Size (1), | ||
914 | * Report Count (3), | ||
915 | * Input (Variable, Relative), | ||
916 | * Report Size (5), | ||
917 | * Report Count (1), | ||
918 | * Input (Constant, Variable, Relative), | ||
919 | * End Collection | ||
920 | */ | ||
921 | |||
922 | /* Size of the original report descriptor of Media Tablet 14.1 inch */ | ||
923 | #define MEDIA_TABLET_14_1_INCH_RDESC_ORIG_SIZE 309 | ||
924 | |||
925 | /* | ||
926 | * Fixed Media Tablet 14.1 inch descriptor. | ||
927 | * It is fixed similarly to the Media Tablet 10.6 inch descriptor. | ||
928 | */ | ||
929 | static __u8 media_tablet_14_1_inch_rdesc_fixed[] = { | ||
930 | 0x05, 0x0D, /* Usage Page (Digitizer), */ | ||
931 | 0x09, 0x02, /* Usage (Pen), */ | ||
932 | 0xA1, 0x01, /* Collection (Application), */ | ||
933 | 0x85, 0x10, /* Report ID (16), */ | ||
934 | 0x09, 0x20, /* Usage (Stylus), */ | ||
935 | 0xA0, /* Collection (Physical), */ | ||
936 | 0x09, 0x42, /* Usage (Tip Switch), */ | ||
937 | 0x09, 0x44, /* Usage (Barrel Switch), */ | ||
938 | 0x09, 0x46, /* Usage (Tablet Pick), */ | ||
939 | 0x15, 0x01, /* Logical Minimum (1), */ | ||
940 | 0x25, 0x03, /* Logical Maximum (3), */ | ||
941 | 0x75, 0x04, /* Report Size (4), */ | ||
942 | 0x95, 0x01, /* Report Count (1), */ | ||
943 | 0x80, /* Input, */ | ||
944 | 0x75, 0x01, /* Report Size (1), */ | ||
945 | 0x09, 0x32, /* Usage (In Range), */ | ||
946 | 0x14, /* Logical Minimum (0), */ | ||
947 | 0x25, 0x01, /* Logical Maximum (1), */ | ||
948 | 0x95, 0x01, /* Report Count (1), */ | ||
949 | 0x81, 0x02, /* Input (Variable), */ | ||
950 | 0x95, 0x03, /* Report Count (3), */ | ||
951 | 0x81, 0x03, /* Input (Constant, Variable), */ | ||
952 | 0x75, 0x10, /* Report Size (16), */ | ||
953 | 0x95, 0x01, /* Report Count (1), */ | ||
954 | 0x14, /* Logical Minimum (0), */ | ||
955 | 0xA4, /* Push, */ | ||
956 | 0x05, 0x01, /* Usage Page (Desktop), */ | ||
957 | 0x65, 0x13, /* Unit (Inch), */ | ||
958 | 0x55, 0xFD, /* Unit Exponent (-3), */ | ||
959 | 0x34, /* Physical Minimum (0), */ | ||
960 | 0x09, 0x30, /* Usage (X), */ | ||
961 | 0x46, 0xE0, 0x2E, /* Physical Maximum (12000), */ | ||
962 | 0x26, 0xFF, 0x3F, /* Logical Maximum (16383), */ | ||
963 | 0x81, 0x02, /* Input (Variable), */ | ||
964 | 0x09, 0x31, /* Usage (Y), */ | ||
965 | 0x46, 0x52, 0x1C, /* Physical Maximum (7250), */ | ||
966 | 0x26, 0xFF, 0x3F, /* Logical Maximum (16383), */ | ||
967 | 0x81, 0x02, /* Input (Variable), */ | ||
968 | 0xB4, /* Pop, */ | ||
969 | 0x09, 0x30, /* Usage (Tip Pressure), */ | ||
970 | 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ | ||
971 | 0x81, 0x02, /* Input (Variable), */ | ||
972 | 0xC0, /* End Collection, */ | ||
973 | 0xC0, /* End Collection, */ | ||
974 | 0x05, 0x01, /* Usage Page (Desktop), */ | ||
975 | 0x09, 0x02, /* Usage (Mouse), */ | ||
976 | 0xA1, 0x01, /* Collection (Application), */ | ||
977 | 0x85, 0x01, /* Report ID (1), */ | ||
978 | 0x09, 0x01, /* Usage (Pointer), */ | ||
979 | 0xA0, /* Collection (Physical), */ | ||
980 | 0x75, 0x08, /* Report Size (8), */ | ||
981 | 0x95, 0x03, /* Report Count (3), */ | ||
982 | 0x81, 0x03, /* Input (Constant, Variable), */ | ||
983 | 0x95, 0x02, /* Report Count (2), */ | ||
984 | 0x15, 0xFF, /* Logical Minimum (-1), */ | ||
985 | 0x25, 0x01, /* Logical Maximum (1), */ | ||
986 | 0x09, 0x38, /* Usage (Wheel), */ | ||
987 | 0x0B, 0x38, 0x02, /* Usage (Consumer AC Pan), */ | ||
988 | 0x0C, 0x00, | ||
989 | 0x81, 0x06, /* Input (Variable, Relative), */ | ||
990 | 0xC0, /* End Collection, */ | ||
991 | 0xC0, /* End Collection, */ | ||
992 | 0x05, 0x0C, /* Usage Page (Consumer), */ | ||
993 | 0x09, 0x01, /* Usage (Consumer Control), */ | ||
994 | 0xA1, 0x01, /* Collection (Application), */ | ||
995 | 0x85, 0x0D, /* Report ID (13), */ | ||
996 | 0x95, 0x01, /* Report Count (1), */ | ||
997 | 0x75, 0x10, /* Report Size (16), */ | ||
998 | 0x81, 0x03, /* Input (Constant, Variable), */ | ||
999 | 0x0A, 0x2F, 0x02, /* Usage (AC Zoom), */ | ||
1000 | 0x0A, 0x2E, 0x02, /* Usage (AC Zoom Out), */ | ||
1001 | 0x0A, 0x2D, 0x02, /* Usage (AC Zoom In), */ | ||
1002 | 0x09, 0xB6, /* Usage (Scan Previous Track), */ | ||
1003 | 0x09, 0xB5, /* Usage (Scan Next Track), */ | ||
1004 | 0x08, /* Usage (00h), */ | ||
1005 | 0x08, /* Usage (00h), */ | ||
1006 | 0x08, /* Usage (00h), */ | ||
1007 | 0x08, /* Usage (00h), */ | ||
1008 | 0x08, /* Usage (00h), */ | ||
1009 | 0x0A, 0x2E, 0x02, /* Usage (AC Zoom Out), */ | ||
1010 | 0x0A, 0x2D, 0x02, /* Usage (AC Zoom In), */ | ||
1011 | 0x15, 0x0C, /* Logical Minimum (12), */ | ||
1012 | 0x25, 0x17, /* Logical Maximum (23), */ | ||
1013 | 0x75, 0x05, /* Report Size (5), */ | ||
1014 | 0x80, /* Input, */ | ||
1015 | 0x75, 0x03, /* Report Size (3), */ | ||
1016 | 0x81, 0x03, /* Input (Constant, Variable), */ | ||
1017 | 0x75, 0x20, /* Report Size (32), */ | ||
1018 | 0x81, 0x03, /* Input (Constant, Variable), */ | ||
1019 | 0xC0, /* End Collection, */ | ||
1020 | 0x09, 0x01, /* Usage (Consumer Control), */ | ||
1021 | 0xA1, 0x01, /* Collection (Application), */ | ||
1022 | 0x85, 0x0C, /* Report ID (12), */ | ||
1023 | 0x75, 0x01, /* Report Size (1), */ | ||
1024 | 0x09, 0xE9, /* Usage (Volume Inc), */ | ||
1025 | 0x09, 0xEA, /* Usage (Volume Dec), */ | ||
1026 | 0x09, 0xE2, /* Usage (Mute), */ | ||
1027 | 0x14, /* Logical Minimum (0), */ | ||
1028 | 0x25, 0x01, /* Logical Maximum (1), */ | ||
1029 | 0x95, 0x03, /* Report Count (3), */ | ||
1030 | 0x81, 0x06, /* Input (Variable, Relative), */ | ||
1031 | 0x75, 0x05, /* Report Size (5), */ | ||
1032 | 0x81, 0x03, /* Input (Constant, Variable), */ | ||
1033 | 0xC0 /* End Collection */ | ||
1034 | }; | ||
1035 | |||
1036 | static __u8 *waltop_report_fixup(struct hid_device *hdev, __u8 *rdesc, | ||
1037 | unsigned int *rsize) | ||
1038 | { | ||
1039 | switch (hdev->product) { | ||
1040 | case USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH: | ||
1041 | if (*rsize == SLIM_TABLET_5_8_INCH_RDESC_ORIG_SIZE) { | ||
1042 | rdesc = slim_tablet_5_8_inch_rdesc_fixed; | ||
1043 | *rsize = sizeof(slim_tablet_5_8_inch_rdesc_fixed); | ||
1044 | } | ||
1045 | break; | ||
1046 | case USB_DEVICE_ID_WALTOP_SLIM_TABLET_12_1_INCH: | ||
1047 | if (*rsize == SLIM_TABLET_12_1_INCH_RDESC_ORIG_SIZE) { | ||
1048 | rdesc = slim_tablet_12_1_inch_rdesc_fixed; | ||
1049 | *rsize = sizeof(slim_tablet_12_1_inch_rdesc_fixed); | ||
1050 | } | ||
1051 | break; | ||
1052 | case USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH: | ||
1053 | if (*rsize == MEDIA_TABLET_10_6_INCH_RDESC_ORIG_SIZE) { | ||
1054 | rdesc = media_tablet_10_6_inch_rdesc_fixed; | ||
1055 | *rsize = sizeof(media_tablet_10_6_inch_rdesc_fixed); | ||
1056 | } | ||
1057 | break; | ||
1058 | case USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH: | ||
1059 | if (*rsize == MEDIA_TABLET_14_1_INCH_RDESC_ORIG_SIZE) { | ||
1060 | rdesc = media_tablet_14_1_inch_rdesc_fixed; | ||
1061 | *rsize = sizeof(media_tablet_14_1_inch_rdesc_fixed); | ||
1062 | } | ||
1063 | break; | ||
1064 | } | ||
1065 | return rdesc; | ||
1066 | } | ||
1067 | |||
1068 | static const struct hid_device_id waltop_devices[] = { | ||
1069 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, | ||
1070 | USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH) }, | ||
1071 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, | ||
1072 | USB_DEVICE_ID_WALTOP_SLIM_TABLET_12_1_INCH) }, | ||
1073 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, | ||
1074 | USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH) }, | ||
1075 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, | ||
1076 | USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH) }, | ||
1077 | { } | ||
1078 | }; | ||
1079 | MODULE_DEVICE_TABLE(hid, waltop_devices); | ||
1080 | |||
1081 | static struct hid_driver waltop_driver = { | ||
1082 | .name = "waltop", | ||
1083 | .id_table = waltop_devices, | ||
1084 | .report_fixup = waltop_report_fixup, | ||
1085 | }; | ||
1086 | |||
1087 | static int __init waltop_init(void) | ||
1088 | { | ||
1089 | return hid_register_driver(&waltop_driver); | ||
1090 | } | ||
1091 | |||
1092 | static void __exit waltop_exit(void) | ||
1093 | { | ||
1094 | hid_unregister_driver(&waltop_driver); | ||
1095 | } | ||
1096 | |||
1097 | module_init(waltop_init); | ||
1098 | module_exit(waltop_exit); | ||
1099 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/hid/hid-zpff.c b/drivers/hid/hid-zpff.c index b7acceabba80..f31fab012f2f 100644 --- a/drivers/hid/hid-zpff.c +++ b/drivers/hid/hid-zpff.c | |||
@@ -75,14 +75,14 @@ static int zpff_init(struct hid_device *hid) | |||
75 | int error; | 75 | int error; |
76 | 76 | ||
77 | if (list_empty(report_list)) { | 77 | if (list_empty(report_list)) { |
78 | dev_err(&hid->dev, "no output report found\n"); | 78 | hid_err(hid, "no output report found\n"); |
79 | return -ENODEV; | 79 | return -ENODEV; |
80 | } | 80 | } |
81 | 81 | ||
82 | report = list_entry(report_list->next, struct hid_report, list); | 82 | report = list_entry(report_list->next, struct hid_report, list); |
83 | 83 | ||
84 | if (report->maxfield < 4) { | 84 | if (report->maxfield < 4) { |
85 | dev_err(&hid->dev, "not enough fields in report\n"); | 85 | hid_err(hid, "not enough fields in report\n"); |
86 | return -ENODEV; | 86 | return -ENODEV; |
87 | } | 87 | } |
88 | 88 | ||
@@ -105,8 +105,7 @@ static int zpff_init(struct hid_device *hid) | |||
105 | zpff->report->field[3]->value[0] = 0x00; | 105 | zpff->report->field[3]->value[0] = 0x00; |
106 | usbhid_submit_report(hid, zpff->report, USB_DIR_OUT); | 106 | usbhid_submit_report(hid, zpff->report, USB_DIR_OUT); |
107 | 107 | ||
108 | dev_info(&hid->dev, "force feedback for Zeroplus based devices by " | 108 | hid_info(hid, "force feedback for Zeroplus based devices by Anssi Hannula <anssi.hannula@gmail.com>\n"); |
109 | "Anssi Hannula <anssi.hannula@gmail.com>\n"); | ||
110 | 109 | ||
111 | return 0; | 110 | return 0; |
112 | } | 111 | } |
@@ -123,13 +122,13 @@ static int zp_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
123 | 122 | ||
124 | ret = hid_parse(hdev); | 123 | ret = hid_parse(hdev); |
125 | if (ret) { | 124 | if (ret) { |
126 | dev_err(&hdev->dev, "parse failed\n"); | 125 | hid_err(hdev, "parse failed\n"); |
127 | goto err; | 126 | goto err; |
128 | } | 127 | } |
129 | 128 | ||
130 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); | 129 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); |
131 | if (ret) { | 130 | if (ret) { |
132 | dev_err(&hdev->dev, "hw start failed\n"); | 131 | hid_err(hdev, "hw start failed\n"); |
133 | goto err; | 132 | goto err; |
134 | } | 133 | } |
135 | 134 | ||
diff --git a/drivers/hid/hid-zydacron.c b/drivers/hid/hid-zydacron.c index 9e8d35a203e4..e90371508fd2 100644 --- a/drivers/hid/hid-zydacron.c +++ b/drivers/hid/hid-zydacron.c | |||
@@ -27,19 +27,19 @@ struct zc_device { | |||
27 | * Zydacron remote control has an invalid HID report descriptor, | 27 | * Zydacron remote control has an invalid HID report descriptor, |
28 | * that needs fixing before we can parse it. | 28 | * that needs fixing before we can parse it. |
29 | */ | 29 | */ |
30 | static void zc_report_fixup(struct hid_device *hdev, __u8 *rdesc, | 30 | static __u8 *zc_report_fixup(struct hid_device *hdev, __u8 *rdesc, |
31 | unsigned int rsize) | 31 | unsigned int *rsize) |
32 | { | 32 | { |
33 | if (rsize >= 253 && | 33 | if (*rsize >= 253 && |
34 | rdesc[0x96] == 0xbc && rdesc[0x97] == 0xff && | 34 | rdesc[0x96] == 0xbc && rdesc[0x97] == 0xff && |
35 | rdesc[0xca] == 0xbc && rdesc[0xcb] == 0xff && | 35 | rdesc[0xca] == 0xbc && rdesc[0xcb] == 0xff && |
36 | rdesc[0xe1] == 0xbc && rdesc[0xe2] == 0xff) { | 36 | rdesc[0xe1] == 0xbc && rdesc[0xe2] == 0xff) { |
37 | dev_info(&hdev->dev, | 37 | hid_info(hdev, |
38 | "fixing up zydacron remote control report " | 38 | "fixing up zydacron remote control report descriptor\n"); |
39 | "descriptor\n"); | ||
40 | rdesc[0x96] = rdesc[0xca] = rdesc[0xe1] = 0x0c; | 39 | rdesc[0x96] = rdesc[0xca] = rdesc[0xe1] = 0x0c; |
41 | rdesc[0x97] = rdesc[0xcb] = rdesc[0xe2] = 0x00; | 40 | rdesc[0x97] = rdesc[0xcb] = rdesc[0xe2] = 0x00; |
42 | } | 41 | } |
42 | return rdesc; | ||
43 | } | 43 | } |
44 | 44 | ||
45 | #define zc_map_key_clear(c) \ | 45 | #define zc_map_key_clear(c) \ |
@@ -171,7 +171,7 @@ static int zc_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
171 | 171 | ||
172 | zc = kzalloc(sizeof(*zc), GFP_KERNEL); | 172 | zc = kzalloc(sizeof(*zc), GFP_KERNEL); |
173 | if (zc == NULL) { | 173 | if (zc == NULL) { |
174 | dev_err(&hdev->dev, "zydacron: can't alloc descriptor\n"); | 174 | hid_err(hdev, "can't alloc descriptor\n"); |
175 | return -ENOMEM; | 175 | return -ENOMEM; |
176 | } | 176 | } |
177 | 177 | ||
@@ -179,13 +179,13 @@ static int zc_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
179 | 179 | ||
180 | ret = hid_parse(hdev); | 180 | ret = hid_parse(hdev); |
181 | if (ret) { | 181 | if (ret) { |
182 | dev_err(&hdev->dev, "zydacron: parse failed\n"); | 182 | hid_err(hdev, "parse failed\n"); |
183 | goto err_free; | 183 | goto err_free; |
184 | } | 184 | } |
185 | 185 | ||
186 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); | 186 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); |
187 | if (ret) { | 187 | if (ret) { |
188 | dev_err(&hdev->dev, "zydacron: hw start failed\n"); | 188 | hid_err(hdev, "hw start failed\n"); |
189 | goto err_free; | 189 | goto err_free; |
190 | } | 190 | } |
191 | 191 | ||
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c index a3866b5c0c43..c79578b5a788 100644 --- a/drivers/hid/hidraw.c +++ b/drivers/hid/hidraw.c | |||
@@ -19,6 +19,8 @@ | |||
19 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | 19 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
23 | |||
22 | #include <linux/fs.h> | 24 | #include <linux/fs.h> |
23 | #include <linux/module.h> | 25 | #include <linux/module.h> |
24 | #include <linux/errno.h> | 26 | #include <linux/errno.h> |
@@ -32,7 +34,6 @@ | |||
32 | #include <linux/hid.h> | 34 | #include <linux/hid.h> |
33 | #include <linux/mutex.h> | 35 | #include <linux/mutex.h> |
34 | #include <linux/sched.h> | 36 | #include <linux/sched.h> |
35 | #include <linux/smp_lock.h> | ||
36 | 37 | ||
37 | #include <linux/hidraw.h> | 38 | #include <linux/hidraw.h> |
38 | 39 | ||
@@ -90,7 +91,7 @@ static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count, | |||
90 | ret = -EFAULT; | 91 | ret = -EFAULT; |
91 | goto out; | 92 | goto out; |
92 | } | 93 | } |
93 | ret += len; | 94 | ret = len; |
94 | 95 | ||
95 | kfree(list->buffer[list->tail].value); | 96 | kfree(list->buffer[list->tail].value); |
96 | list->tail = (list->tail + 1) & (HIDRAW_BUFFER_SIZE - 1); | 97 | list->tail = (list->tail + 1) & (HIDRAW_BUFFER_SIZE - 1); |
@@ -100,16 +101,15 @@ out: | |||
100 | return ret; | 101 | return ret; |
101 | } | 102 | } |
102 | 103 | ||
103 | /* the first byte is expected to be a report number */ | 104 | /* The first byte is expected to be a report number. |
104 | static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) | 105 | * This function is to be called with the minors_lock mutex held */ |
106 | static ssize_t hidraw_send_report(struct file *file, const char __user *buffer, size_t count, unsigned char report_type) | ||
105 | { | 107 | { |
106 | unsigned int minor = iminor(file->f_path.dentry->d_inode); | 108 | unsigned int minor = iminor(file->f_path.dentry->d_inode); |
107 | struct hid_device *dev; | 109 | struct hid_device *dev; |
108 | __u8 *buf; | 110 | __u8 *buf; |
109 | int ret = 0; | 111 | int ret = 0; |
110 | 112 | ||
111 | mutex_lock(&minors_lock); | ||
112 | |||
113 | if (!hidraw_table[minor]) { | 113 | if (!hidraw_table[minor]) { |
114 | ret = -ENODEV; | 114 | ret = -ENODEV; |
115 | goto out; | 115 | goto out; |
@@ -123,6 +123,70 @@ static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t | |||
123 | } | 123 | } |
124 | 124 | ||
125 | if (count > HID_MAX_BUFFER_SIZE) { | 125 | if (count > HID_MAX_BUFFER_SIZE) { |
126 | hid_warn(dev, "pid %d passed too large report\n", | ||
127 | task_pid_nr(current)); | ||
128 | ret = -EINVAL; | ||
129 | goto out; | ||
130 | } | ||
131 | |||
132 | if (count < 2) { | ||
133 | hid_warn(dev, "pid %d passed too short report\n", | ||
134 | task_pid_nr(current)); | ||
135 | ret = -EINVAL; | ||
136 | goto out; | ||
137 | } | ||
138 | |||
139 | buf = kmalloc(count * sizeof(__u8), GFP_KERNEL); | ||
140 | if (!buf) { | ||
141 | ret = -ENOMEM; | ||
142 | goto out; | ||
143 | } | ||
144 | |||
145 | if (copy_from_user(buf, buffer, count)) { | ||
146 | ret = -EFAULT; | ||
147 | goto out_free; | ||
148 | } | ||
149 | |||
150 | ret = dev->hid_output_raw_report(dev, buf, count, report_type); | ||
151 | out_free: | ||
152 | kfree(buf); | ||
153 | out: | ||
154 | return ret; | ||
155 | } | ||
156 | |||
157 | /* the first byte is expected to be a report number */ | ||
158 | static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) | ||
159 | { | ||
160 | ssize_t ret; | ||
161 | mutex_lock(&minors_lock); | ||
162 | ret = hidraw_send_report(file, buffer, count, HID_OUTPUT_REPORT); | ||
163 | mutex_unlock(&minors_lock); | ||
164 | return ret; | ||
165 | } | ||
166 | |||
167 | |||
168 | /* This function performs a Get_Report transfer over the control endpoint | ||
169 | * per section 7.2.1 of the HID specification, version 1.1. The first byte | ||
170 | * of buffer is the report number to request, or 0x0 if the defice does not | ||
171 | * use numbered reports. The report_type parameter can be HID_FEATURE_REPORT | ||
172 | * or HID_INPUT_REPORT. This function is to be called with the minors_lock | ||
173 | * mutex held. */ | ||
174 | static ssize_t hidraw_get_report(struct file *file, char __user *buffer, size_t count, unsigned char report_type) | ||
175 | { | ||
176 | unsigned int minor = iminor(file->f_path.dentry->d_inode); | ||
177 | struct hid_device *dev; | ||
178 | __u8 *buf; | ||
179 | int ret = 0, len; | ||
180 | unsigned char report_number; | ||
181 | |||
182 | dev = hidraw_table[minor]->hid; | ||
183 | |||
184 | if (!dev->hid_get_raw_report) { | ||
185 | ret = -ENODEV; | ||
186 | goto out; | ||
187 | } | ||
188 | |||
189 | if (count > HID_MAX_BUFFER_SIZE) { | ||
126 | printk(KERN_WARNING "hidraw: pid %d passed too large report\n", | 190 | printk(KERN_WARNING "hidraw: pid %d passed too large report\n", |
127 | task_pid_nr(current)); | 191 | task_pid_nr(current)); |
128 | ret = -EINVAL; | 192 | ret = -EINVAL; |
@@ -142,16 +206,30 @@ static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t | |||
142 | goto out; | 206 | goto out; |
143 | } | 207 | } |
144 | 208 | ||
145 | if (copy_from_user(buf, buffer, count)) { | 209 | /* Read the first byte from the user. This is the report number, |
210 | * which is passed to dev->hid_get_raw_report(). */ | ||
211 | if (copy_from_user(&report_number, buffer, 1)) { | ||
212 | ret = -EFAULT; | ||
213 | goto out_free; | ||
214 | } | ||
215 | |||
216 | ret = dev->hid_get_raw_report(dev, report_number, buf, count, report_type); | ||
217 | |||
218 | if (ret < 0) | ||
219 | goto out_free; | ||
220 | |||
221 | len = (ret < count) ? ret : count; | ||
222 | |||
223 | if (copy_to_user(buffer, buf, len)) { | ||
146 | ret = -EFAULT; | 224 | ret = -EFAULT; |
147 | goto out_free; | 225 | goto out_free; |
148 | } | 226 | } |
149 | 227 | ||
150 | ret = dev->hid_output_raw_report(dev, buf, count, HID_OUTPUT_REPORT); | 228 | ret = len; |
229 | |||
151 | out_free: | 230 | out_free: |
152 | kfree(buf); | 231 | kfree(buf); |
153 | out: | 232 | out: |
154 | mutex_unlock(&minors_lock); | ||
155 | return ret; | 233 | return ret; |
156 | } | 234 | } |
157 | 235 | ||
@@ -193,15 +271,13 @@ static int hidraw_open(struct inode *inode, struct file *file) | |||
193 | 271 | ||
194 | dev = hidraw_table[minor]; | 272 | dev = hidraw_table[minor]; |
195 | if (!dev->open++) { | 273 | if (!dev->open++) { |
196 | if (dev->hid->ll_driver->power) { | 274 | err = hid_hw_power(dev->hid, PM_HINT_FULLON); |
197 | err = dev->hid->ll_driver->power(dev->hid, PM_HINT_FULLON); | 275 | if (err < 0) |
198 | if (err < 0) | 276 | goto out_unlock; |
199 | goto out_unlock; | 277 | |
200 | } | 278 | err = hid_hw_open(dev->hid); |
201 | err = dev->hid->ll_driver->open(dev->hid); | ||
202 | if (err < 0) { | 279 | if (err < 0) { |
203 | if (dev->hid->ll_driver->power) | 280 | hid_hw_power(dev->hid, PM_HINT_NORMAL); |
204 | dev->hid->ll_driver->power(dev->hid, PM_HINT_NORMAL); | ||
205 | dev->open--; | 281 | dev->open--; |
206 | } | 282 | } |
207 | } | 283 | } |
@@ -218,25 +294,30 @@ static int hidraw_release(struct inode * inode, struct file * file) | |||
218 | unsigned int minor = iminor(inode); | 294 | unsigned int minor = iminor(inode); |
219 | struct hidraw *dev; | 295 | struct hidraw *dev; |
220 | struct hidraw_list *list = file->private_data; | 296 | struct hidraw_list *list = file->private_data; |
297 | int ret; | ||
221 | 298 | ||
222 | if (!hidraw_table[minor]) | 299 | mutex_lock(&minors_lock); |
223 | return -ENODEV; | 300 | if (!hidraw_table[minor]) { |
301 | ret = -ENODEV; | ||
302 | goto unlock; | ||
303 | } | ||
224 | 304 | ||
225 | list_del(&list->node); | 305 | list_del(&list->node); |
226 | dev = hidraw_table[minor]; | 306 | dev = hidraw_table[minor]; |
227 | if (!--dev->open) { | 307 | if (!--dev->open) { |
228 | if (list->hidraw->exist) { | 308 | if (list->hidraw->exist) { |
229 | if (dev->hid->ll_driver->power) | 309 | hid_hw_power(dev->hid, PM_HINT_NORMAL); |
230 | dev->hid->ll_driver->power(dev->hid, PM_HINT_NORMAL); | 310 | hid_hw_close(dev->hid); |
231 | dev->hid->ll_driver->close(dev->hid); | ||
232 | } else { | 311 | } else { |
233 | kfree(list->hidraw); | 312 | kfree(list->hidraw); |
234 | } | 313 | } |
235 | } | 314 | } |
236 | |||
237 | kfree(list); | 315 | kfree(list); |
316 | ret = 0; | ||
317 | unlock: | ||
318 | mutex_unlock(&minors_lock); | ||
238 | 319 | ||
239 | return 0; | 320 | return ret; |
240 | } | 321 | } |
241 | 322 | ||
242 | static long hidraw_ioctl(struct file *file, unsigned int cmd, | 323 | static long hidraw_ioctl(struct file *file, unsigned int cmd, |
@@ -291,18 +372,30 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd, | |||
291 | default: | 372 | default: |
292 | { | 373 | { |
293 | struct hid_device *hid = dev->hid; | 374 | struct hid_device *hid = dev->hid; |
294 | if (_IOC_TYPE(cmd) != 'H' || _IOC_DIR(cmd) != _IOC_READ) { | 375 | if (_IOC_TYPE(cmd) != 'H') { |
376 | ret = -EINVAL; | ||
377 | break; | ||
378 | } | ||
379 | |||
380 | if (_IOC_NR(cmd) == _IOC_NR(HIDIOCSFEATURE(0))) { | ||
381 | int len = _IOC_SIZE(cmd); | ||
382 | ret = hidraw_send_report(file, user_arg, len, HID_FEATURE_REPORT); | ||
383 | break; | ||
384 | } | ||
385 | if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGFEATURE(0))) { | ||
386 | int len = _IOC_SIZE(cmd); | ||
387 | ret = hidraw_get_report(file, user_arg, len, HID_FEATURE_REPORT); | ||
388 | break; | ||
389 | } | ||
390 | |||
391 | /* Begin Read-only ioctls. */ | ||
392 | if (_IOC_DIR(cmd) != _IOC_READ) { | ||
295 | ret = -EINVAL; | 393 | ret = -EINVAL; |
296 | break; | 394 | break; |
297 | } | 395 | } |
298 | 396 | ||
299 | if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWNAME(0))) { | 397 | if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWNAME(0))) { |
300 | int len; | 398 | int len = strlen(hid->name) + 1; |
301 | if (!hid->name) { | ||
302 | ret = 0; | ||
303 | break; | ||
304 | } | ||
305 | len = strlen(hid->name) + 1; | ||
306 | if (len > _IOC_SIZE(cmd)) | 399 | if (len > _IOC_SIZE(cmd)) |
307 | len = _IOC_SIZE(cmd); | 400 | len = _IOC_SIZE(cmd); |
308 | ret = copy_to_user(user_arg, hid->name, len) ? | 401 | ret = copy_to_user(user_arg, hid->name, len) ? |
@@ -311,19 +404,14 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd, | |||
311 | } | 404 | } |
312 | 405 | ||
313 | if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWPHYS(0))) { | 406 | if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWPHYS(0))) { |
314 | int len; | 407 | int len = strlen(hid->phys) + 1; |
315 | if (!hid->phys) { | ||
316 | ret = 0; | ||
317 | break; | ||
318 | } | ||
319 | len = strlen(hid->phys) + 1; | ||
320 | if (len > _IOC_SIZE(cmd)) | 408 | if (len > _IOC_SIZE(cmd)) |
321 | len = _IOC_SIZE(cmd); | 409 | len = _IOC_SIZE(cmd); |
322 | ret = copy_to_user(user_arg, hid->phys, len) ? | 410 | ret = copy_to_user(user_arg, hid->phys, len) ? |
323 | -EFAULT : len; | 411 | -EFAULT : len; |
324 | break; | 412 | break; |
325 | } | 413 | } |
326 | } | 414 | } |
327 | 415 | ||
328 | ret = -ENOTTY; | 416 | ret = -ENOTTY; |
329 | } | 417 | } |
@@ -340,6 +428,10 @@ static const struct file_operations hidraw_ops = { | |||
340 | .open = hidraw_open, | 428 | .open = hidraw_open, |
341 | .release = hidraw_release, | 429 | .release = hidraw_release, |
342 | .unlocked_ioctl = hidraw_ioctl, | 430 | .unlocked_ioctl = hidraw_ioctl, |
431 | #ifdef CONFIG_COMPAT | ||
432 | .compat_ioctl = hidraw_ioctl, | ||
433 | #endif | ||
434 | .llseek = noop_llseek, | ||
343 | }; | 435 | }; |
344 | 436 | ||
345 | void hidraw_report_event(struct hid_device *hid, u8 *data, int len) | 437 | void hidraw_report_event(struct hid_device *hid, u8 *data, int len) |
@@ -420,14 +512,14 @@ void hidraw_disconnect(struct hid_device *hid) | |||
420 | 512 | ||
421 | hidraw->exist = 0; | 513 | hidraw->exist = 0; |
422 | 514 | ||
515 | device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor)); | ||
516 | |||
423 | mutex_lock(&minors_lock); | 517 | mutex_lock(&minors_lock); |
424 | hidraw_table[hidraw->minor] = NULL; | 518 | hidraw_table[hidraw->minor] = NULL; |
425 | mutex_unlock(&minors_lock); | 519 | mutex_unlock(&minors_lock); |
426 | 520 | ||
427 | device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor)); | ||
428 | |||
429 | if (hidraw->open) { | 521 | if (hidraw->open) { |
430 | hid->ll_driver->close(hid); | 522 | hid_hw_close(hid); |
431 | wake_up_interruptible(&hidraw->wait); | 523 | wake_up_interruptible(&hidraw->wait); |
432 | } else { | 524 | } else { |
433 | kfree(hidraw); | 525 | kfree(hidraw); |
@@ -446,7 +538,7 @@ int __init hidraw_init(void) | |||
446 | hidraw_major = MAJOR(dev_id); | 538 | hidraw_major = MAJOR(dev_id); |
447 | 539 | ||
448 | if (result < 0) { | 540 | if (result < 0) { |
449 | printk(KERN_WARNING "hidraw: can't get major number\n"); | 541 | pr_warn("can't get major number\n"); |
450 | result = 0; | 542 | result = 0; |
451 | goto out; | 543 | goto out; |
452 | } | 544 | } |
diff --git a/drivers/hid/usbhid/Kconfig b/drivers/hid/usbhid/Kconfig index 4edb3bef94a6..0f20fd17cf06 100644 --- a/drivers/hid/usbhid/Kconfig +++ b/drivers/hid/usbhid/Kconfig | |||
@@ -45,7 +45,7 @@ config USB_HIDDEV | |||
45 | If unsure, say Y. | 45 | If unsure, say Y. |
46 | 46 | ||
47 | menu "USB HID Boot Protocol drivers" | 47 | menu "USB HID Boot Protocol drivers" |
48 | depends on USB!=n && USB_HID!=y && EMBEDDED | 48 | depends on USB!=n && USB_HID!=y && EXPERT |
49 | 49 | ||
50 | config USB_KBD | 50 | config USB_KBD |
51 | tristate "USB HIDBP Keyboard (simple Boot) support" | 51 | tristate "USB HIDBP Keyboard (simple Boot) support" |
diff --git a/drivers/hid/usbhid/Makefile b/drivers/hid/usbhid/Makefile index 1329ecb37a1c..db3cf31c6fa1 100644 --- a/drivers/hid/usbhid/Makefile +++ b/drivers/hid/usbhid/Makefile | |||
@@ -3,15 +3,15 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | # Multipart objects. | 5 | # Multipart objects. |
6 | usbhid-objs := hid-core.o hid-quirks.o | 6 | usbhid-y := hid-core.o hid-quirks.o |
7 | 7 | ||
8 | # Optional parts of multipart objects. | 8 | # Optional parts of multipart objects. |
9 | 9 | ||
10 | ifeq ($(CONFIG_USB_HIDDEV),y) | 10 | ifeq ($(CONFIG_USB_HIDDEV),y) |
11 | usbhid-objs += hiddev.o | 11 | usbhid-y += hiddev.o |
12 | endif | 12 | endif |
13 | ifeq ($(CONFIG_HID_PID),y) | 13 | ifeq ($(CONFIG_HID_PID),y) |
14 | usbhid-objs += hid-pidff.o | 14 | usbhid-y += hid-pidff.o |
15 | endif | 15 | endif |
16 | 16 | ||
17 | obj-$(CONFIG_USB_HID) += usbhid.o | 17 | obj-$(CONFIG_USB_HID) += usbhid.o |
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 599041a7f670..38c261a40c74 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c | |||
@@ -67,7 +67,6 @@ MODULE_PARM_DESC(quirks, "Add/modify USB HID quirks by specifying " | |||
67 | * Input submission and I/O error handler. | 67 | * Input submission and I/O error handler. |
68 | */ | 68 | */ |
69 | static DEFINE_MUTEX(hid_open_mut); | 69 | static DEFINE_MUTEX(hid_open_mut); |
70 | static struct workqueue_struct *resumption_waker; | ||
71 | 70 | ||
72 | static void hid_io_error(struct hid_device *hid); | 71 | static void hid_io_error(struct hid_device *hid); |
73 | static int hid_submit_out(struct hid_device *hid); | 72 | static int hid_submit_out(struct hid_device *hid); |
@@ -136,10 +135,10 @@ static void hid_reset(struct work_struct *work) | |||
136 | hid_io_error(hid); | 135 | hid_io_error(hid); |
137 | break; | 136 | break; |
138 | default: | 137 | default: |
139 | err_hid("can't reset device, %s-%s/input%d, status %d", | 138 | hid_err(hid, "can't reset device, %s-%s/input%d, status %d\n", |
140 | hid_to_usb_dev(hid)->bus->bus_name, | 139 | hid_to_usb_dev(hid)->bus->bus_name, |
141 | hid_to_usb_dev(hid)->devpath, | 140 | hid_to_usb_dev(hid)->devpath, |
142 | usbhid->ifnum, rc); | 141 | usbhid->ifnum, rc); |
143 | /* FALLTHROUGH */ | 142 | /* FALLTHROUGH */ |
144 | case -EHOSTUNREACH: | 143 | case -EHOSTUNREACH: |
145 | case -ENODEV: | 144 | case -ENODEV: |
@@ -278,18 +277,18 @@ static void hid_irq_in(struct urb *urb) | |||
278 | hid_io_error(hid); | 277 | hid_io_error(hid); |
279 | return; | 278 | return; |
280 | default: /* error */ | 279 | default: /* error */ |
281 | dev_warn(&urb->dev->dev, "input irq status %d " | 280 | hid_warn(urb->dev, "input irq status %d received\n", |
282 | "received\n", urb->status); | 281 | urb->status); |
283 | } | 282 | } |
284 | 283 | ||
285 | status = usb_submit_urb(urb, GFP_ATOMIC); | 284 | status = usb_submit_urb(urb, GFP_ATOMIC); |
286 | if (status) { | 285 | if (status) { |
287 | clear_bit(HID_IN_RUNNING, &usbhid->iofl); | 286 | clear_bit(HID_IN_RUNNING, &usbhid->iofl); |
288 | if (status != -EPERM) { | 287 | if (status != -EPERM) { |
289 | err_hid("can't resubmit intr, %s-%s/input%d, status %d", | 288 | hid_err(hid, "can't resubmit intr, %s-%s/input%d, status %d\n", |
290 | hid_to_usb_dev(hid)->bus->bus_name, | 289 | hid_to_usb_dev(hid)->bus->bus_name, |
291 | hid_to_usb_dev(hid)->devpath, | 290 | hid_to_usb_dev(hid)->devpath, |
292 | usbhid->ifnum, status); | 291 | usbhid->ifnum, status); |
293 | hid_io_error(hid); | 292 | hid_io_error(hid); |
294 | } | 293 | } |
295 | } | 294 | } |
@@ -300,10 +299,19 @@ static int hid_submit_out(struct hid_device *hid) | |||
300 | struct hid_report *report; | 299 | struct hid_report *report; |
301 | char *raw_report; | 300 | char *raw_report; |
302 | struct usbhid_device *usbhid = hid->driver_data; | 301 | struct usbhid_device *usbhid = hid->driver_data; |
302 | int r; | ||
303 | 303 | ||
304 | report = usbhid->out[usbhid->outtail].report; | 304 | report = usbhid->out[usbhid->outtail].report; |
305 | raw_report = usbhid->out[usbhid->outtail].raw_report; | 305 | raw_report = usbhid->out[usbhid->outtail].raw_report; |
306 | 306 | ||
307 | r = usb_autopm_get_interface_async(usbhid->intf); | ||
308 | if (r < 0) | ||
309 | return -1; | ||
310 | |||
311 | /* | ||
312 | * if the device hasn't been woken, we leave the output | ||
313 | * to resume() | ||
314 | */ | ||
307 | if (!test_bit(HID_REPORTED_IDLE, &usbhid->iofl)) { | 315 | if (!test_bit(HID_REPORTED_IDLE, &usbhid->iofl)) { |
308 | usbhid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + (report->id > 0); | 316 | usbhid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + (report->id > 0); |
309 | usbhid->urbout->dev = hid_to_usb_dev(hid); | 317 | usbhid->urbout->dev = hid_to_usb_dev(hid); |
@@ -313,17 +321,11 @@ static int hid_submit_out(struct hid_device *hid) | |||
313 | dbg_hid("submitting out urb\n"); | 321 | dbg_hid("submitting out urb\n"); |
314 | 322 | ||
315 | if (usb_submit_urb(usbhid->urbout, GFP_ATOMIC)) { | 323 | if (usb_submit_urb(usbhid->urbout, GFP_ATOMIC)) { |
316 | err_hid("usb_submit_urb(out) failed"); | 324 | hid_err(hid, "usb_submit_urb(out) failed\n"); |
325 | usb_autopm_put_interface_async(usbhid->intf); | ||
317 | return -1; | 326 | return -1; |
318 | } | 327 | } |
319 | usbhid->last_out = jiffies; | 328 | usbhid->last_out = jiffies; |
320 | } else { | ||
321 | /* | ||
322 | * queue work to wake up the device. | ||
323 | * as the work queue is freezeable, this is safe | ||
324 | * with respect to STD and STR | ||
325 | */ | ||
326 | queue_work(resumption_waker, &usbhid->restart_work); | ||
327 | } | 329 | } |
328 | 330 | ||
329 | return 0; | 331 | return 0; |
@@ -334,13 +336,16 @@ static int hid_submit_ctrl(struct hid_device *hid) | |||
334 | struct hid_report *report; | 336 | struct hid_report *report; |
335 | unsigned char dir; | 337 | unsigned char dir; |
336 | char *raw_report; | 338 | char *raw_report; |
337 | int len; | 339 | int len, r; |
338 | struct usbhid_device *usbhid = hid->driver_data; | 340 | struct usbhid_device *usbhid = hid->driver_data; |
339 | 341 | ||
340 | report = usbhid->ctrl[usbhid->ctrltail].report; | 342 | report = usbhid->ctrl[usbhid->ctrltail].report; |
341 | raw_report = usbhid->ctrl[usbhid->ctrltail].raw_report; | 343 | raw_report = usbhid->ctrl[usbhid->ctrltail].raw_report; |
342 | dir = usbhid->ctrl[usbhid->ctrltail].dir; | 344 | dir = usbhid->ctrl[usbhid->ctrltail].dir; |
343 | 345 | ||
346 | r = usb_autopm_get_interface_async(usbhid->intf); | ||
347 | if (r < 0) | ||
348 | return -1; | ||
344 | if (!test_bit(HID_REPORTED_IDLE, &usbhid->iofl)) { | 349 | if (!test_bit(HID_REPORTED_IDLE, &usbhid->iofl)) { |
345 | len = ((report->size - 1) >> 3) + 1 + (report->id > 0); | 350 | len = ((report->size - 1) >> 3) + 1 + (report->id > 0); |
346 | if (dir == USB_DIR_OUT) { | 351 | if (dir == USB_DIR_OUT) { |
@@ -375,17 +380,11 @@ static int hid_submit_ctrl(struct hid_device *hid) | |||
375 | usbhid->cr->wValue, usbhid->cr->wIndex, usbhid->cr->wLength); | 380 | usbhid->cr->wValue, usbhid->cr->wIndex, usbhid->cr->wLength); |
376 | 381 | ||
377 | if (usb_submit_urb(usbhid->urbctrl, GFP_ATOMIC)) { | 382 | if (usb_submit_urb(usbhid->urbctrl, GFP_ATOMIC)) { |
378 | err_hid("usb_submit_urb(ctrl) failed"); | 383 | usb_autopm_put_interface_async(usbhid->intf); |
384 | hid_err(hid, "usb_submit_urb(ctrl) failed\n"); | ||
379 | return -1; | 385 | return -1; |
380 | } | 386 | } |
381 | usbhid->last_ctrl = jiffies; | 387 | usbhid->last_ctrl = jiffies; |
382 | } else { | ||
383 | /* | ||
384 | * queue work to wake up the device. | ||
385 | * as the work queue is freezeable, this is safe | ||
386 | * with respect to STD and STR | ||
387 | */ | ||
388 | queue_work(resumption_waker, &usbhid->restart_work); | ||
389 | } | 388 | } |
390 | 389 | ||
391 | return 0; | 390 | return 0; |
@@ -413,8 +412,8 @@ static void hid_irq_out(struct urb *urb) | |||
413 | case -ENOENT: | 412 | case -ENOENT: |
414 | break; | 413 | break; |
415 | default: /* error */ | 414 | default: /* error */ |
416 | dev_warn(&urb->dev->dev, "output irq status %d " | 415 | hid_warn(urb->dev, "output irq status %d received\n", |
417 | "received\n", urb->status); | 416 | urb->status); |
418 | } | 417 | } |
419 | 418 | ||
420 | spin_lock_irqsave(&usbhid->lock, flags); | 419 | spin_lock_irqsave(&usbhid->lock, flags); |
@@ -435,6 +434,7 @@ static void hid_irq_out(struct urb *urb) | |||
435 | 434 | ||
436 | clear_bit(HID_OUT_RUNNING, &usbhid->iofl); | 435 | clear_bit(HID_OUT_RUNNING, &usbhid->iofl); |
437 | spin_unlock_irqrestore(&usbhid->lock, flags); | 436 | spin_unlock_irqrestore(&usbhid->lock, flags); |
437 | usb_autopm_put_interface_async(usbhid->intf); | ||
438 | wake_up(&usbhid->wait); | 438 | wake_up(&usbhid->wait); |
439 | } | 439 | } |
440 | 440 | ||
@@ -466,8 +466,7 @@ static void hid_ctrl(struct urb *urb) | |||
466 | case -EPIPE: /* report not available */ | 466 | case -EPIPE: /* report not available */ |
467 | break; | 467 | break; |
468 | default: /* error */ | 468 | default: /* error */ |
469 | dev_warn(&urb->dev->dev, "ctrl urb status %d " | 469 | hid_warn(urb->dev, "ctrl urb status %d received\n", status); |
470 | "received\n", status); | ||
471 | } | 470 | } |
472 | 471 | ||
473 | if (unplug) | 472 | if (unplug) |
@@ -481,11 +480,13 @@ static void hid_ctrl(struct urb *urb) | |||
481 | wake_up(&usbhid->wait); | 480 | wake_up(&usbhid->wait); |
482 | } | 481 | } |
483 | spin_unlock(&usbhid->lock); | 482 | spin_unlock(&usbhid->lock); |
483 | usb_autopm_put_interface_async(usbhid->intf); | ||
484 | return; | 484 | return; |
485 | } | 485 | } |
486 | 486 | ||
487 | clear_bit(HID_CTRL_RUNNING, &usbhid->iofl); | 487 | clear_bit(HID_CTRL_RUNNING, &usbhid->iofl); |
488 | spin_unlock(&usbhid->lock); | 488 | spin_unlock(&usbhid->lock); |
489 | usb_autopm_put_interface_async(usbhid->intf); | ||
489 | wake_up(&usbhid->wait); | 490 | wake_up(&usbhid->wait); |
490 | } | 491 | } |
491 | 492 | ||
@@ -501,13 +502,13 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re | |||
501 | 502 | ||
502 | if (usbhid->urbout && dir == USB_DIR_OUT && report->type == HID_OUTPUT_REPORT) { | 503 | if (usbhid->urbout && dir == USB_DIR_OUT && report->type == HID_OUTPUT_REPORT) { |
503 | if ((head = (usbhid->outhead + 1) & (HID_OUTPUT_FIFO_SIZE - 1)) == usbhid->outtail) { | 504 | if ((head = (usbhid->outhead + 1) & (HID_OUTPUT_FIFO_SIZE - 1)) == usbhid->outtail) { |
504 | dev_warn(&hid->dev, "output queue full\n"); | 505 | hid_warn(hid, "output queue full\n"); |
505 | return; | 506 | return; |
506 | } | 507 | } |
507 | 508 | ||
508 | usbhid->out[usbhid->outhead].raw_report = kmalloc(len, GFP_ATOMIC); | 509 | usbhid->out[usbhid->outhead].raw_report = kmalloc(len, GFP_ATOMIC); |
509 | if (!usbhid->out[usbhid->outhead].raw_report) { | 510 | if (!usbhid->out[usbhid->outhead].raw_report) { |
510 | dev_warn(&hid->dev, "output queueing failed\n"); | 511 | hid_warn(hid, "output queueing failed\n"); |
511 | return; | 512 | return; |
512 | } | 513 | } |
513 | hid_output_report(report, usbhid->out[usbhid->outhead].raw_report); | 514 | hid_output_report(report, usbhid->out[usbhid->outhead].raw_report); |
@@ -532,14 +533,14 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re | |||
532 | } | 533 | } |
533 | 534 | ||
534 | if ((head = (usbhid->ctrlhead + 1) & (HID_CONTROL_FIFO_SIZE - 1)) == usbhid->ctrltail) { | 535 | if ((head = (usbhid->ctrlhead + 1) & (HID_CONTROL_FIFO_SIZE - 1)) == usbhid->ctrltail) { |
535 | dev_warn(&hid->dev, "control queue full\n"); | 536 | hid_warn(hid, "control queue full\n"); |
536 | return; | 537 | return; |
537 | } | 538 | } |
538 | 539 | ||
539 | if (dir == USB_DIR_OUT) { | 540 | if (dir == USB_DIR_OUT) { |
540 | usbhid->ctrl[usbhid->ctrlhead].raw_report = kmalloc(len, GFP_ATOMIC); | 541 | usbhid->ctrl[usbhid->ctrlhead].raw_report = kmalloc(len, GFP_ATOMIC); |
541 | if (!usbhid->ctrl[usbhid->ctrlhead].raw_report) { | 542 | if (!usbhid->ctrl[usbhid->ctrlhead].raw_report) { |
542 | dev_warn(&hid->dev, "control queueing failed\n"); | 543 | hid_warn(hid, "control queueing failed\n"); |
543 | return; | 544 | return; |
544 | } | 545 | } |
545 | hid_output_report(report, usbhid->ctrl[usbhid->ctrlhead].raw_report); | 546 | hid_output_report(report, usbhid->ctrl[usbhid->ctrlhead].raw_report); |
@@ -590,7 +591,7 @@ static int usb_hidinput_input_event(struct input_dev *dev, unsigned int type, un | |||
590 | return -1; | 591 | return -1; |
591 | 592 | ||
592 | if ((offset = hidinput_find_field(hid, type, code, &field)) == -1) { | 593 | if ((offset = hidinput_find_field(hid, type, code, &field)) == -1) { |
593 | dev_warn(&dev->dev, "event field not found\n"); | 594 | hid_warn(dev, "event field not found\n"); |
594 | return -1; | 595 | return -1; |
595 | } | 596 | } |
596 | 597 | ||
@@ -656,7 +657,7 @@ int usbhid_open(struct hid_device *hid) | |||
656 | mutex_lock(&hid_open_mut); | 657 | mutex_lock(&hid_open_mut); |
657 | if (!hid->open++) { | 658 | if (!hid->open++) { |
658 | res = usb_autopm_get_interface(usbhid->intf); | 659 | res = usb_autopm_get_interface(usbhid->intf); |
659 | /* the device must be awake to reliable request remote wakeup */ | 660 | /* the device must be awake to reliably request remote wakeup */ |
660 | if (res < 0) { | 661 | if (res < 0) { |
661 | hid->open--; | 662 | hid->open--; |
662 | mutex_unlock(&hid_open_mut); | 663 | mutex_unlock(&hid_open_mut); |
@@ -722,7 +723,7 @@ void usbhid_init_reports(struct hid_device *hid) | |||
722 | } | 723 | } |
723 | 724 | ||
724 | if (err) | 725 | if (err) |
725 | dev_warn(&hid->dev, "timeout initializing reports\n"); | 726 | hid_warn(hid, "timeout initializing reports\n"); |
726 | } | 727 | } |
727 | 728 | ||
728 | /* | 729 | /* |
@@ -798,6 +799,40 @@ static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid) | |||
798 | return 0; | 799 | return 0; |
799 | } | 800 | } |
800 | 801 | ||
802 | static int usbhid_get_raw_report(struct hid_device *hid, | ||
803 | unsigned char report_number, __u8 *buf, size_t count, | ||
804 | unsigned char report_type) | ||
805 | { | ||
806 | struct usbhid_device *usbhid = hid->driver_data; | ||
807 | struct usb_device *dev = hid_to_usb_dev(hid); | ||
808 | struct usb_interface *intf = usbhid->intf; | ||
809 | struct usb_host_interface *interface = intf->cur_altsetting; | ||
810 | int skipped_report_id = 0; | ||
811 | int ret; | ||
812 | |||
813 | /* Byte 0 is the report number. Report data starts at byte 1.*/ | ||
814 | buf[0] = report_number; | ||
815 | if (report_number == 0x0) { | ||
816 | /* Offset the return buffer by 1, so that the report ID | ||
817 | will remain in byte 0. */ | ||
818 | buf++; | ||
819 | count--; | ||
820 | skipped_report_id = 1; | ||
821 | } | ||
822 | ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), | ||
823 | HID_REQ_GET_REPORT, | ||
824 | USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, | ||
825 | ((report_type + 1) << 8) | report_number, | ||
826 | interface->desc.bInterfaceNumber, buf, count, | ||
827 | USB_CTRL_SET_TIMEOUT); | ||
828 | |||
829 | /* count also the report id */ | ||
830 | if (ret > 0 && skipped_report_id) | ||
831 | ret++; | ||
832 | |||
833 | return ret; | ||
834 | } | ||
835 | |||
801 | static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t count, | 836 | static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t count, |
802 | unsigned char report_type) | 837 | unsigned char report_type) |
803 | { | 838 | { |
@@ -807,9 +842,10 @@ static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t co | |||
807 | struct usb_host_interface *interface = intf->cur_altsetting; | 842 | struct usb_host_interface *interface = intf->cur_altsetting; |
808 | int ret; | 843 | int ret; |
809 | 844 | ||
810 | if (usbhid->urbout) { | 845 | if (usbhid->urbout && report_type != HID_FEATURE_REPORT) { |
811 | int actual_length; | 846 | int actual_length; |
812 | int skipped_report_id = 0; | 847 | int skipped_report_id = 0; |
848 | |||
813 | if (buf[0] == 0x0) { | 849 | if (buf[0] == 0x0) { |
814 | /* Don't send the Report ID */ | 850 | /* Don't send the Report ID */ |
815 | buf++; | 851 | buf++; |
@@ -856,18 +892,6 @@ static void usbhid_restart_queues(struct usbhid_device *usbhid) | |||
856 | usbhid_restart_ctrl_queue(usbhid); | 892 | usbhid_restart_ctrl_queue(usbhid); |
857 | } | 893 | } |
858 | 894 | ||
859 | static void __usbhid_restart_queues(struct work_struct *work) | ||
860 | { | ||
861 | struct usbhid_device *usbhid = | ||
862 | container_of(work, struct usbhid_device, restart_work); | ||
863 | int r; | ||
864 | |||
865 | r = usb_autopm_get_interface(usbhid->intf); | ||
866 | if (r < 0) | ||
867 | return; | ||
868 | usb_autopm_put_interface(usbhid->intf); | ||
869 | } | ||
870 | |||
871 | static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid) | 895 | static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid) |
872 | { | 896 | { |
873 | struct usbhid_device *usbhid = hid->driver_data; | 897 | struct usbhid_device *usbhid = hid->driver_data; |
@@ -1139,8 +1163,7 @@ static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id * | |||
1139 | if (usb_endpoint_is_int_in(&interface->endpoint[n].desc)) | 1163 | if (usb_endpoint_is_int_in(&interface->endpoint[n].desc)) |
1140 | has_in++; | 1164 | has_in++; |
1141 | if (!has_in) { | 1165 | if (!has_in) { |
1142 | dev_err(&intf->dev, "couldn't find an input interrupt " | 1166 | hid_err(intf, "couldn't find an input interrupt endpoint\n"); |
1143 | "endpoint\n"); | ||
1144 | return -ENODEV; | 1167 | return -ENODEV; |
1145 | } | 1168 | } |
1146 | 1169 | ||
@@ -1150,6 +1173,7 @@ static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id * | |||
1150 | 1173 | ||
1151 | usb_set_intfdata(intf, hid); | 1174 | usb_set_intfdata(intf, hid); |
1152 | hid->ll_driver = &usb_hid_driver; | 1175 | hid->ll_driver = &usb_hid_driver; |
1176 | hid->hid_get_raw_report = usbhid_get_raw_report; | ||
1153 | hid->hid_output_raw_report = usbhid_output_raw_report; | 1177 | hid->hid_output_raw_report = usbhid_output_raw_report; |
1154 | hid->ff_init = hid_pidff_init; | 1178 | hid->ff_init = hid_pidff_init; |
1155 | #ifdef CONFIG_USB_HIDDEV | 1179 | #ifdef CONFIG_USB_HIDDEV |
@@ -1205,14 +1229,13 @@ static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id * | |||
1205 | 1229 | ||
1206 | init_waitqueue_head(&usbhid->wait); | 1230 | init_waitqueue_head(&usbhid->wait); |
1207 | INIT_WORK(&usbhid->reset_work, hid_reset); | 1231 | INIT_WORK(&usbhid->reset_work, hid_reset); |
1208 | INIT_WORK(&usbhid->restart_work, __usbhid_restart_queues); | ||
1209 | setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid); | 1232 | setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid); |
1210 | spin_lock_init(&usbhid->lock); | 1233 | spin_lock_init(&usbhid->lock); |
1211 | 1234 | ||
1212 | ret = hid_add_device(hid); | 1235 | ret = hid_add_device(hid); |
1213 | if (ret) { | 1236 | if (ret) { |
1214 | if (ret != -ENODEV) | 1237 | if (ret != -ENODEV) |
1215 | dev_err(&intf->dev, "can't add hid device: %d\n", ret); | 1238 | hid_err(intf, "can't add hid device: %d\n", ret); |
1216 | goto err_free; | 1239 | goto err_free; |
1217 | } | 1240 | } |
1218 | 1241 | ||
@@ -1240,7 +1263,6 @@ static void usbhid_disconnect(struct usb_interface *intf) | |||
1240 | static void hid_cancel_delayed_stuff(struct usbhid_device *usbhid) | 1263 | static void hid_cancel_delayed_stuff(struct usbhid_device *usbhid) |
1241 | { | 1264 | { |
1242 | del_timer_sync(&usbhid->io_retry); | 1265 | del_timer_sync(&usbhid->io_retry); |
1243 | cancel_work_sync(&usbhid->restart_work); | ||
1244 | cancel_work_sync(&usbhid->reset_work); | 1266 | cancel_work_sync(&usbhid->reset_work); |
1245 | } | 1267 | } |
1246 | 1268 | ||
@@ -1261,7 +1283,6 @@ static int hid_pre_reset(struct usb_interface *intf) | |||
1261 | spin_lock_irq(&usbhid->lock); | 1283 | spin_lock_irq(&usbhid->lock); |
1262 | set_bit(HID_RESET_PENDING, &usbhid->iofl); | 1284 | set_bit(HID_RESET_PENDING, &usbhid->iofl); |
1263 | spin_unlock_irq(&usbhid->lock); | 1285 | spin_unlock_irq(&usbhid->lock); |
1264 | cancel_work_sync(&usbhid->restart_work); | ||
1265 | hid_cease_io(usbhid); | 1286 | hid_cease_io(usbhid); |
1266 | 1287 | ||
1267 | return 0; | 1288 | return 0; |
@@ -1460,18 +1481,12 @@ static int __init hid_init(void) | |||
1460 | { | 1481 | { |
1461 | int retval = -ENOMEM; | 1482 | int retval = -ENOMEM; |
1462 | 1483 | ||
1463 | resumption_waker = create_freezeable_workqueue("usbhid_resumer"); | ||
1464 | if (!resumption_waker) | ||
1465 | goto no_queue; | ||
1466 | retval = hid_register_driver(&hid_usb_driver); | 1484 | retval = hid_register_driver(&hid_usb_driver); |
1467 | if (retval) | 1485 | if (retval) |
1468 | goto hid_register_fail; | 1486 | goto hid_register_fail; |
1469 | retval = usbhid_quirks_init(quirks_param); | 1487 | retval = usbhid_quirks_init(quirks_param); |
1470 | if (retval) | 1488 | if (retval) |
1471 | goto usbhid_quirks_init_fail; | 1489 | goto usbhid_quirks_init_fail; |
1472 | retval = hiddev_init(); | ||
1473 | if (retval) | ||
1474 | goto hiddev_init_fail; | ||
1475 | retval = usb_register(&hid_driver); | 1490 | retval = usb_register(&hid_driver); |
1476 | if (retval) | 1491 | if (retval) |
1477 | goto usb_register_fail; | 1492 | goto usb_register_fail; |
@@ -1479,24 +1494,18 @@ static int __init hid_init(void) | |||
1479 | 1494 | ||
1480 | return 0; | 1495 | return 0; |
1481 | usb_register_fail: | 1496 | usb_register_fail: |
1482 | hiddev_exit(); | ||
1483 | hiddev_init_fail: | ||
1484 | usbhid_quirks_exit(); | 1497 | usbhid_quirks_exit(); |
1485 | usbhid_quirks_init_fail: | 1498 | usbhid_quirks_init_fail: |
1486 | hid_unregister_driver(&hid_usb_driver); | 1499 | hid_unregister_driver(&hid_usb_driver); |
1487 | hid_register_fail: | 1500 | hid_register_fail: |
1488 | destroy_workqueue(resumption_waker); | ||
1489 | no_queue: | ||
1490 | return retval; | 1501 | return retval; |
1491 | } | 1502 | } |
1492 | 1503 | ||
1493 | static void __exit hid_exit(void) | 1504 | static void __exit hid_exit(void) |
1494 | { | 1505 | { |
1495 | usb_deregister(&hid_driver); | 1506 | usb_deregister(&hid_driver); |
1496 | hiddev_exit(); | ||
1497 | usbhid_quirks_exit(); | 1507 | usbhid_quirks_exit(); |
1498 | hid_unregister_driver(&hid_usb_driver); | 1508 | hid_unregister_driver(&hid_usb_driver); |
1499 | destroy_workqueue(resumption_waker); | ||
1500 | } | 1509 | } |
1501 | 1510 | ||
1502 | module_init(hid_init); | 1511 | module_init(hid_init); |
diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c index ef381d79cfa8..f91c136821f7 100644 --- a/drivers/hid/usbhid/hid-pidff.c +++ b/drivers/hid/usbhid/hid-pidff.c | |||
@@ -22,7 +22,7 @@ | |||
22 | 22 | ||
23 | /* #define DEBUG */ | 23 | /* #define DEBUG */ |
24 | 24 | ||
25 | #define debug(format, arg...) pr_debug("hid-pidff: " format "\n" , ## arg) | 25 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
26 | 26 | ||
27 | #include <linux/input.h> | 27 | #include <linux/input.h> |
28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
@@ -220,7 +220,7 @@ static int pidff_rescale_signed(int i, struct hid_field *field) | |||
220 | static void pidff_set(struct pidff_usage *usage, u16 value) | 220 | static void pidff_set(struct pidff_usage *usage, u16 value) |
221 | { | 221 | { |
222 | usage->value[0] = pidff_rescale(value, 0xffff, usage->field); | 222 | usage->value[0] = pidff_rescale(value, 0xffff, usage->field); |
223 | debug("calculated from %d to %d", value, usage->value[0]); | 223 | pr_debug("calculated from %d to %d\n", value, usage->value[0]); |
224 | } | 224 | } |
225 | 225 | ||
226 | static void pidff_set_signed(struct pidff_usage *usage, s16 value) | 226 | static void pidff_set_signed(struct pidff_usage *usage, s16 value) |
@@ -235,7 +235,7 @@ static void pidff_set_signed(struct pidff_usage *usage, s16 value) | |||
235 | usage->value[0] = | 235 | usage->value[0] = |
236 | pidff_rescale(value, 0x7fff, usage->field); | 236 | pidff_rescale(value, 0x7fff, usage->field); |
237 | } | 237 | } |
238 | debug("calculated from %d to %d", value, usage->value[0]); | 238 | pr_debug("calculated from %d to %d\n", value, usage->value[0]); |
239 | } | 239 | } |
240 | 240 | ||
241 | /* | 241 | /* |
@@ -259,8 +259,9 @@ static void pidff_set_envelope_report(struct pidff_device *pidff, | |||
259 | pidff->set_envelope[PID_ATTACK_TIME].value[0] = envelope->attack_length; | 259 | pidff->set_envelope[PID_ATTACK_TIME].value[0] = envelope->attack_length; |
260 | pidff->set_envelope[PID_FADE_TIME].value[0] = envelope->fade_length; | 260 | pidff->set_envelope[PID_FADE_TIME].value[0] = envelope->fade_length; |
261 | 261 | ||
262 | debug("attack %u => %d", envelope->attack_level, | 262 | hid_dbg(pidff->hid, "attack %u => %d\n", |
263 | pidff->set_envelope[PID_ATTACK_LEVEL].value[0]); | 263 | envelope->attack_level, |
264 | pidff->set_envelope[PID_ATTACK_LEVEL].value[0]); | ||
264 | 265 | ||
265 | usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_ENVELOPE], | 266 | usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_ENVELOPE], |
266 | USB_DIR_OUT); | 267 | USB_DIR_OUT); |
@@ -466,33 +467,33 @@ static int pidff_request_effect_upload(struct pidff_device *pidff, int efnum) | |||
466 | pidff->create_new_effect_type->value[0] = efnum; | 467 | pidff->create_new_effect_type->value[0] = efnum; |
467 | usbhid_submit_report(pidff->hid, pidff->reports[PID_CREATE_NEW_EFFECT], | 468 | usbhid_submit_report(pidff->hid, pidff->reports[PID_CREATE_NEW_EFFECT], |
468 | USB_DIR_OUT); | 469 | USB_DIR_OUT); |
469 | debug("create_new_effect sent, type: %d", efnum); | 470 | hid_dbg(pidff->hid, "create_new_effect sent, type: %d\n", efnum); |
470 | 471 | ||
471 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0] = 0; | 472 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0] = 0; |
472 | pidff->block_load_status->value[0] = 0; | 473 | pidff->block_load_status->value[0] = 0; |
473 | usbhid_wait_io(pidff->hid); | 474 | usbhid_wait_io(pidff->hid); |
474 | 475 | ||
475 | for (j = 0; j < 60; j++) { | 476 | for (j = 0; j < 60; j++) { |
476 | debug("pid_block_load requested"); | 477 | hid_dbg(pidff->hid, "pid_block_load requested\n"); |
477 | usbhid_submit_report(pidff->hid, pidff->reports[PID_BLOCK_LOAD], | 478 | usbhid_submit_report(pidff->hid, pidff->reports[PID_BLOCK_LOAD], |
478 | USB_DIR_IN); | 479 | USB_DIR_IN); |
479 | usbhid_wait_io(pidff->hid); | 480 | usbhid_wait_io(pidff->hid); |
480 | if (pidff->block_load_status->value[0] == | 481 | if (pidff->block_load_status->value[0] == |
481 | pidff->status_id[PID_BLOCK_LOAD_SUCCESS]) { | 482 | pidff->status_id[PID_BLOCK_LOAD_SUCCESS]) { |
482 | debug("device reported free memory: %d bytes", | 483 | hid_dbg(pidff->hid, "device reported free memory: %d bytes\n", |
483 | pidff->block_load[PID_RAM_POOL_AVAILABLE].value ? | 484 | pidff->block_load[PID_RAM_POOL_AVAILABLE].value ? |
484 | pidff->block_load[PID_RAM_POOL_AVAILABLE].value[0] : -1); | 485 | pidff->block_load[PID_RAM_POOL_AVAILABLE].value[0] : -1); |
485 | return 0; | 486 | return 0; |
486 | } | 487 | } |
487 | if (pidff->block_load_status->value[0] == | 488 | if (pidff->block_load_status->value[0] == |
488 | pidff->status_id[PID_BLOCK_LOAD_FULL]) { | 489 | pidff->status_id[PID_BLOCK_LOAD_FULL]) { |
489 | debug("not enough memory free: %d bytes", | 490 | hid_dbg(pidff->hid, "not enough memory free: %d bytes\n", |
490 | pidff->block_load[PID_RAM_POOL_AVAILABLE].value ? | 491 | pidff->block_load[PID_RAM_POOL_AVAILABLE].value ? |
491 | pidff->block_load[PID_RAM_POOL_AVAILABLE].value[0] : -1); | 492 | pidff->block_load[PID_RAM_POOL_AVAILABLE].value[0] : -1); |
492 | return -ENOSPC; | 493 | return -ENOSPC; |
493 | } | 494 | } |
494 | } | 495 | } |
495 | printk(KERN_ERR "hid-pidff: pid_block_load failed 60 times\n"); | 496 | hid_err(pidff->hid, "pid_block_load failed 60 times\n"); |
496 | return -EIO; | 497 | return -EIO; |
497 | } | 498 | } |
498 | 499 | ||
@@ -546,7 +547,8 @@ static int pidff_erase_effect(struct input_dev *dev, int effect_id) | |||
546 | struct pidff_device *pidff = dev->ff->private; | 547 | struct pidff_device *pidff = dev->ff->private; |
547 | int pid_id = pidff->pid_id[effect_id]; | 548 | int pid_id = pidff->pid_id[effect_id]; |
548 | 549 | ||
549 | debug("starting to erase %d/%d", effect_id, pidff->pid_id[effect_id]); | 550 | hid_dbg(pidff->hid, "starting to erase %d/%d\n", |
551 | effect_id, pidff->pid_id[effect_id]); | ||
550 | /* Wait for the queue to clear. We do not want a full fifo to | 552 | /* Wait for the queue to clear. We do not want a full fifo to |
551 | prevent the effect removal. */ | 553 | prevent the effect removal. */ |
552 | usbhid_wait_io(pidff->hid); | 554 | usbhid_wait_io(pidff->hid); |
@@ -604,8 +606,7 @@ static int pidff_upload_effect(struct input_dev *dev, struct ff_effect *effect, | |||
604 | type_id = PID_SAW_DOWN; | 606 | type_id = PID_SAW_DOWN; |
605 | break; | 607 | break; |
606 | default: | 608 | default: |
607 | printk(KERN_ERR | 609 | hid_err(pidff->hid, "invalid waveform\n"); |
608 | "hid-pidff: invalid waveform\n"); | ||
609 | return -EINVAL; | 610 | return -EINVAL; |
610 | } | 611 | } |
611 | 612 | ||
@@ -696,7 +697,7 @@ static int pidff_upload_effect(struct input_dev *dev, struct ff_effect *effect, | |||
696 | break; | 697 | break; |
697 | 698 | ||
698 | default: | 699 | default: |
699 | printk(KERN_ERR "hid-pidff: invalid type\n"); | 700 | hid_err(pidff->hid, "invalid type\n"); |
700 | return -EINVAL; | 701 | return -EINVAL; |
701 | } | 702 | } |
702 | 703 | ||
@@ -704,7 +705,7 @@ static int pidff_upload_effect(struct input_dev *dev, struct ff_effect *effect, | |||
704 | pidff->pid_id[effect->id] = | 705 | pidff->pid_id[effect->id] = |
705 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; | 706 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; |
706 | 707 | ||
707 | debug("uploaded"); | 708 | hid_dbg(pidff->hid, "uploaded\n"); |
708 | 709 | ||
709 | return 0; | 710 | return 0; |
710 | } | 711 | } |
@@ -770,14 +771,14 @@ static int pidff_find_fields(struct pidff_usage *usage, const u8 *table, | |||
770 | for (i = 0; i < report->maxfield; i++) { | 771 | for (i = 0; i < report->maxfield; i++) { |
771 | if (report->field[i]->maxusage != | 772 | if (report->field[i]->maxusage != |
772 | report->field[i]->report_count) { | 773 | report->field[i]->report_count) { |
773 | debug("maxusage and report_count do not match, " | 774 | pr_debug("maxusage and report_count do not match, skipping\n"); |
774 | "skipping"); | ||
775 | continue; | 775 | continue; |
776 | } | 776 | } |
777 | for (j = 0; j < report->field[i]->maxusage; j++) { | 777 | for (j = 0; j < report->field[i]->maxusage; j++) { |
778 | if (report->field[i]->usage[j].hid == | 778 | if (report->field[i]->usage[j].hid == |
779 | (HID_UP_PID | table[k])) { | 779 | (HID_UP_PID | table[k])) { |
780 | debug("found %d at %d->%d", k, i, j); | 780 | pr_debug("found %d at %d->%d\n", |
781 | k, i, j); | ||
781 | usage[k].field = report->field[i]; | 782 | usage[k].field = report->field[i]; |
782 | usage[k].value = | 783 | usage[k].value = |
783 | &report->field[i]->value[j]; | 784 | &report->field[i]->value[j]; |
@@ -789,7 +790,7 @@ static int pidff_find_fields(struct pidff_usage *usage, const u8 *table, | |||
789 | break; | 790 | break; |
790 | } | 791 | } |
791 | if (!found && strict) { | 792 | if (!found && strict) { |
792 | debug("failed to locate %d", k); | 793 | pr_debug("failed to locate %d\n", k); |
793 | return -1; | 794 | return -1; |
794 | } | 795 | } |
795 | } | 796 | } |
@@ -826,8 +827,8 @@ static void pidff_find_reports(struct hid_device *hid, int report_type, | |||
826 | continue; | 827 | continue; |
827 | ret = pidff_check_usage(report->field[0]->logical); | 828 | ret = pidff_check_usage(report->field[0]->logical); |
828 | if (ret != -1) { | 829 | if (ret != -1) { |
829 | debug("found usage 0x%02x from field->logical", | 830 | hid_dbg(hid, "found usage 0x%02x from field->logical\n", |
830 | pidff_reports[ret]); | 831 | pidff_reports[ret]); |
831 | pidff->reports[ret] = report; | 832 | pidff->reports[ret] = report; |
832 | continue; | 833 | continue; |
833 | } | 834 | } |
@@ -845,8 +846,9 @@ static void pidff_find_reports(struct hid_device *hid, int report_type, | |||
845 | continue; | 846 | continue; |
846 | ret = pidff_check_usage(hid->collection[i - 1].usage); | 847 | ret = pidff_check_usage(hid->collection[i - 1].usage); |
847 | if (ret != -1 && !pidff->reports[ret]) { | 848 | if (ret != -1 && !pidff->reports[ret]) { |
848 | debug("found usage 0x%02x from collection array", | 849 | hid_dbg(hid, |
849 | pidff_reports[ret]); | 850 | "found usage 0x%02x from collection array\n", |
851 | pidff_reports[ret]); | ||
850 | pidff->reports[ret] = report; | 852 | pidff->reports[ret] = report; |
851 | } | 853 | } |
852 | } | 854 | } |
@@ -861,7 +863,7 @@ static int pidff_reports_ok(struct pidff_device *pidff) | |||
861 | 863 | ||
862 | for (i = 0; i <= PID_REQUIRED_REPORTS; i++) { | 864 | for (i = 0; i <= PID_REQUIRED_REPORTS; i++) { |
863 | if (!pidff->reports[i]) { | 865 | if (!pidff->reports[i]) { |
864 | debug("%d missing", i); | 866 | hid_dbg(pidff->hid, "%d missing\n", i); |
865 | return 0; | 867 | return 0; |
866 | } | 868 | } |
867 | } | 869 | } |
@@ -884,8 +886,7 @@ static struct hid_field *pidff_find_special_field(struct hid_report *report, | |||
884 | report->field[i]->logical_minimum == 1) | 886 | report->field[i]->logical_minimum == 1) |
885 | return report->field[i]; | 887 | return report->field[i]; |
886 | else { | 888 | else { |
887 | printk(KERN_ERR "hid-pidff: logical_minimum " | 889 | pr_err("logical_minimum is not 1 as it should be\n"); |
888 | "is not 1 as it should be\n"); | ||
889 | return NULL; | 890 | return NULL; |
890 | } | 891 | } |
891 | } | 892 | } |
@@ -924,7 +925,7 @@ static int pidff_find_special_keys(int *keys, struct hid_field *fld, | |||
924 | */ | 925 | */ |
925 | static int pidff_find_special_fields(struct pidff_device *pidff) | 926 | static int pidff_find_special_fields(struct pidff_device *pidff) |
926 | { | 927 | { |
927 | debug("finding special fields"); | 928 | hid_dbg(pidff->hid, "finding special fields\n"); |
928 | 929 | ||
929 | pidff->create_new_effect_type = | 930 | pidff->create_new_effect_type = |
930 | pidff_find_special_field(pidff->reports[PID_CREATE_NEW_EFFECT], | 931 | pidff_find_special_field(pidff->reports[PID_CREATE_NEW_EFFECT], |
@@ -945,32 +946,30 @@ static int pidff_find_special_fields(struct pidff_device *pidff) | |||
945 | pidff_find_special_field(pidff->reports[PID_EFFECT_OPERATION], | 946 | pidff_find_special_field(pidff->reports[PID_EFFECT_OPERATION], |
946 | 0x78, 1); | 947 | 0x78, 1); |
947 | 948 | ||
948 | debug("search done"); | 949 | hid_dbg(pidff->hid, "search done\n"); |
949 | 950 | ||
950 | if (!pidff->create_new_effect_type || !pidff->set_effect_type) { | 951 | if (!pidff->create_new_effect_type || !pidff->set_effect_type) { |
951 | printk(KERN_ERR "hid-pidff: effect lists not found\n"); | 952 | hid_err(pidff->hid, "effect lists not found\n"); |
952 | return -1; | 953 | return -1; |
953 | } | 954 | } |
954 | 955 | ||
955 | if (!pidff->effect_direction) { | 956 | if (!pidff->effect_direction) { |
956 | printk(KERN_ERR "hid-pidff: direction field not found\n"); | 957 | hid_err(pidff->hid, "direction field not found\n"); |
957 | return -1; | 958 | return -1; |
958 | } | 959 | } |
959 | 960 | ||
960 | if (!pidff->device_control) { | 961 | if (!pidff->device_control) { |
961 | printk(KERN_ERR "hid-pidff: device control field not found\n"); | 962 | hid_err(pidff->hid, "device control field not found\n"); |
962 | return -1; | 963 | return -1; |
963 | } | 964 | } |
964 | 965 | ||
965 | if (!pidff->block_load_status) { | 966 | if (!pidff->block_load_status) { |
966 | printk(KERN_ERR | 967 | hid_err(pidff->hid, "block load status field not found\n"); |
967 | "hid-pidff: block load status field not found\n"); | ||
968 | return -1; | 968 | return -1; |
969 | } | 969 | } |
970 | 970 | ||
971 | if (!pidff->effect_operation_status) { | 971 | if (!pidff->effect_operation_status) { |
972 | printk(KERN_ERR | 972 | hid_err(pidff->hid, "effect operation field not found\n"); |
973 | "hid-pidff: effect operation field not found\n"); | ||
974 | return -1; | 973 | return -1; |
975 | } | 974 | } |
976 | 975 | ||
@@ -982,23 +981,22 @@ static int pidff_find_special_fields(struct pidff_device *pidff) | |||
982 | 981 | ||
983 | if (!PIDFF_FIND_SPECIAL_KEYS(type_id, create_new_effect_type, | 982 | if (!PIDFF_FIND_SPECIAL_KEYS(type_id, create_new_effect_type, |
984 | effect_types)) { | 983 | effect_types)) { |
985 | printk(KERN_ERR "hid-pidff: no effect types found\n"); | 984 | hid_err(pidff->hid, "no effect types found\n"); |
986 | return -1; | 985 | return -1; |
987 | } | 986 | } |
988 | 987 | ||
989 | if (PIDFF_FIND_SPECIAL_KEYS(status_id, block_load_status, | 988 | if (PIDFF_FIND_SPECIAL_KEYS(status_id, block_load_status, |
990 | block_load_status) != | 989 | block_load_status) != |
991 | sizeof(pidff_block_load_status)) { | 990 | sizeof(pidff_block_load_status)) { |
992 | printk(KERN_ERR | 991 | hid_err(pidff->hid, |
993 | "hidpidff: block load status identifiers not found\n"); | 992 | "block load status identifiers not found\n"); |
994 | return -1; | 993 | return -1; |
995 | } | 994 | } |
996 | 995 | ||
997 | if (PIDFF_FIND_SPECIAL_KEYS(operation_id, effect_operation_status, | 996 | if (PIDFF_FIND_SPECIAL_KEYS(operation_id, effect_operation_status, |
998 | effect_operation_status) != | 997 | effect_operation_status) != |
999 | sizeof(pidff_effect_operation_status)) { | 998 | sizeof(pidff_effect_operation_status)) { |
1000 | printk(KERN_ERR | 999 | hid_err(pidff->hid, "effect operation identifiers not found\n"); |
1001 | "hidpidff: effect operation identifiers not found\n"); | ||
1002 | return -1; | 1000 | return -1; |
1003 | } | 1001 | } |
1004 | 1002 | ||
@@ -1017,8 +1015,8 @@ static int pidff_find_effects(struct pidff_device *pidff, | |||
1017 | int pidff_type = pidff->type_id[i]; | 1015 | int pidff_type = pidff->type_id[i]; |
1018 | if (pidff->set_effect_type->usage[pidff_type].hid != | 1016 | if (pidff->set_effect_type->usage[pidff_type].hid != |
1019 | pidff->create_new_effect_type->usage[pidff_type].hid) { | 1017 | pidff->create_new_effect_type->usage[pidff_type].hid) { |
1020 | printk(KERN_ERR "hid-pidff: " | 1018 | hid_err(pidff->hid, |
1021 | "effect type number %d is invalid\n", i); | 1019 | "effect type number %d is invalid\n", i); |
1022 | return -1; | 1020 | return -1; |
1023 | } | 1021 | } |
1024 | } | 1022 | } |
@@ -1073,27 +1071,23 @@ static int pidff_init_fields(struct pidff_device *pidff, struct input_dev *dev) | |||
1073 | int envelope_ok = 0; | 1071 | int envelope_ok = 0; |
1074 | 1072 | ||
1075 | if (PIDFF_FIND_FIELDS(set_effect, PID_SET_EFFECT, 1)) { | 1073 | if (PIDFF_FIND_FIELDS(set_effect, PID_SET_EFFECT, 1)) { |
1076 | printk(KERN_ERR | 1074 | hid_err(pidff->hid, "unknown set_effect report layout\n"); |
1077 | "hid-pidff: unknown set_effect report layout\n"); | ||
1078 | return -ENODEV; | 1075 | return -ENODEV; |
1079 | } | 1076 | } |
1080 | 1077 | ||
1081 | PIDFF_FIND_FIELDS(block_load, PID_BLOCK_LOAD, 0); | 1078 | PIDFF_FIND_FIELDS(block_load, PID_BLOCK_LOAD, 0); |
1082 | if (!pidff->block_load[PID_EFFECT_BLOCK_INDEX].value) { | 1079 | if (!pidff->block_load[PID_EFFECT_BLOCK_INDEX].value) { |
1083 | printk(KERN_ERR | 1080 | hid_err(pidff->hid, "unknown pid_block_load report layout\n"); |
1084 | "hid-pidff: unknown pid_block_load report layout\n"); | ||
1085 | return -ENODEV; | 1081 | return -ENODEV; |
1086 | } | 1082 | } |
1087 | 1083 | ||
1088 | if (PIDFF_FIND_FIELDS(effect_operation, PID_EFFECT_OPERATION, 1)) { | 1084 | if (PIDFF_FIND_FIELDS(effect_operation, PID_EFFECT_OPERATION, 1)) { |
1089 | printk(KERN_ERR | 1085 | hid_err(pidff->hid, "unknown effect_operation report layout\n"); |
1090 | "hid-pidff: unknown effect_operation report layout\n"); | ||
1091 | return -ENODEV; | 1086 | return -ENODEV; |
1092 | } | 1087 | } |
1093 | 1088 | ||
1094 | if (PIDFF_FIND_FIELDS(block_free, PID_BLOCK_FREE, 1)) { | 1089 | if (PIDFF_FIND_FIELDS(block_free, PID_BLOCK_FREE, 1)) { |
1095 | printk(KERN_ERR | 1090 | hid_err(pidff->hid, "unknown pid_block_free report layout\n"); |
1096 | "hid-pidff: unknown pid_block_free report layout\n"); | ||
1097 | return -ENODEV; | 1091 | return -ENODEV; |
1098 | } | 1092 | } |
1099 | 1093 | ||
@@ -1105,27 +1099,26 @@ static int pidff_init_fields(struct pidff_device *pidff, struct input_dev *dev) | |||
1105 | 1099 | ||
1106 | if (!envelope_ok) { | 1100 | if (!envelope_ok) { |
1107 | if (test_and_clear_bit(FF_CONSTANT, dev->ffbit)) | 1101 | if (test_and_clear_bit(FF_CONSTANT, dev->ffbit)) |
1108 | printk(KERN_WARNING "hid-pidff: " | 1102 | hid_warn(pidff->hid, |
1109 | "has constant effect but no envelope\n"); | 1103 | "has constant effect but no envelope\n"); |
1110 | if (test_and_clear_bit(FF_RAMP, dev->ffbit)) | 1104 | if (test_and_clear_bit(FF_RAMP, dev->ffbit)) |
1111 | printk(KERN_WARNING "hid-pidff: " | 1105 | hid_warn(pidff->hid, |
1112 | "has ramp effect but no envelope\n"); | 1106 | "has ramp effect but no envelope\n"); |
1113 | 1107 | ||
1114 | if (test_and_clear_bit(FF_PERIODIC, dev->ffbit)) | 1108 | if (test_and_clear_bit(FF_PERIODIC, dev->ffbit)) |
1115 | printk(KERN_WARNING "hid-pidff: " | 1109 | hid_warn(pidff->hid, |
1116 | "has periodic effect but no envelope\n"); | 1110 | "has periodic effect but no envelope\n"); |
1117 | } | 1111 | } |
1118 | 1112 | ||
1119 | if (test_bit(FF_CONSTANT, dev->ffbit) && | 1113 | if (test_bit(FF_CONSTANT, dev->ffbit) && |
1120 | PIDFF_FIND_FIELDS(set_constant, PID_SET_CONSTANT, 1)) { | 1114 | PIDFF_FIND_FIELDS(set_constant, PID_SET_CONSTANT, 1)) { |
1121 | printk(KERN_WARNING | 1115 | hid_warn(pidff->hid, "unknown constant effect layout\n"); |
1122 | "hid-pidff: unknown constant effect layout\n"); | ||
1123 | clear_bit(FF_CONSTANT, dev->ffbit); | 1116 | clear_bit(FF_CONSTANT, dev->ffbit); |
1124 | } | 1117 | } |
1125 | 1118 | ||
1126 | if (test_bit(FF_RAMP, dev->ffbit) && | 1119 | if (test_bit(FF_RAMP, dev->ffbit) && |
1127 | PIDFF_FIND_FIELDS(set_ramp, PID_SET_RAMP, 1)) { | 1120 | PIDFF_FIND_FIELDS(set_ramp, PID_SET_RAMP, 1)) { |
1128 | printk(KERN_WARNING "hid-pidff: unknown ramp effect layout\n"); | 1121 | hid_warn(pidff->hid, "unknown ramp effect layout\n"); |
1129 | clear_bit(FF_RAMP, dev->ffbit); | 1122 | clear_bit(FF_RAMP, dev->ffbit); |
1130 | } | 1123 | } |
1131 | 1124 | ||
@@ -1134,8 +1127,7 @@ static int pidff_init_fields(struct pidff_device *pidff, struct input_dev *dev) | |||
1134 | test_bit(FF_FRICTION, dev->ffbit) || | 1127 | test_bit(FF_FRICTION, dev->ffbit) || |
1135 | test_bit(FF_INERTIA, dev->ffbit)) && | 1128 | test_bit(FF_INERTIA, dev->ffbit)) && |
1136 | PIDFF_FIND_FIELDS(set_condition, PID_SET_CONDITION, 1)) { | 1129 | PIDFF_FIND_FIELDS(set_condition, PID_SET_CONDITION, 1)) { |
1137 | printk(KERN_WARNING | 1130 | hid_warn(pidff->hid, "unknown condition effect layout\n"); |
1138 | "hid-pidff: unknown condition effect layout\n"); | ||
1139 | clear_bit(FF_SPRING, dev->ffbit); | 1131 | clear_bit(FF_SPRING, dev->ffbit); |
1140 | clear_bit(FF_DAMPER, dev->ffbit); | 1132 | clear_bit(FF_DAMPER, dev->ffbit); |
1141 | clear_bit(FF_FRICTION, dev->ffbit); | 1133 | clear_bit(FF_FRICTION, dev->ffbit); |
@@ -1144,8 +1136,7 @@ static int pidff_init_fields(struct pidff_device *pidff, struct input_dev *dev) | |||
1144 | 1136 | ||
1145 | if (test_bit(FF_PERIODIC, dev->ffbit) && | 1137 | if (test_bit(FF_PERIODIC, dev->ffbit) && |
1146 | PIDFF_FIND_FIELDS(set_periodic, PID_SET_PERIODIC, 1)) { | 1138 | PIDFF_FIND_FIELDS(set_periodic, PID_SET_PERIODIC, 1)) { |
1147 | printk(KERN_WARNING | 1139 | hid_warn(pidff->hid, "unknown periodic effect layout\n"); |
1148 | "hid-pidff: unknown periodic effect layout\n"); | ||
1149 | clear_bit(FF_PERIODIC, dev->ffbit); | 1140 | clear_bit(FF_PERIODIC, dev->ffbit); |
1150 | } | 1141 | } |
1151 | 1142 | ||
@@ -1184,12 +1175,12 @@ static void pidff_reset(struct pidff_device *pidff) | |||
1184 | if (pidff->pool[PID_SIMULTANEOUS_MAX].value) { | 1175 | if (pidff->pool[PID_SIMULTANEOUS_MAX].value) { |
1185 | while (pidff->pool[PID_SIMULTANEOUS_MAX].value[0] < 2) { | 1176 | while (pidff->pool[PID_SIMULTANEOUS_MAX].value[0] < 2) { |
1186 | if (i++ > 20) { | 1177 | if (i++ > 20) { |
1187 | printk(KERN_WARNING "hid-pidff: device reports " | 1178 | hid_warn(pidff->hid, |
1188 | "%d simultaneous effects\n", | 1179 | "device reports %d simultaneous effects\n", |
1189 | pidff->pool[PID_SIMULTANEOUS_MAX].value[0]); | 1180 | pidff->pool[PID_SIMULTANEOUS_MAX].value[0]); |
1190 | break; | 1181 | break; |
1191 | } | 1182 | } |
1192 | debug("pid_pool requested again"); | 1183 | hid_dbg(pidff->hid, "pid_pool requested again\n"); |
1193 | usbhid_submit_report(hid, pidff->reports[PID_POOL], | 1184 | usbhid_submit_report(hid, pidff->reports[PID_POOL], |
1194 | USB_DIR_IN); | 1185 | USB_DIR_IN); |
1195 | usbhid_wait_io(hid); | 1186 | usbhid_wait_io(hid); |
@@ -1215,7 +1206,7 @@ static int pidff_check_autocenter(struct pidff_device *pidff, | |||
1215 | 1206 | ||
1216 | error = pidff_request_effect_upload(pidff, 1); | 1207 | error = pidff_request_effect_upload(pidff, 1); |
1217 | if (error) { | 1208 | if (error) { |
1218 | printk(KERN_ERR "hid-pidff: upload request failed\n"); | 1209 | hid_err(pidff->hid, "upload request failed\n"); |
1219 | return error; | 1210 | return error; |
1220 | } | 1211 | } |
1221 | 1212 | ||
@@ -1224,8 +1215,8 @@ static int pidff_check_autocenter(struct pidff_device *pidff, | |||
1224 | pidff_autocenter(pidff, 0xffff); | 1215 | pidff_autocenter(pidff, 0xffff); |
1225 | set_bit(FF_AUTOCENTER, dev->ffbit); | 1216 | set_bit(FF_AUTOCENTER, dev->ffbit); |
1226 | } else { | 1217 | } else { |
1227 | printk(KERN_NOTICE "hid-pidff: " | 1218 | hid_notice(pidff->hid, |
1228 | "device has unknown autocenter control method\n"); | 1219 | "device has unknown autocenter control method\n"); |
1229 | } | 1220 | } |
1230 | 1221 | ||
1231 | pidff_erase_pid(pidff, | 1222 | pidff_erase_pid(pidff, |
@@ -1248,10 +1239,10 @@ int hid_pidff_init(struct hid_device *hid) | |||
1248 | int max_effects; | 1239 | int max_effects; |
1249 | int error; | 1240 | int error; |
1250 | 1241 | ||
1251 | debug("starting pid init"); | 1242 | hid_dbg(hid, "starting pid init\n"); |
1252 | 1243 | ||
1253 | if (list_empty(&hid->report_enum[HID_OUTPUT_REPORT].report_list)) { | 1244 | if (list_empty(&hid->report_enum[HID_OUTPUT_REPORT].report_list)) { |
1254 | debug("not a PID device, no output report"); | 1245 | hid_dbg(hid, "not a PID device, no output report\n"); |
1255 | return -ENODEV; | 1246 | return -ENODEV; |
1256 | } | 1247 | } |
1257 | 1248 | ||
@@ -1265,7 +1256,7 @@ int hid_pidff_init(struct hid_device *hid) | |||
1265 | pidff_find_reports(hid, HID_FEATURE_REPORT, pidff); | 1256 | pidff_find_reports(hid, HID_FEATURE_REPORT, pidff); |
1266 | 1257 | ||
1267 | if (!pidff_reports_ok(pidff)) { | 1258 | if (!pidff_reports_ok(pidff)) { |
1268 | debug("reports not ok, aborting"); | 1259 | hid_dbg(hid, "reports not ok, aborting\n"); |
1269 | error = -ENODEV; | 1260 | error = -ENODEV; |
1270 | goto fail; | 1261 | goto fail; |
1271 | } | 1262 | } |
@@ -1278,8 +1269,8 @@ int hid_pidff_init(struct hid_device *hid) | |||
1278 | 1269 | ||
1279 | if (test_bit(FF_GAIN, dev->ffbit)) { | 1270 | if (test_bit(FF_GAIN, dev->ffbit)) { |
1280 | pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], 0xffff); | 1271 | pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], 0xffff); |
1281 | usbhid_submit_report(pidff->hid, pidff->reports[PID_DEVICE_GAIN], | 1272 | usbhid_submit_report(hid, pidff->reports[PID_DEVICE_GAIN], |
1282 | USB_DIR_OUT); | 1273 | USB_DIR_OUT); |
1283 | } | 1274 | } |
1284 | 1275 | ||
1285 | error = pidff_check_autocenter(pidff, dev); | 1276 | error = pidff_check_autocenter(pidff, dev); |
@@ -1290,23 +1281,23 @@ int hid_pidff_init(struct hid_device *hid) | |||
1290 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].field->logical_maximum - | 1281 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].field->logical_maximum - |
1291 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].field->logical_minimum + | 1282 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].field->logical_minimum + |
1292 | 1; | 1283 | 1; |
1293 | debug("max effects is %d", max_effects); | 1284 | hid_dbg(hid, "max effects is %d\n", max_effects); |
1294 | 1285 | ||
1295 | if (max_effects > PID_EFFECTS_MAX) | 1286 | if (max_effects > PID_EFFECTS_MAX) |
1296 | max_effects = PID_EFFECTS_MAX; | 1287 | max_effects = PID_EFFECTS_MAX; |
1297 | 1288 | ||
1298 | if (pidff->pool[PID_SIMULTANEOUS_MAX].value) | 1289 | if (pidff->pool[PID_SIMULTANEOUS_MAX].value) |
1299 | debug("max simultaneous effects is %d", | 1290 | hid_dbg(hid, "max simultaneous effects is %d\n", |
1300 | pidff->pool[PID_SIMULTANEOUS_MAX].value[0]); | 1291 | pidff->pool[PID_SIMULTANEOUS_MAX].value[0]); |
1301 | 1292 | ||
1302 | if (pidff->pool[PID_RAM_POOL_SIZE].value) | 1293 | if (pidff->pool[PID_RAM_POOL_SIZE].value) |
1303 | debug("device memory size is %d bytes", | 1294 | hid_dbg(hid, "device memory size is %d bytes\n", |
1304 | pidff->pool[PID_RAM_POOL_SIZE].value[0]); | 1295 | pidff->pool[PID_RAM_POOL_SIZE].value[0]); |
1305 | 1296 | ||
1306 | if (pidff->pool[PID_DEVICE_MANAGED_POOL].value && | 1297 | if (pidff->pool[PID_DEVICE_MANAGED_POOL].value && |
1307 | pidff->pool[PID_DEVICE_MANAGED_POOL].value[0] == 0) { | 1298 | pidff->pool[PID_DEVICE_MANAGED_POOL].value[0] == 0) { |
1308 | printk(KERN_NOTICE "hid-pidff: " | 1299 | hid_notice(hid, |
1309 | "device does not support device managed pool\n"); | 1300 | "device does not support device managed pool\n"); |
1310 | goto fail; | 1301 | goto fail; |
1311 | } | 1302 | } |
1312 | 1303 | ||
@@ -1322,8 +1313,7 @@ int hid_pidff_init(struct hid_device *hid) | |||
1322 | ff->set_autocenter = pidff_set_autocenter; | 1313 | ff->set_autocenter = pidff_set_autocenter; |
1323 | ff->playback = pidff_playback; | 1314 | ff->playback = pidff_playback; |
1324 | 1315 | ||
1325 | printk(KERN_INFO "Force feedback for USB HID PID devices by " | 1316 | hid_info(dev, "Force feedback for USB HID PID devices by Anssi Hannula <anssi.hannula@gmail.com>\n"); |
1326 | "Anssi Hannula <anssi.hannula@gmail.com>\n"); | ||
1327 | 1317 | ||
1328 | return 0; | 1318 | return 0; |
1329 | 1319 | ||
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index f0260c699adb..621959d5cc42 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c | |||
@@ -34,9 +34,7 @@ static const struct hid_blacklist { | |||
34 | { USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD }, | 34 | { USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD }, |
35 | { USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD }, | 35 | { USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD }, |
36 | { USB_VENDOR_ID_DWAV, USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER, HID_QUIRK_MULTI_INPUT | HID_QUIRK_NOGET }, | 36 | { USB_VENDOR_ID_DWAV, USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER, HID_QUIRK_MULTI_INPUT | HID_QUIRK_NOGET }, |
37 | { USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH, HID_QUIRK_MULTI_INPUT }, | ||
38 | { USB_VENDOR_ID_MOJO, USB_DEVICE_ID_RETRO_ADAPTER, HID_QUIRK_MULTI_INPUT }, | 37 | { USB_VENDOR_ID_MOJO, USB_DEVICE_ID_RETRO_ADAPTER, HID_QUIRK_MULTI_INPUT }, |
39 | { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART, HID_QUIRK_MULTI_INPUT }, | ||
40 | { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, | 38 | { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, |
41 | { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, | 39 | { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, |
42 | { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, | 40 | { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, |
@@ -61,17 +59,26 @@ static const struct hid_blacklist { | |||
61 | { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_COMBATSTICK, HID_QUIRK_NOGET }, | 59 | { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_COMBATSTICK, HID_QUIRK_NOGET }, |
62 | { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FLIGHT_SIM_ECLIPSE_YOKE, HID_QUIRK_NOGET }, | 60 | { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FLIGHT_SIM_ECLIPSE_YOKE, HID_QUIRK_NOGET }, |
63 | { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FLIGHT_SIM_YOKE, HID_QUIRK_NOGET }, | 61 | { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FLIGHT_SIM_YOKE, HID_QUIRK_NOGET }, |
62 | { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_PRO_THROTTLE, HID_QUIRK_NOGET }, | ||
64 | { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_PRO_PEDALS, HID_QUIRK_NOGET }, | 63 | { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_PRO_PEDALS, HID_QUIRK_NOGET }, |
65 | { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_3AXIS_5BUTTON_STICK, HID_QUIRK_NOGET }, | 64 | { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_3AXIS_5BUTTON_STICK, HID_QUIRK_NOGET }, |
65 | { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_AXIS_295, HID_QUIRK_NOGET }, | ||
66 | { USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET }, | 66 | { USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET }, |
67 | { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET }, | 67 | { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET }, |
68 | { USB_VENDOR_ID_PRODIGE, USB_DEVICE_ID_PRODIGE_CORDLESS, HID_QUIRK_NOGET }, | 68 | { USB_VENDOR_ID_PRODIGE, USB_DEVICE_ID_PRODIGE_CORDLESS, HID_QUIRK_NOGET }, |
69 | { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NOGET }, | 69 | { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NOGET }, |
70 | { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET }, | 70 | { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET }, |
71 | { USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_1, HID_QUIRK_NOGET }, | ||
72 | { USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_2, HID_QUIRK_NOGET }, | ||
71 | { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET }, | 73 | { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET }, |
72 | { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209, HID_QUIRK_MULTI_INPUT }, | 74 | { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209, HID_QUIRK_MULTI_INPUT }, |
73 | { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U, HID_QUIRK_MULTI_INPUT }, | 75 | { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U, HID_QUIRK_MULTI_INPUT }, |
74 | { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_KNA5, HID_QUIRK_MULTI_INPUT }, | 76 | { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_KNA5, HID_QUIRK_MULTI_INPUT }, |
77 | { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_TWA60, HID_QUIRK_MULTI_INPUT }, | ||
78 | { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U, HID_QUIRK_MULTI_INPUT }, | ||
79 | { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U, HID_QUIRK_MULTI_INPUT }, | ||
80 | { USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH, HID_QUIRK_MULTI_INPUT }, | ||
81 | { USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH, HID_QUIRK_MULTI_INPUT }, | ||
75 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS }, | 82 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS }, |
76 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, | 83 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, |
77 | 84 | ||
@@ -81,7 +88,7 @@ static const struct hid_blacklist { | |||
81 | { USB_VENDOR_ID_PI_ENGINEERING, USB_DEVICE_ID_PI_ENGINEERING_VEC_USB_FOOTPEDAL, HID_QUIRK_HIDINPUT_FORCE }, | 88 | { USB_VENDOR_ID_PI_ENGINEERING, USB_DEVICE_ID_PI_ENGINEERING_VEC_USB_FOOTPEDAL, HID_QUIRK_HIDINPUT_FORCE }, |
82 | 89 | ||
83 | { USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_MULTI_TOUCH, HID_QUIRK_MULTI_INPUT }, | 90 | { USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_MULTI_TOUCH, HID_QUIRK_MULTI_INPUT }, |
84 | 91 | { USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS, HID_QUIRK_MULTI_INPUT }, | |
85 | { 0, 0 } | 92 | { 0, 0 } |
86 | }; | 93 | }; |
87 | 94 | ||
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index 681e620eb95b..7c1188b53c3e 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c | |||
@@ -29,7 +29,6 @@ | |||
29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
31 | #include <linux/init.h> | 31 | #include <linux/init.h> |
32 | #include <linux/smp_lock.h> | ||
33 | #include <linux/input.h> | 32 | #include <linux/input.h> |
34 | #include <linux/usb.h> | 33 | #include <linux/usb.h> |
35 | #include <linux/hid.h> | 34 | #include <linux/hid.h> |
@@ -67,8 +66,6 @@ struct hiddev_list { | |||
67 | struct mutex thread_lock; | 66 | struct mutex thread_lock; |
68 | }; | 67 | }; |
69 | 68 | ||
70 | static struct usb_driver hiddev_driver; | ||
71 | |||
72 | /* | 69 | /* |
73 | * Find a report, given the report's type and ID. The ID can be specified | 70 | * Find a report, given the report's type and ID. The ID can be specified |
74 | * indirectly by REPORT_ID_FIRST (which returns the first report of the given | 71 | * indirectly by REPORT_ID_FIRST (which returns the first report of the given |
@@ -245,15 +242,20 @@ static int hiddev_release(struct inode * inode, struct file * file) | |||
245 | list_del(&list->node); | 242 | list_del(&list->node); |
246 | spin_unlock_irqrestore(&list->hiddev->list_lock, flags); | 243 | spin_unlock_irqrestore(&list->hiddev->list_lock, flags); |
247 | 244 | ||
245 | mutex_lock(&list->hiddev->existancelock); | ||
248 | if (!--list->hiddev->open) { | 246 | if (!--list->hiddev->open) { |
249 | if (list->hiddev->exist) { | 247 | if (list->hiddev->exist) { |
250 | usbhid_close(list->hiddev->hid); | 248 | usbhid_close(list->hiddev->hid); |
251 | usbhid_put_power(list->hiddev->hid); | 249 | usbhid_put_power(list->hiddev->hid); |
252 | } else { | 250 | } else { |
251 | mutex_unlock(&list->hiddev->existancelock); | ||
253 | kfree(list->hiddev); | 252 | kfree(list->hiddev); |
253 | kfree(list); | ||
254 | return 0; | ||
254 | } | 255 | } |
255 | } | 256 | } |
256 | 257 | ||
258 | mutex_unlock(&list->hiddev->existancelock); | ||
257 | kfree(list); | 259 | kfree(list); |
258 | 260 | ||
259 | return 0; | 261 | return 0; |
@@ -303,17 +305,21 @@ static int hiddev_open(struct inode *inode, struct file *file) | |||
303 | list_add_tail(&list->node, &hiddev->list); | 305 | list_add_tail(&list->node, &hiddev->list); |
304 | spin_unlock_irq(&list->hiddev->list_lock); | 306 | spin_unlock_irq(&list->hiddev->list_lock); |
305 | 307 | ||
308 | mutex_lock(&hiddev->existancelock); | ||
306 | if (!list->hiddev->open++) | 309 | if (!list->hiddev->open++) |
307 | if (list->hiddev->exist) { | 310 | if (list->hiddev->exist) { |
308 | struct hid_device *hid = hiddev->hid; | 311 | struct hid_device *hid = hiddev->hid; |
309 | res = usbhid_get_power(hid); | 312 | res = usbhid_get_power(hid); |
310 | if (res < 0) { | 313 | if (res < 0) { |
311 | res = -EIO; | 314 | res = -EIO; |
312 | goto bail; | 315 | goto bail_unlock; |
313 | } | 316 | } |
314 | usbhid_open(hid); | 317 | usbhid_open(hid); |
315 | } | 318 | } |
319 | mutex_unlock(&hiddev->existancelock); | ||
316 | return 0; | 320 | return 0; |
321 | bail_unlock: | ||
322 | mutex_unlock(&hiddev->existancelock); | ||
317 | bail: | 323 | bail: |
318 | file->private_data = NULL; | 324 | file->private_data = NULL; |
319 | kfree(list); | 325 | kfree(list); |
@@ -370,8 +376,10 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun | |||
370 | /* let O_NONBLOCK tasks run */ | 376 | /* let O_NONBLOCK tasks run */ |
371 | mutex_unlock(&list->thread_lock); | 377 | mutex_unlock(&list->thread_lock); |
372 | schedule(); | 378 | schedule(); |
373 | if (mutex_lock_interruptible(&list->thread_lock)) | 379 | if (mutex_lock_interruptible(&list->thread_lock)) { |
380 | finish_wait(&list->hiddev->wait, &wait); | ||
374 | return -EINTR; | 381 | return -EINTR; |
382 | } | ||
375 | set_current_state(TASK_INTERRUPTIBLE); | 383 | set_current_state(TASK_INTERRUPTIBLE); |
376 | } | 384 | } |
377 | finish_wait(&list->hiddev->wait, &wait); | 385 | finish_wait(&list->hiddev->wait, &wait); |
@@ -512,7 +520,7 @@ static noinline int hiddev_ioctl_usage(struct hiddev *hiddev, unsigned int cmd, | |||
512 | (uref_multi->num_values > HID_MAX_MULTI_USAGES || | 520 | (uref_multi->num_values > HID_MAX_MULTI_USAGES || |
513 | uref->usage_index + uref_multi->num_values > field->report_count)) | 521 | uref->usage_index + uref_multi->num_values > field->report_count)) |
514 | goto inval; | 522 | goto inval; |
515 | } | 523 | } |
516 | 524 | ||
517 | switch (cmd) { | 525 | switch (cmd) { |
518 | case HIDIOCGUSAGE: | 526 | case HIDIOCGUSAGE: |
@@ -588,163 +596,168 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
588 | { | 596 | { |
589 | struct hiddev_list *list = file->private_data; | 597 | struct hiddev_list *list = file->private_data; |
590 | struct hiddev *hiddev = list->hiddev; | 598 | struct hiddev *hiddev = list->hiddev; |
591 | struct hid_device *hid = hiddev->hid; | 599 | struct hid_device *hid; |
592 | struct usb_device *dev; | ||
593 | struct hiddev_collection_info cinfo; | 600 | struct hiddev_collection_info cinfo; |
594 | struct hiddev_report_info rinfo; | 601 | struct hiddev_report_info rinfo; |
595 | struct hiddev_field_info finfo; | 602 | struct hiddev_field_info finfo; |
596 | struct hiddev_devinfo dinfo; | 603 | struct hiddev_devinfo dinfo; |
597 | struct hid_report *report; | 604 | struct hid_report *report; |
598 | struct hid_field *field; | 605 | struct hid_field *field; |
599 | struct usbhid_device *usbhid = hid->driver_data; | ||
600 | void __user *user_arg = (void __user *)arg; | 606 | void __user *user_arg = (void __user *)arg; |
601 | int i, r; | 607 | int i, r = -EINVAL; |
602 | 608 | ||
603 | /* Called without BKL by compat methods so no BKL taken */ | 609 | /* Called without BKL by compat methods so no BKL taken */ |
604 | 610 | ||
605 | /* FIXME: Who or what stop this racing with a disconnect ?? */ | 611 | mutex_lock(&hiddev->existancelock); |
606 | if (!hiddev->exist || !hid) | 612 | if (!hiddev->exist) { |
607 | return -EIO; | 613 | r = -ENODEV; |
614 | goto ret_unlock; | ||
615 | } | ||
608 | 616 | ||
609 | dev = hid_to_usb_dev(hid); | 617 | hid = hiddev->hid; |
610 | 618 | ||
611 | switch (cmd) { | 619 | switch (cmd) { |
612 | 620 | ||
613 | case HIDIOCGVERSION: | 621 | case HIDIOCGVERSION: |
614 | return put_user(HID_VERSION, (int __user *)arg); | 622 | r = put_user(HID_VERSION, (int __user *)arg) ? |
623 | -EFAULT : 0; | ||
624 | break; | ||
615 | 625 | ||
616 | case HIDIOCAPPLICATION: | 626 | case HIDIOCAPPLICATION: |
617 | if (arg < 0 || arg >= hid->maxapplication) | 627 | if (arg < 0 || arg >= hid->maxapplication) |
618 | return -EINVAL; | 628 | break; |
619 | 629 | ||
620 | for (i = 0; i < hid->maxcollection; i++) | 630 | for (i = 0; i < hid->maxcollection; i++) |
621 | if (hid->collection[i].type == | 631 | if (hid->collection[i].type == |
622 | HID_COLLECTION_APPLICATION && arg-- == 0) | 632 | HID_COLLECTION_APPLICATION && arg-- == 0) |
623 | break; | 633 | break; |
624 | 634 | ||
625 | if (i == hid->maxcollection) | 635 | if (i < hid->maxcollection) |
626 | return -EINVAL; | 636 | r = hid->collection[i].usage; |
627 | 637 | break; | |
628 | return hid->collection[i].usage; | ||
629 | 638 | ||
630 | case HIDIOCGDEVINFO: | 639 | case HIDIOCGDEVINFO: |
631 | dinfo.bustype = BUS_USB; | 640 | { |
632 | dinfo.busnum = dev->bus->busnum; | 641 | struct usb_device *dev = hid_to_usb_dev(hid); |
633 | dinfo.devnum = dev->devnum; | 642 | struct usbhid_device *usbhid = hid->driver_data; |
634 | dinfo.ifnum = usbhid->ifnum; | 643 | |
635 | dinfo.vendor = le16_to_cpu(dev->descriptor.idVendor); | 644 | dinfo.bustype = BUS_USB; |
636 | dinfo.product = le16_to_cpu(dev->descriptor.idProduct); | 645 | dinfo.busnum = dev->bus->busnum; |
637 | dinfo.version = le16_to_cpu(dev->descriptor.bcdDevice); | 646 | dinfo.devnum = dev->devnum; |
638 | dinfo.num_applications = hid->maxapplication; | 647 | dinfo.ifnum = usbhid->ifnum; |
639 | if (copy_to_user(user_arg, &dinfo, sizeof(dinfo))) | 648 | dinfo.vendor = le16_to_cpu(dev->descriptor.idVendor); |
640 | return -EFAULT; | 649 | dinfo.product = le16_to_cpu(dev->descriptor.idProduct); |
641 | 650 | dinfo.version = le16_to_cpu(dev->descriptor.bcdDevice); | |
642 | return 0; | 651 | dinfo.num_applications = hid->maxapplication; |
652 | |||
653 | r = copy_to_user(user_arg, &dinfo, sizeof(dinfo)) ? | ||
654 | -EFAULT : 0; | ||
655 | break; | ||
656 | } | ||
643 | 657 | ||
644 | case HIDIOCGFLAG: | 658 | case HIDIOCGFLAG: |
645 | if (put_user(list->flags, (int __user *)arg)) | 659 | r = put_user(list->flags, (int __user *)arg) ? |
646 | return -EFAULT; | 660 | -EFAULT : 0; |
647 | 661 | break; | |
648 | return 0; | ||
649 | 662 | ||
650 | case HIDIOCSFLAG: | 663 | case HIDIOCSFLAG: |
651 | { | 664 | { |
652 | int newflags; | 665 | int newflags; |
653 | if (get_user(newflags, (int __user *)arg)) | 666 | |
654 | return -EFAULT; | 667 | if (get_user(newflags, (int __user *)arg)) { |
668 | r = -EFAULT; | ||
669 | break; | ||
670 | } | ||
655 | 671 | ||
656 | if ((newflags & ~HIDDEV_FLAGS) != 0 || | 672 | if ((newflags & ~HIDDEV_FLAGS) != 0 || |
657 | ((newflags & HIDDEV_FLAG_REPORT) != 0 && | 673 | ((newflags & HIDDEV_FLAG_REPORT) != 0 && |
658 | (newflags & HIDDEV_FLAG_UREF) == 0)) | 674 | (newflags & HIDDEV_FLAG_UREF) == 0)) |
659 | return -EINVAL; | 675 | break; |
660 | 676 | ||
661 | list->flags = newflags; | 677 | list->flags = newflags; |
662 | 678 | ||
663 | return 0; | 679 | r = 0; |
680 | break; | ||
664 | } | 681 | } |
665 | 682 | ||
666 | case HIDIOCGSTRING: | 683 | case HIDIOCGSTRING: |
667 | mutex_lock(&hiddev->existancelock); | 684 | r = hiddev_ioctl_string(hiddev, cmd, user_arg); |
668 | if (hiddev->exist) | 685 | break; |
669 | r = hiddev_ioctl_string(hiddev, cmd, user_arg); | ||
670 | else | ||
671 | r = -ENODEV; | ||
672 | mutex_unlock(&hiddev->existancelock); | ||
673 | return r; | ||
674 | 686 | ||
675 | case HIDIOCINITREPORT: | 687 | case HIDIOCINITREPORT: |
676 | mutex_lock(&hiddev->existancelock); | ||
677 | if (!hiddev->exist) { | ||
678 | mutex_unlock(&hiddev->existancelock); | ||
679 | return -ENODEV; | ||
680 | } | ||
681 | usbhid_init_reports(hid); | 688 | usbhid_init_reports(hid); |
682 | mutex_unlock(&hiddev->existancelock); | 689 | r = 0; |
683 | 690 | break; | |
684 | return 0; | ||
685 | 691 | ||
686 | case HIDIOCGREPORT: | 692 | case HIDIOCGREPORT: |
687 | if (copy_from_user(&rinfo, user_arg, sizeof(rinfo))) | 693 | if (copy_from_user(&rinfo, user_arg, sizeof(rinfo))) { |
688 | return -EFAULT; | 694 | r = -EFAULT; |
695 | break; | ||
696 | } | ||
689 | 697 | ||
690 | if (rinfo.report_type == HID_REPORT_TYPE_OUTPUT) | 698 | if (rinfo.report_type == HID_REPORT_TYPE_OUTPUT) |
691 | return -EINVAL; | 699 | break; |
692 | 700 | ||
693 | if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) | 701 | report = hiddev_lookup_report(hid, &rinfo); |
694 | return -EINVAL; | 702 | if (report == NULL) |
703 | break; | ||
695 | 704 | ||
696 | mutex_lock(&hiddev->existancelock); | 705 | usbhid_submit_report(hid, report, USB_DIR_IN); |
697 | if (hiddev->exist) { | 706 | usbhid_wait_io(hid); |
698 | usbhid_submit_report(hid, report, USB_DIR_IN); | ||
699 | usbhid_wait_io(hid); | ||
700 | } | ||
701 | mutex_unlock(&hiddev->existancelock); | ||
702 | 707 | ||
703 | return 0; | 708 | r = 0; |
709 | break; | ||
704 | 710 | ||
705 | case HIDIOCSREPORT: | 711 | case HIDIOCSREPORT: |
706 | if (copy_from_user(&rinfo, user_arg, sizeof(rinfo))) | 712 | if (copy_from_user(&rinfo, user_arg, sizeof(rinfo))) { |
707 | return -EFAULT; | 713 | r = -EFAULT; |
714 | break; | ||
715 | } | ||
708 | 716 | ||
709 | if (rinfo.report_type == HID_REPORT_TYPE_INPUT) | 717 | if (rinfo.report_type == HID_REPORT_TYPE_INPUT) |
710 | return -EINVAL; | 718 | break; |
711 | 719 | ||
712 | if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) | 720 | report = hiddev_lookup_report(hid, &rinfo); |
713 | return -EINVAL; | 721 | if (report == NULL) |
722 | break; | ||
714 | 723 | ||
715 | mutex_lock(&hiddev->existancelock); | 724 | usbhid_submit_report(hid, report, USB_DIR_OUT); |
716 | if (hiddev->exist) { | 725 | usbhid_wait_io(hid); |
717 | usbhid_submit_report(hid, report, USB_DIR_OUT); | ||
718 | usbhid_wait_io(hid); | ||
719 | } | ||
720 | mutex_unlock(&hiddev->existancelock); | ||
721 | 726 | ||
722 | return 0; | 727 | r = 0; |
728 | break; | ||
723 | 729 | ||
724 | case HIDIOCGREPORTINFO: | 730 | case HIDIOCGREPORTINFO: |
725 | if (copy_from_user(&rinfo, user_arg, sizeof(rinfo))) | 731 | if (copy_from_user(&rinfo, user_arg, sizeof(rinfo))) { |
726 | return -EFAULT; | 732 | r = -EFAULT; |
733 | break; | ||
734 | } | ||
727 | 735 | ||
728 | if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) | 736 | report = hiddev_lookup_report(hid, &rinfo); |
729 | return -EINVAL; | 737 | if (report == NULL) |
738 | break; | ||
730 | 739 | ||
731 | rinfo.num_fields = report->maxfield; | 740 | rinfo.num_fields = report->maxfield; |
732 | 741 | ||
733 | if (copy_to_user(user_arg, &rinfo, sizeof(rinfo))) | 742 | r = copy_to_user(user_arg, &rinfo, sizeof(rinfo)) ? |
734 | return -EFAULT; | 743 | -EFAULT : 0; |
735 | 744 | break; | |
736 | return 0; | ||
737 | 745 | ||
738 | case HIDIOCGFIELDINFO: | 746 | case HIDIOCGFIELDINFO: |
739 | if (copy_from_user(&finfo, user_arg, sizeof(finfo))) | 747 | if (copy_from_user(&finfo, user_arg, sizeof(finfo))) { |
740 | return -EFAULT; | 748 | r = -EFAULT; |
749 | break; | ||
750 | } | ||
751 | |||
741 | rinfo.report_type = finfo.report_type; | 752 | rinfo.report_type = finfo.report_type; |
742 | rinfo.report_id = finfo.report_id; | 753 | rinfo.report_id = finfo.report_id; |
743 | if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) | 754 | |
744 | return -EINVAL; | 755 | report = hiddev_lookup_report(hid, &rinfo); |
756 | if (report == NULL) | ||
757 | break; | ||
745 | 758 | ||
746 | if (finfo.field_index >= report->maxfield) | 759 | if (finfo.field_index >= report->maxfield) |
747 | return -EINVAL; | 760 | break; |
748 | 761 | ||
749 | field = report->field[finfo.field_index]; | 762 | field = report->field[finfo.field_index]; |
750 | memset(&finfo, 0, sizeof(finfo)); | 763 | memset(&finfo, 0, sizeof(finfo)); |
@@ -763,10 +776,9 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
763 | finfo.unit_exponent = field->unit_exponent; | 776 | finfo.unit_exponent = field->unit_exponent; |
764 | finfo.unit = field->unit; | 777 | finfo.unit = field->unit; |
765 | 778 | ||
766 | if (copy_to_user(user_arg, &finfo, sizeof(finfo))) | 779 | r = copy_to_user(user_arg, &finfo, sizeof(finfo)) ? |
767 | return -EFAULT; | 780 | -EFAULT : 0; |
768 | 781 | break; | |
769 | return 0; | ||
770 | 782 | ||
771 | case HIDIOCGUCODE: | 783 | case HIDIOCGUCODE: |
772 | /* fall through */ | 784 | /* fall through */ |
@@ -775,57 +787,52 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
775 | case HIDIOCGUSAGES: | 787 | case HIDIOCGUSAGES: |
776 | case HIDIOCSUSAGES: | 788 | case HIDIOCSUSAGES: |
777 | case HIDIOCGCOLLECTIONINDEX: | 789 | case HIDIOCGCOLLECTIONINDEX: |
778 | mutex_lock(&hiddev->existancelock); | 790 | r = hiddev_ioctl_usage(hiddev, cmd, user_arg); |
779 | if (hiddev->exist) | 791 | break; |
780 | r = hiddev_ioctl_usage(hiddev, cmd, user_arg); | ||
781 | else | ||
782 | r = -ENODEV; | ||
783 | mutex_unlock(&hiddev->existancelock); | ||
784 | return r; | ||
785 | 792 | ||
786 | case HIDIOCGCOLLECTIONINFO: | 793 | case HIDIOCGCOLLECTIONINFO: |
787 | if (copy_from_user(&cinfo, user_arg, sizeof(cinfo))) | 794 | if (copy_from_user(&cinfo, user_arg, sizeof(cinfo))) { |
788 | return -EFAULT; | 795 | r = -EFAULT; |
796 | break; | ||
797 | } | ||
789 | 798 | ||
790 | if (cinfo.index >= hid->maxcollection) | 799 | if (cinfo.index >= hid->maxcollection) |
791 | return -EINVAL; | 800 | break; |
792 | 801 | ||
793 | cinfo.type = hid->collection[cinfo.index].type; | 802 | cinfo.type = hid->collection[cinfo.index].type; |
794 | cinfo.usage = hid->collection[cinfo.index].usage; | 803 | cinfo.usage = hid->collection[cinfo.index].usage; |
795 | cinfo.level = hid->collection[cinfo.index].level; | 804 | cinfo.level = hid->collection[cinfo.index].level; |
796 | 805 | ||
797 | if (copy_to_user(user_arg, &cinfo, sizeof(cinfo))) | 806 | r = copy_to_user(user_arg, &cinfo, sizeof(cinfo)) ? |
798 | return -EFAULT; | 807 | -EFAULT : 0; |
799 | return 0; | 808 | break; |
800 | 809 | ||
801 | default: | 810 | default: |
802 | |||
803 | if (_IOC_TYPE(cmd) != 'H' || _IOC_DIR(cmd) != _IOC_READ) | 811 | if (_IOC_TYPE(cmd) != 'H' || _IOC_DIR(cmd) != _IOC_READ) |
804 | return -EINVAL; | 812 | break; |
805 | 813 | ||
806 | if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGNAME(0))) { | 814 | if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGNAME(0))) { |
807 | int len; | 815 | int len = strlen(hid->name) + 1; |
808 | if (!hid->name) | ||
809 | return 0; | ||
810 | len = strlen(hid->name) + 1; | ||
811 | if (len > _IOC_SIZE(cmd)) | 816 | if (len > _IOC_SIZE(cmd)) |
812 | len = _IOC_SIZE(cmd); | 817 | len = _IOC_SIZE(cmd); |
813 | return copy_to_user(user_arg, hid->name, len) ? | 818 | r = copy_to_user(user_arg, hid->name, len) ? |
814 | -EFAULT : len; | 819 | -EFAULT : len; |
820 | break; | ||
815 | } | 821 | } |
816 | 822 | ||
817 | if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGPHYS(0))) { | 823 | if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGPHYS(0))) { |
818 | int len; | 824 | int len = strlen(hid->phys) + 1; |
819 | if (!hid->phys) | ||
820 | return 0; | ||
821 | len = strlen(hid->phys) + 1; | ||
822 | if (len > _IOC_SIZE(cmd)) | 825 | if (len > _IOC_SIZE(cmd)) |
823 | len = _IOC_SIZE(cmd); | 826 | len = _IOC_SIZE(cmd); |
824 | return copy_to_user(user_arg, hid->phys, len) ? | 827 | r = copy_to_user(user_arg, hid->phys, len) ? |
825 | -EFAULT : len; | 828 | -EFAULT : len; |
829 | break; | ||
826 | } | 830 | } |
827 | } | 831 | } |
828 | return -EINVAL; | 832 | |
833 | ret_unlock: | ||
834 | mutex_unlock(&hiddev->existancelock); | ||
835 | return r; | ||
829 | } | 836 | } |
830 | 837 | ||
831 | #ifdef CONFIG_COMPAT | 838 | #ifdef CONFIG_COMPAT |
@@ -847,6 +854,7 @@ static const struct file_operations hiddev_fops = { | |||
847 | #ifdef CONFIG_COMPAT | 854 | #ifdef CONFIG_COMPAT |
848 | .compat_ioctl = hiddev_compat_ioctl, | 855 | .compat_ioctl = hiddev_compat_ioctl, |
849 | #endif | 856 | #endif |
857 | .llseek = noop_llseek, | ||
850 | }; | 858 | }; |
851 | 859 | ||
852 | static char *hiddev_devnode(struct device *dev, mode_t *mode) | 860 | static char *hiddev_devnode(struct device *dev, mode_t *mode) |
@@ -894,7 +902,7 @@ int hiddev_connect(struct hid_device *hid, unsigned int force) | |||
894 | hiddev->exist = 1; | 902 | hiddev->exist = 1; |
895 | retval = usb_register_dev(usbhid->intf, &hiddev_class); | 903 | retval = usb_register_dev(usbhid->intf, &hiddev_class); |
896 | if (retval) { | 904 | if (retval) { |
897 | err_hid("Not able to get a minor for this device."); | 905 | hid_err(hid, "Not able to get a minor for this device\n"); |
898 | hid->hiddev = NULL; | 906 | hid->hiddev = NULL; |
899 | kfree(hiddev); | 907 | kfree(hiddev); |
900 | return -1; | 908 | return -1; |
@@ -914,52 +922,15 @@ void hiddev_disconnect(struct hid_device *hid) | |||
914 | 922 | ||
915 | mutex_lock(&hiddev->existancelock); | 923 | mutex_lock(&hiddev->existancelock); |
916 | hiddev->exist = 0; | 924 | hiddev->exist = 0; |
917 | mutex_unlock(&hiddev->existancelock); | ||
918 | 925 | ||
919 | usb_deregister_dev(usbhid->intf, &hiddev_class); | 926 | usb_deregister_dev(usbhid->intf, &hiddev_class); |
920 | 927 | ||
921 | if (hiddev->open) { | 928 | if (hiddev->open) { |
929 | mutex_unlock(&hiddev->existancelock); | ||
922 | usbhid_close(hiddev->hid); | 930 | usbhid_close(hiddev->hid); |
923 | wake_up_interruptible(&hiddev->wait); | 931 | wake_up_interruptible(&hiddev->wait); |
924 | } else { | 932 | } else { |
933 | mutex_unlock(&hiddev->existancelock); | ||
925 | kfree(hiddev); | 934 | kfree(hiddev); |
926 | } | 935 | } |
927 | } | 936 | } |
928 | |||
929 | /* Currently this driver is a USB driver. It's not a conventional one in | ||
930 | * the sense that it doesn't probe at the USB level. Instead it waits to | ||
931 | * be connected by HID through the hiddev_connect / hiddev_disconnect | ||
932 | * routines. The reason to register as a USB device is to gain part of the | ||
933 | * minor number space from the USB major. | ||
934 | * | ||
935 | * In theory, should the HID code be generalized to more than one physical | ||
936 | * medium (say, IEEE 1384), this driver will probably need to register its | ||
937 | * own major number, and in doing so, no longer need to register with USB. | ||
938 | * At that point the probe routine and hiddev_driver struct below will no | ||
939 | * longer be useful. | ||
940 | */ | ||
941 | |||
942 | |||
943 | /* We never attach in this manner, and rely on HID to connect us. This | ||
944 | * is why there is no disconnect routine defined in the usb_driver either. | ||
945 | */ | ||
946 | static int hiddev_usbd_probe(struct usb_interface *intf, | ||
947 | const struct usb_device_id *hiddev_info) | ||
948 | { | ||
949 | return -ENODEV; | ||
950 | } | ||
951 | |||
952 | static /* const */ struct usb_driver hiddev_driver = { | ||
953 | .name = "hiddev", | ||
954 | .probe = hiddev_usbd_probe, | ||
955 | }; | ||
956 | |||
957 | int __init hiddev_init(void) | ||
958 | { | ||
959 | return usb_register(&hiddev_driver); | ||
960 | } | ||
961 | |||
962 | void hiddev_exit(void) | ||
963 | { | ||
964 | usb_deregister(&hiddev_driver); | ||
965 | } | ||
diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h index 89d2e847dcc6..1673cac93d77 100644 --- a/drivers/hid/usbhid/usbhid.h +++ b/drivers/hid/usbhid/usbhid.h | |||
@@ -95,7 +95,6 @@ struct usbhid_device { | |||
95 | unsigned long stop_retry; /* Time to give up, in jiffies */ | 95 | unsigned long stop_retry; /* Time to give up, in jiffies */ |
96 | unsigned int retry_delay; /* Delay length in ms */ | 96 | unsigned int retry_delay; /* Delay length in ms */ |
97 | struct work_struct reset_work; /* Task context for resets */ | 97 | struct work_struct reset_work; /* Task context for resets */ |
98 | struct work_struct restart_work; /* waking up for output to be done in a task */ | ||
99 | wait_queue_head_t wait; /* For sleeping */ | 98 | wait_queue_head_t wait; /* For sleeping */ |
100 | int ledcount; /* counting the number of active leds */ | 99 | int ledcount; /* counting the number of active leds */ |
101 | }; | 100 | }; |
diff --git a/drivers/hid/usbhid/usbkbd.c b/drivers/hid/usbhid/usbkbd.c index a948605564fb..065817329f03 100644 --- a/drivers/hid/usbhid/usbkbd.c +++ b/drivers/hid/usbhid/usbkbd.c | |||
@@ -24,6 +24,8 @@ | |||
24 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic | 24 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic |
25 | */ | 25 | */ |
26 | 26 | ||
27 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
28 | |||
27 | #include <linux/kernel.h> | 29 | #include <linux/kernel.h> |
28 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
29 | #include <linux/module.h> | 31 | #include <linux/module.h> |
@@ -104,16 +106,18 @@ static void usb_kbd_irq(struct urb *urb) | |||
104 | if (usb_kbd_keycode[kbd->old[i]]) | 106 | if (usb_kbd_keycode[kbd->old[i]]) |
105 | input_report_key(kbd->dev, usb_kbd_keycode[kbd->old[i]], 0); | 107 | input_report_key(kbd->dev, usb_kbd_keycode[kbd->old[i]], 0); |
106 | else | 108 | else |
107 | dev_info(&urb->dev->dev, | 109 | hid_info(urb->dev, |
108 | "Unknown key (scancode %#x) released.\n", kbd->old[i]); | 110 | "Unknown key (scancode %#x) released.\n", |
111 | kbd->old[i]); | ||
109 | } | 112 | } |
110 | 113 | ||
111 | if (kbd->new[i] > 3 && memscan(kbd->old + 2, kbd->new[i], 6) == kbd->old + 8) { | 114 | if (kbd->new[i] > 3 && memscan(kbd->old + 2, kbd->new[i], 6) == kbd->old + 8) { |
112 | if (usb_kbd_keycode[kbd->new[i]]) | 115 | if (usb_kbd_keycode[kbd->new[i]]) |
113 | input_report_key(kbd->dev, usb_kbd_keycode[kbd->new[i]], 1); | 116 | input_report_key(kbd->dev, usb_kbd_keycode[kbd->new[i]], 1); |
114 | else | 117 | else |
115 | dev_info(&urb->dev->dev, | 118 | hid_info(urb->dev, |
116 | "Unknown key (scancode %#x) released.\n", kbd->new[i]); | 119 | "Unknown key (scancode %#x) released.\n", |
120 | kbd->new[i]); | ||
117 | } | 121 | } |
118 | } | 122 | } |
119 | 123 | ||
@@ -124,9 +128,9 @@ static void usb_kbd_irq(struct urb *urb) | |||
124 | resubmit: | 128 | resubmit: |
125 | i = usb_submit_urb (urb, GFP_ATOMIC); | 129 | i = usb_submit_urb (urb, GFP_ATOMIC); |
126 | if (i) | 130 | if (i) |
127 | err_hid ("can't resubmit intr, %s-%s/input0, status %d", | 131 | hid_err(urb->dev, "can't resubmit intr, %s-%s/input0, status %d", |
128 | kbd->usbdev->bus->bus_name, | 132 | kbd->usbdev->bus->bus_name, |
129 | kbd->usbdev->devpath, i); | 133 | kbd->usbdev->devpath, i); |
130 | } | 134 | } |
131 | 135 | ||
132 | static int usb_kbd_event(struct input_dev *dev, unsigned int type, | 136 | static int usb_kbd_event(struct input_dev *dev, unsigned int type, |
@@ -150,7 +154,7 @@ static int usb_kbd_event(struct input_dev *dev, unsigned int type, | |||
150 | *(kbd->leds) = kbd->newleds; | 154 | *(kbd->leds) = kbd->newleds; |
151 | kbd->led->dev = kbd->usbdev; | 155 | kbd->led->dev = kbd->usbdev; |
152 | if (usb_submit_urb(kbd->led, GFP_ATOMIC)) | 156 | if (usb_submit_urb(kbd->led, GFP_ATOMIC)) |
153 | err_hid("usb_submit_urb(leds) failed"); | 157 | pr_err("usb_submit_urb(leds) failed\n"); |
154 | 158 | ||
155 | return 0; | 159 | return 0; |
156 | } | 160 | } |
@@ -160,7 +164,7 @@ static void usb_kbd_led(struct urb *urb) | |||
160 | struct usb_kbd *kbd = urb->context; | 164 | struct usb_kbd *kbd = urb->context; |
161 | 165 | ||
162 | if (urb->status) | 166 | if (urb->status) |
163 | dev_warn(&urb->dev->dev, "led urb status %d received\n", | 167 | hid_warn(urb->dev, "led urb status %d received\n", |
164 | urb->status); | 168 | urb->status); |
165 | 169 | ||
166 | if (*(kbd->leds) == kbd->newleds) | 170 | if (*(kbd->leds) == kbd->newleds) |
@@ -169,7 +173,7 @@ static void usb_kbd_led(struct urb *urb) | |||
169 | *(kbd->leds) = kbd->newleds; | 173 | *(kbd->leds) = kbd->newleds; |
170 | kbd->led->dev = kbd->usbdev; | 174 | kbd->led->dev = kbd->usbdev; |
171 | if (usb_submit_urb(kbd->led, GFP_ATOMIC)) | 175 | if (usb_submit_urb(kbd->led, GFP_ATOMIC)) |
172 | err_hid("usb_submit_urb(leds) failed"); | 176 | hid_err(urb->dev, "usb_submit_urb(leds) failed\n"); |
173 | } | 177 | } |
174 | 178 | ||
175 | static int usb_kbd_open(struct input_dev *dev) | 179 | static int usb_kbd_open(struct input_dev *dev) |