aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hid')
-rw-r--r--drivers/hid/Kconfig43
-rw-r--r--drivers/hid/Makefile6
-rw-r--r--drivers/hid/hid-core.c6
-rw-r--r--drivers/hid/hid-dr.c (renamed from drivers/hid/hid-drff.c)117
-rw-r--r--drivers/hid/hid-egalax.c279
-rw-r--r--drivers/hid/hid-gyration.c5
-rw-r--r--drivers/hid/hid-ids.h7
-rw-r--r--drivers/hid/hid-input.c1
-rw-r--r--drivers/hid/hid-lg.c2
-rw-r--r--drivers/hid/hid-magicmouse.c4
-rw-r--r--drivers/hid/hid-multitouch.c74
-rw-r--r--drivers/hid/hid-ntrig.c519
-rw-r--r--drivers/hid/hid-ortek.c6
-rw-r--r--drivers/hid/hid-roccat-arvo.c450
-rw-r--r--drivers/hid/hid-roccat-arvo.h98
-rw-r--r--drivers/hid/hid-roccat-common.c62
-rw-r--r--drivers/hid/hid-roccat-common.h23
-rw-r--r--drivers/hid/hid-roccat-kone.c156
-rw-r--r--drivers/hid/hid-roccat-koneplus.c167
-rw-r--r--drivers/hid/hid-roccat-kovaplus.c715
-rw-r--r--drivers/hid/hid-roccat-kovaplus.h157
-rw-r--r--drivers/hid/hid-roccat-pyra.c174
-rw-r--r--drivers/hid/hid-roccat.c53
-rw-r--r--drivers/hid/hid-roccat.h32
-rw-r--r--drivers/hid/hidraw.c110
-rw-r--r--drivers/hid/usbhid/hid-core.c35
26 files changed, 2363 insertions, 938 deletions
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index d942d421af51..d8123920f79c 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -146,7 +146,12 @@ config HID_DRAGONRISE
146 tristate "DragonRise Inc. game controller" 146 tristate "DragonRise Inc. game controller"
147 depends on USB_HID 147 depends on USB_HID
148 ---help--- 148 ---help---
149 Say Y here if you have DragonRise Inc.game controllers. 149 Say Y here if you have DragonRise Inc. game controllers.
150 These might be branded as:
151 - Tesun USB-703
152 - Media-tech MT1504 "Rogue"
153 - DVTech JS19 "Gear"
154 - Defender Game Master
150 155
151config DRAGONRISE_FF 156config DRAGONRISE_FF
152 bool "DragonRise Inc. force feedback" 157 bool "DragonRise Inc. force feedback"
@@ -166,13 +171,6 @@ config HID_EMS_FF
166 Currently the following devices are known to be supported: 171 Currently the following devices are known to be supported:
167 - Trio Linker Plus II 172 - Trio Linker Plus II
168 173
169config HID_EGALAX
170 tristate "eGalax multi-touch panel"
171 depends on USB_HID
172 ---help---
173 Support for the eGalax dual-touch panels, including the
174 Joojoo and Wetab tablets.
175
176config HID_ELECOM 174config HID_ELECOM
177 tristate "ELECOM BM084 bluetooth mouse" 175 tristate "ELECOM BM084 bluetooth mouse"
178 depends on BT_HIDP 176 depends on BT_HIDP
@@ -324,8 +322,11 @@ config HID_MULTITOUCH
324 Say Y here if you have one of the following devices: 322 Say Y here if you have one of the following devices:
325 - Cypress TrueTouch panels 323 - Cypress TrueTouch panels
326 - Hanvon dual touch panels 324 - Hanvon dual touch panels
325 - IrTouch Infrared USB panels
327 - Pixcir dual touch panels 326 - Pixcir dual touch panels
328 - 'Sensing Win7-TwoFinger' panel by GeneralTouch 327 - 'Sensing Win7-TwoFinger' panel by GeneralTouch
328 - eGalax dual-touch panels, including the
329 Joojoo and Wetab tablets
329 330
330 If unsure, say N. 331 If unsure, say N.
331 332
@@ -339,10 +340,10 @@ config HID_NTRIG
339 Support for N-Trig touch screen. 340 Support for N-Trig touch screen.
340 341
341config HID_ORTEK 342config HID_ORTEK
342 tristate "Ortek WKB-2000 wireless keyboard and mouse trackpad" 343 tristate "Ortek PKB-1700/WKB-2000 wireless keyboard and mouse trackpad"
343 depends on USB_HID 344 depends on USB_HID
344 ---help--- 345 ---help---
345 Support for Ortek WKB-2000 wireless keyboard + mouse trackpad. 346 Support for Ortek PKB-1700/WKB-2000 wireless keyboard + mouse trackpad.
346 347
347config HID_PANTHERLORD 348config HID_PANTHERLORD
348 tristate "Pantherlord/GreenAsia game controller" 349 tristate "Pantherlord/GreenAsia game controller"
@@ -437,10 +438,22 @@ config HID_ROCCAT
437 Say Y here if you have a Roccat mouse or keyboard and want OSD or 438 Say Y here if you have a Roccat mouse or keyboard and want OSD or
438 macro execution support. 439 macro execution support.
439 440
441config HID_ROCCAT_COMMON
442 tristate
443
444config HID_ROCCAT_ARVO
445 tristate "Roccat Arvo keyboard support"
446 depends on USB_HID
447 select HID_ROCCAT
448 select HID_ROCCAT_COMMON
449 ---help---
450 Support for Roccat Arvo keyboard.
451
440config HID_ROCCAT_KONE 452config HID_ROCCAT_KONE
441 tristate "Roccat Kone Mouse support" 453 tristate "Roccat Kone Mouse support"
442 depends on USB_HID 454 depends on USB_HID
443 select HID_ROCCAT 455 select HID_ROCCAT
456 select HID_ROCCAT_COMMON
444 ---help--- 457 ---help---
445 Support for Roccat Kone mouse. 458 Support for Roccat Kone mouse.
446 459
@@ -448,13 +461,23 @@ config HID_ROCCAT_KONEPLUS
448 tristate "Roccat Kone[+] mouse support" 461 tristate "Roccat Kone[+] mouse support"
449 depends on USB_HID 462 depends on USB_HID
450 select HID_ROCCAT 463 select HID_ROCCAT
464 select HID_ROCCAT_COMMON
451 ---help--- 465 ---help---
452 Support for Roccat Kone[+] mouse. 466 Support for Roccat Kone[+] mouse.
453 467
468config HID_ROCCAT_KOVAPLUS
469 tristate "Roccat Kova[+] mouse support"
470 depends on USB_HID
471 select HID_ROCCAT
472 select HID_ROCCAT_COMMON
473 ---help---
474 Support for Roccat Kova[+] mouse.
475
454config HID_ROCCAT_PYRA 476config HID_ROCCAT_PYRA
455 tristate "Roccat Pyra mouse support" 477 tristate "Roccat Pyra mouse support"
456 depends on USB_HID 478 depends on USB_HID
457 select HID_ROCCAT 479 select HID_ROCCAT
480 select HID_ROCCAT_COMMON
458 ---help--- 481 ---help---
459 Support for Roccat Pyra mouse. 482 Support for Roccat Pyra mouse.
460 483
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 125ba103eba0..06c68ae3abee 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -34,9 +34,8 @@ obj-$(CONFIG_HID_CANDO) += hid-cando.o
34obj-$(CONFIG_HID_CHERRY) += hid-cherry.o 34obj-$(CONFIG_HID_CHERRY) += hid-cherry.o
35obj-$(CONFIG_HID_CHICONY) += hid-chicony.o 35obj-$(CONFIG_HID_CHICONY) += hid-chicony.o
36obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o 36obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o
37obj-$(CONFIG_HID_DRAGONRISE) += hid-drff.o 37obj-$(CONFIG_HID_DRAGONRISE) += hid-dr.o
38obj-$(CONFIG_HID_EMS_FF) += hid-emsff.o 38obj-$(CONFIG_HID_EMS_FF) += hid-emsff.o
39obj-$(CONFIG_HID_EGALAX) += hid-egalax.o
40obj-$(CONFIG_HID_ELECOM) += hid-elecom.o 39obj-$(CONFIG_HID_ELECOM) += hid-elecom.o
41obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o 40obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o
42obj-$(CONFIG_HID_GYRATION) += hid-gyration.o 41obj-$(CONFIG_HID_GYRATION) += hid-gyration.o
@@ -58,8 +57,11 @@ obj-$(CONFIG_HID_PANTHERLORD) += hid-pl.o
58obj-$(CONFIG_HID_PETALYNX) += hid-petalynx.o 57obj-$(CONFIG_HID_PETALYNX) += hid-petalynx.o
59obj-$(CONFIG_HID_PICOLCD) += hid-picolcd.o 58obj-$(CONFIG_HID_PICOLCD) += hid-picolcd.o
60obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o 59obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o
60obj-$(CONFIG_HID_ROCCAT_COMMON) += hid-roccat-common.o
61obj-$(CONFIG_HID_ROCCAT_ARVO) += hid-roccat-arvo.o
61obj-$(CONFIG_HID_ROCCAT_KONE) += hid-roccat-kone.o 62obj-$(CONFIG_HID_ROCCAT_KONE) += hid-roccat-kone.o
62obj-$(CONFIG_HID_ROCCAT_KONEPLUS) += hid-roccat-koneplus.o 63obj-$(CONFIG_HID_ROCCAT_KONEPLUS) += hid-roccat-koneplus.o
64obj-$(CONFIG_HID_ROCCAT_KOVAPLUS) += hid-roccat-kovaplus.o
63obj-$(CONFIG_HID_ROCCAT_PYRA) += hid-roccat-pyra.o 65obj-$(CONFIG_HID_ROCCAT_PYRA) += hid-roccat-pyra.o
64obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o 66obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o
65obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o 67obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index c650efb52a45..c3d66269ed7d 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1359,6 +1359,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
1359 { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE) }, 1359 { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE) },
1360 { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_TRUETOUCH) }, 1360 { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_TRUETOUCH) },
1361 { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) }, 1361 { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) },
1362 { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0011) },
1362 { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH) }, 1363 { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH) },
1363 { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1) }, 1364 { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1) },
1364 { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH2) }, 1365 { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH2) },
@@ -1376,6 +1377,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
1376 { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) }, 1377 { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) },
1377 { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) }, 1378 { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) },
1378 { HID_USB_DEVICE(USB_VENDOR_ID_HANVON, USB_DEVICE_ID_HANVON_MULTITOUCH) }, 1379 { HID_USB_DEVICE(USB_VENDOR_ID_HANVON, USB_DEVICE_ID_HANVON_MULTITOUCH) },
1380 { HID_USB_DEVICE(USB_VENDOR_ID_IRTOUCHSYSTEMS, USB_DEVICE_ID_IRTOUCH_INFRARED_USB) },
1379 { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) }, 1381 { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) },
1380 { HID_USB_DEVICE(USB_VENDOR_ID_KEYTOUCH, USB_DEVICE_ID_KEYTOUCH_IEC) }, 1382 { HID_USB_DEVICE(USB_VENDOR_ID_KEYTOUCH, USB_DEVICE_ID_KEYTOUCH_IEC) },
1381 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) }, 1383 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) },
@@ -1401,6 +1403,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
1401 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FLIGHT_SYSTEM_G940) }, 1403 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FLIGHT_SYSTEM_G940) },
1402 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL) }, 1404 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL) },
1403 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2) }, 1405 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2) },
1406 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFP_WHEEL) },
1404 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL) }, 1407 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL) },
1405 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WII_WHEEL) }, 1408 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WII_WHEEL) },
1406 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2) }, 1409 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2) },
@@ -1433,12 +1436,15 @@ static const struct hid_device_id hid_have_special_driver[] = {
1433 { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_16) }, 1436 { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_16) },
1434 { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_17) }, 1437 { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_17) },
1435 { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_18) }, 1438 { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_18) },
1439 { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_PKB1700) },
1436 { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) }, 1440 { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) },
1437 { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) }, 1441 { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) },
1438 { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) }, 1442 { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) },
1439 { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN) }, 1443 { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN) },
1440 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONE) }, 1444 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONE) },
1445 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ARVO) },
1441 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) }, 1446 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) },
1447 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KOVAPLUS) },
1442 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRED) }, 1448 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRED) },
1443 { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, 1449 { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) },
1444 { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) }, 1450 { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) },
diff --git a/drivers/hid/hid-drff.c b/drivers/hid/hid-dr.c
index afcf3d67eb02..61eece47204d 100644
--- a/drivers/hid/hid-drff.c
+++ b/drivers/hid/hid-dr.c
@@ -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 */
209static __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
238static __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
148static int dr_probe(struct hid_device *hdev, const struct hid_device_id *id) 252static int dr_probe(struct hid_device *hdev, const struct hid_device_id *id)
149{ 253{
150 int ret; 254 int ret;
@@ -163,7 +267,16 @@ static int dr_probe(struct hid_device *hdev, const struct hid_device_id *id)
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;
169err: 282err:
@@ -172,6 +285,7 @@ err:
172 285
173static const struct hid_device_id dr_devices[] = { 286static 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};
177MODULE_DEVICE_TABLE(hid, dr_devices); 291MODULE_DEVICE_TABLE(hid, dr_devices);
@@ -179,6 +293,7 @@ MODULE_DEVICE_TABLE(hid, dr_devices);
179static struct hid_driver dr_driver = { 293static 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 03bee1970d70..000000000000
--- a/drivers/hid/hid-egalax.c
+++ /dev/null
@@ -1,279 +0,0 @@
1/*
2 * HID driver for eGalax dual-touch panels
3 *
4 * Copyright (c) 2010 Stephane Chatty <chatty@enac.fr>
5 * Copyright (c) 2010 Henrik Rydberg <rydberg@euromail.se>
6 * Copyright (c) 2010 Canonical, Ltd.
7 *
8 */
9
10/*
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the Free
13 * Software Foundation; either version 2 of the License, or (at your option)
14 * any later version.
15 */
16
17#include <linux/device.h>
18#include <linux/hid.h>
19#include <linux/module.h>
20#include <linux/usb.h>
21#include <linux/input/mt.h>
22#include <linux/slab.h>
23#include "usbhid/usbhid.h"
24
25MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
26MODULE_DESCRIPTION("eGalax dual-touch panel");
27MODULE_LICENSE("GPL");
28
29#include "hid-ids.h"
30
31#define MAX_SLOTS 2
32
33/* estimated signal-to-noise ratios */
34#define SN_MOVE 4096
35#define SN_PRESSURE 32
36
37struct egalax_data {
38 int valid;
39 int slot;
40 int touch;
41 int x, y, z;
42};
43
44static void set_abs(struct input_dev *input, unsigned int code,
45 struct hid_field *field, int snratio)
46{
47 int fmin = field->logical_minimum;
48 int fmax = field->logical_maximum;
49 int fuzz = snratio ? (fmax - fmin) / snratio : 0;
50 input_set_abs_params(input, code, fmin, fmax, fuzz, 0);
51}
52
53static int egalax_input_mapping(struct hid_device *hdev, struct hid_input *hi,
54 struct hid_field *field, struct hid_usage *usage,
55 unsigned long **bit, int *max)
56{
57 struct input_dev *input = hi->input;
58
59 switch (usage->hid & HID_USAGE_PAGE) {
60
61 case HID_UP_GENDESK:
62 switch (usage->hid) {
63 case HID_GD_X:
64 field->logical_maximum = 32760;
65 hid_map_usage(hi, usage, bit, max,
66 EV_ABS, ABS_MT_POSITION_X);
67 set_abs(input, ABS_MT_POSITION_X, field, SN_MOVE);
68 /* touchscreen emulation */
69 set_abs(input, ABS_X, field, SN_MOVE);
70 return 1;
71 case HID_GD_Y:
72 field->logical_maximum = 32760;
73 hid_map_usage(hi, usage, bit, max,
74 EV_ABS, ABS_MT_POSITION_Y);
75 set_abs(input, ABS_MT_POSITION_Y, field, SN_MOVE);
76 /* touchscreen emulation */
77 set_abs(input, ABS_Y, field, SN_MOVE);
78 return 1;
79 }
80 return 0;
81
82 case HID_UP_DIGITIZER:
83 switch (usage->hid) {
84 case HID_DG_TIPSWITCH:
85 /* touchscreen emulation */
86 hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
87 input_set_capability(input, EV_KEY, BTN_TOUCH);
88 return 1;
89 case HID_DG_INRANGE:
90 case HID_DG_CONFIDENCE:
91 case HID_DG_CONTACTCOUNT:
92 case HID_DG_CONTACTMAX:
93 return -1;
94 case HID_DG_CONTACTID:
95 input_mt_init_slots(input, MAX_SLOTS);
96 return 1;
97 case HID_DG_TIPPRESSURE:
98 field->logical_minimum = 0;
99 hid_map_usage(hi, usage, bit, max,
100 EV_ABS, ABS_MT_PRESSURE);
101 set_abs(input, ABS_MT_PRESSURE, field, SN_PRESSURE);
102 /* touchscreen emulation */
103 set_abs(input, ABS_PRESSURE, field, SN_PRESSURE);
104 return 1;
105 }
106 return 0;
107 }
108
109 /* ignore others (from other reports we won't get anyway) */
110 return -1;
111}
112
113static int egalax_input_mapped(struct hid_device *hdev, struct hid_input *hi,
114 struct hid_field *field, struct hid_usage *usage,
115 unsigned long **bit, int *max)
116{
117 /* tell hid-input to skip setup of these event types */
118 if (usage->type == EV_KEY || usage->type == EV_ABS)
119 set_bit(usage->type, hi->input->evbit);
120 return -1;
121}
122
123/*
124 * this function is called when a whole finger has been parsed,
125 * so that it can decide what to send to the input layer.
126 */
127static void egalax_filter_event(struct egalax_data *td, struct input_dev *input)
128{
129 input_mt_slot(input, td->slot);
130 input_mt_report_slot_state(input, MT_TOOL_FINGER, td->touch);
131 if (td->touch) {
132 input_event(input, EV_ABS, ABS_MT_POSITION_X, td->x);
133 input_event(input, EV_ABS, ABS_MT_POSITION_Y, td->y);
134 input_event(input, EV_ABS, ABS_MT_PRESSURE, td->z);
135 }
136 input_mt_report_pointer_emulation(input, true);
137}
138
139static int egalax_event(struct hid_device *hid, struct hid_field *field,
140 struct hid_usage *usage, __s32 value)
141{
142 struct egalax_data *td = hid_get_drvdata(hid);
143
144 /* Note, eGalax has two product lines: the first is resistive and
145 * uses a standard parallel multitouch protocol (product ID ==
146 * 48xx). The second is capacitive and uses an unusual "serial"
147 * protocol with a different message for each multitouch finger
148 * (product ID == 72xx).
149 */
150 if (hid->claimed & HID_CLAIMED_INPUT) {
151 struct input_dev *input = field->hidinput->input;
152
153 switch (usage->hid) {
154 case HID_DG_INRANGE:
155 td->valid = value;
156 break;
157 case HID_DG_CONFIDENCE:
158 /* avoid interference from generic hidinput handling */
159 break;
160 case HID_DG_TIPSWITCH:
161 td->touch = value;
162 break;
163 case HID_DG_TIPPRESSURE:
164 td->z = value;
165 break;
166 case HID_DG_CONTACTID:
167 td->slot = clamp_val(value, 0, MAX_SLOTS - 1);
168 break;
169 case HID_GD_X:
170 td->x = value;
171 break;
172 case HID_GD_Y:
173 td->y = value;
174 /* this is the last field in a finger */
175 if (td->valid)
176 egalax_filter_event(td, input);
177 break;
178 case HID_DG_CONTACTCOUNT:
179 /* touch emulation: this is the last field in a frame */
180 break;
181
182 default:
183 /* fallback to the generic hidinput handling */
184 return 0;
185 }
186 }
187
188 /* we have handled the hidinput part, now remains hiddev */
189 if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
190 hid->hiddev_hid_event(hid, field, usage, value);
191
192 return 1;
193}
194
195static int egalax_probe(struct hid_device *hdev, const struct hid_device_id *id)
196{
197 int ret;
198 struct egalax_data *td;
199 struct hid_report *report;
200
201 td = kzalloc(sizeof(struct egalax_data), GFP_KERNEL);
202 if (!td) {
203 hid_err(hdev, "cannot allocate eGalax data\n");
204 return -ENOMEM;
205 }
206 hid_set_drvdata(hdev, td);
207
208 ret = hid_parse(hdev);
209 if (ret)
210 goto end;
211
212 ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
213 if (ret)
214 goto end;
215
216 report = hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[5];
217 if (report) {
218 report->field[0]->value[0] = 2;
219 usbhid_submit_report(hdev, report, USB_DIR_OUT);
220 }
221
222end:
223 if (ret)
224 kfree(td);
225
226 return ret;
227}
228
229static void egalax_remove(struct hid_device *hdev)
230{
231 hid_hw_stop(hdev);
232 kfree(hid_get_drvdata(hdev));
233 hid_set_drvdata(hdev, NULL);
234}
235
236static const struct hid_device_id egalax_devices[] = {
237 { HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
238 USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH) },
239 { HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
240 USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1) },
241 { HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
242 USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH2) },
243 { HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
244 USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH3) },
245 { HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
246 USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH4) },
247 { }
248};
249MODULE_DEVICE_TABLE(hid, egalax_devices);
250
251static const struct hid_usage_id egalax_grabbed_usages[] = {
252 { HID_ANY_ID, HID_ANY_ID, HID_ANY_ID },
253 { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
254};
255
256static struct hid_driver egalax_driver = {
257 .name = "egalax-touch",
258 .id_table = egalax_devices,
259 .probe = egalax_probe,
260 .remove = egalax_remove,
261 .input_mapping = egalax_input_mapping,
262 .input_mapped = egalax_input_mapped,
263 .usage_table = egalax_grabbed_usages,
264 .event = egalax_event,
265};
266
267static int __init egalax_init(void)
268{
269 return hid_register_driver(&egalax_driver);
270}
271
272static void __exit egalax_exit(void)
273{
274 hid_unregister_driver(&egalax_driver);
275}
276
277module_init(egalax_init);
278module_exit(egalax_exit);
279
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 8fc82a7b2a82..d485894ff4db 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -333,6 +333,9 @@
333#define USB_VENDOR_ID_IMATION 0x0718 333#define USB_VENDOR_ID_IMATION 0x0718
334#define USB_DEVICE_ID_DISC_STAKKA 0xd000 334#define USB_DEVICE_ID_DISC_STAKKA 0xd000
335 335
336#define USB_VENDOR_ID_IRTOUCHSYSTEMS 0x6615
337#define USB_DEVICE_ID_IRTOUCH_INFRARED_USB 0x0070
338
336#define USB_VENDOR_ID_JESS 0x0c45 339#define USB_VENDOR_ID_JESS 0x0c45
337#define USB_DEVICE_ID_JESS_YUREX 0x1010 340#define USB_DEVICE_ID_JESS_YUREX 0x1010
338 341
@@ -389,6 +392,7 @@
389#define USB_DEVICE_ID_LOGITECH_WHEEL 0xc294 392#define USB_DEVICE_ID_LOGITECH_WHEEL 0xc294
390#define USB_DEVICE_ID_LOGITECH_WINGMAN_FFG 0xc293 393#define USB_DEVICE_ID_LOGITECH_WINGMAN_FFG 0xc293
391#define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL 0xc295 394#define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL 0xc295
395#define USB_DEVICE_ID_LOGITECH_DFP_WHEEL 0xc298
392#define USB_DEVICE_ID_LOGITECH_G25_WHEEL 0xc299 396#define USB_DEVICE_ID_LOGITECH_G25_WHEEL 0xc299
393#define USB_DEVICE_ID_LOGITECH_WII_WHEEL 0xc29c 397#define USB_DEVICE_ID_LOGITECH_WII_WHEEL 0xc29c
394#define USB_DEVICE_ID_LOGITECH_ELITE_KBD 0xc30a 398#define USB_DEVICE_ID_LOGITECH_ELITE_KBD 0xc30a
@@ -472,6 +476,7 @@
472#define USB_DEVICE_ID_ONTRAK_ADU100 0x0064 476#define USB_DEVICE_ID_ONTRAK_ADU100 0x0064
473 477
474#define USB_VENDOR_ID_ORTEK 0x05a4 478#define USB_VENDOR_ID_ORTEK 0x05a4
479#define USB_DEVICE_ID_ORTEK_PKB1700 0x1700
475#define USB_DEVICE_ID_ORTEK_WKB2000 0x2000 480#define USB_DEVICE_ID_ORTEK_WKB2000 0x2000
476 481
477#define USB_VENDOR_ID_PANJIT 0x134c 482#define USB_VENDOR_ID_PANJIT 0x134c
@@ -502,8 +507,10 @@
502#define USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN 0x3001 507#define USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN 0x3001
503 508
504#define USB_VENDOR_ID_ROCCAT 0x1e7d 509#define USB_VENDOR_ID_ROCCAT 0x1e7d
510#define USB_DEVICE_ID_ROCCAT_ARVO 0x30d4
505#define USB_DEVICE_ID_ROCCAT_KONE 0x2ced 511#define USB_DEVICE_ID_ROCCAT_KONE 0x2ced
506#define USB_DEVICE_ID_ROCCAT_KONEPLUS 0x2d51 512#define USB_DEVICE_ID_ROCCAT_KONEPLUS 0x2d51
513#define USB_DEVICE_ID_ROCCAT_KOVAPLUS 0x2d50
507#define USB_DEVICE_ID_ROCCAT_PYRA_WIRED 0x2c24 514#define USB_DEVICE_ID_ROCCAT_PYRA_WIRED 0x2c24
508#define USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS 0x2cf6 515#define USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS 0x2cf6
509 516
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index ebcc02a1c1c9..cd74203c8178 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -940,6 +940,7 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
940 return 0; 940 return 0;
941 941
942out_cleanup: 942out_cleanup:
943 list_del(&hidinput->list);
943 input_free_device(hidinput->input); 944 input_free_device(hidinput->input);
944 kfree(hidinput); 945 kfree(hidinput);
945out_unwind: 946out_unwind:
diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c
index aef4104da141..3da90402ee81 100644
--- a/drivers/hid/hid-lg.c
+++ b/drivers/hid/hid-lg.c
@@ -377,6 +377,8 @@ static const struct hid_device_id lg_devices[] = {
377 .driver_data = LG_FF }, 377 .driver_data = LG_FF },
378 { 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),
379 .driver_data = LG_FF }, 379 .driver_data = LG_FF },
380 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFP_WHEEL),
381 .driver_data = LG_FF },
380 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WII_WHEEL), 382 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WII_WHEEL),
381 .driver_data = LG_FF4 }, 383 .driver_data = LG_FF4 },
382 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ), 384 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ),
diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c
index 698e6459fd0b..318cc40df92d 100644
--- a/drivers/hid/hid-magicmouse.c
+++ b/drivers/hid/hid-magicmouse.c
@@ -258,7 +258,7 @@ static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tda
258 input_report_abs(input, ABS_MT_TRACKING_ID, id); 258 input_report_abs(input, ABS_MT_TRACKING_ID, id);
259 input_report_abs(input, ABS_MT_TOUCH_MAJOR, touch_major << 2); 259 input_report_abs(input, ABS_MT_TOUCH_MAJOR, touch_major << 2);
260 input_report_abs(input, ABS_MT_TOUCH_MINOR, touch_minor << 2); 260 input_report_abs(input, ABS_MT_TOUCH_MINOR, touch_minor << 2);
261 input_report_abs(input, ABS_MT_ORIENTATION, orientation); 261 input_report_abs(input, ABS_MT_ORIENTATION, -orientation);
262 input_report_abs(input, ABS_MT_POSITION_X, x); 262 input_report_abs(input, ABS_MT_POSITION_X, x);
263 input_report_abs(input, ABS_MT_POSITION_Y, y); 263 input_report_abs(input, ABS_MT_POSITION_Y, y);
264 264
@@ -397,7 +397,7 @@ static void magicmouse_setup_input(struct input_dev *input, struct hid_device *h
397 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);
398 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);
399 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);
400 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);
401 401
402 /* Note: Touch Y position from the device is inverted relative 402 /* Note: Touch Y position from the device is inverted relative
403 * to how pointer motion is reported (and relative to how USB 403 * to how pointer motion is reported (and relative to how USB
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 2bbc9545f5cc..ee01e65e22d6 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -5,6 +5,12 @@
5 * Copyright (c) 2010-2011 Benjamin Tissoires <benjamin.tissoires@gmail.com> 5 * Copyright (c) 2010-2011 Benjamin Tissoires <benjamin.tissoires@gmail.com>
6 * Copyright (c) 2010-2011 Ecole Nationale de l'Aviation Civile, France 6 * Copyright (c) 2010-2011 Ecole Nationale de l'Aviation Civile, France
7 * 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 *
8 */ 14 */
9 15
10/* 16/*
@@ -24,6 +30,7 @@
24 30
25 31
26MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>"); 32MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
33MODULE_AUTHOR("Benjamin Tissoires <benjamin.tissoires@gmail.com>");
27MODULE_DESCRIPTION("HID multitouch panels"); 34MODULE_DESCRIPTION("HID multitouch panels");
28MODULE_LICENSE("GPL"); 35MODULE_LICENSE("GPL");
29 36
@@ -36,6 +43,7 @@ MODULE_LICENSE("GPL");
36#define MT_QUIRK_SLOT_IS_CONTACTNUMBER (1 << 3) 43#define MT_QUIRK_SLOT_IS_CONTACTNUMBER (1 << 3)
37#define MT_QUIRK_VALID_IS_INRANGE (1 << 4) 44#define MT_QUIRK_VALID_IS_INRANGE (1 << 4)
38#define MT_QUIRK_VALID_IS_CONFIDENCE (1 << 5) 45#define MT_QUIRK_VALID_IS_CONFIDENCE (1 << 5)
46#define MT_QUIRK_EGALAX_XYZ_FIXUP (1 << 6)
39 47
40struct mt_slot { 48struct mt_slot {
41 __s32 x, y, p, w, h; 49 __s32 x, y, p, w, h;
@@ -65,10 +73,11 @@ struct mt_class {
65}; 73};
66 74
67/* classes of device behavior */ 75/* classes of device behavior */
68#define MT_CLS_DEFAULT 1 76#define MT_CLS_DEFAULT 1
69#define MT_CLS_DUAL1 2 77#define MT_CLS_DUAL_INRANGE_CONTACTID 2
70#define MT_CLS_DUAL2 3 78#define MT_CLS_DUAL_INRANGE_CONTACTNUMBER 3
71#define MT_CLS_CYPRESS 4 79#define MT_CLS_CYPRESS 4
80#define MT_CLS_EGALAX 5
72 81
73/* 82/*
74 * these device-dependent functions determine what slot corresponds 83 * these device-dependent functions determine what slot corresponds
@@ -104,13 +113,13 @@ static int find_slot_from_contactid(struct mt_device *td)
104 113
105struct mt_class mt_classes[] = { 114struct mt_class mt_classes[] = {
106 { .name = MT_CLS_DEFAULT, 115 { .name = MT_CLS_DEFAULT,
107 .quirks = MT_QUIRK_VALID_IS_INRANGE, 116 .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP,
108 .maxcontacts = 10 }, 117 .maxcontacts = 10 },
109 { .name = MT_CLS_DUAL1, 118 { .name = MT_CLS_DUAL_INRANGE_CONTACTID,
110 .quirks = MT_QUIRK_VALID_IS_INRANGE | 119 .quirks = MT_QUIRK_VALID_IS_INRANGE |
111 MT_QUIRK_SLOT_IS_CONTACTID, 120 MT_QUIRK_SLOT_IS_CONTACTID,
112 .maxcontacts = 2 }, 121 .maxcontacts = 2 },
113 { .name = MT_CLS_DUAL2, 122 { .name = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
114 .quirks = MT_QUIRK_VALID_IS_INRANGE | 123 .quirks = MT_QUIRK_VALID_IS_INRANGE |
115 MT_QUIRK_SLOT_IS_CONTACTNUMBER, 124 MT_QUIRK_SLOT_IS_CONTACTNUMBER,
116 .maxcontacts = 2 }, 125 .maxcontacts = 2 },
@@ -119,6 +128,14 @@ struct mt_class mt_classes[] = {
119 MT_QUIRK_CYPRESS, 128 MT_QUIRK_CYPRESS,
120 .maxcontacts = 10 }, 129 .maxcontacts = 10 },
121 130
131 { .name = MT_CLS_EGALAX,
132 .quirks = MT_QUIRK_SLOT_IS_CONTACTID |
133 MT_QUIRK_VALID_IS_INRANGE |
134 MT_QUIRK_EGALAX_XYZ_FIXUP,
135 .maxcontacts = 2,
136 .sn_move = 4096,
137 .sn_pressure = 32,
138 },
122 { } 139 { }
123}; 140};
124 141
@@ -146,11 +163,15 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
146{ 163{
147 struct mt_device *td = hid_get_drvdata(hdev); 164 struct mt_device *td = hid_get_drvdata(hdev);
148 struct mt_class *cls = td->mtclass; 165 struct mt_class *cls = td->mtclass;
166 __s32 quirks = cls->quirks;
167
149 switch (usage->hid & HID_USAGE_PAGE) { 168 switch (usage->hid & HID_USAGE_PAGE) {
150 169
151 case HID_UP_GENDESK: 170 case HID_UP_GENDESK:
152 switch (usage->hid) { 171 switch (usage->hid) {
153 case HID_GD_X: 172 case HID_GD_X:
173 if (quirks & MT_QUIRK_EGALAX_XYZ_FIXUP)
174 field->logical_maximum = 32760;
154 hid_map_usage(hi, usage, bit, max, 175 hid_map_usage(hi, usage, bit, max,
155 EV_ABS, ABS_MT_POSITION_X); 176 EV_ABS, ABS_MT_POSITION_X);
156 set_abs(hi->input, ABS_MT_POSITION_X, field, 177 set_abs(hi->input, ABS_MT_POSITION_X, field,
@@ -160,6 +181,8 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
160 td->last_slot_field = usage->hid; 181 td->last_slot_field = usage->hid;
161 return 1; 182 return 1;
162 case HID_GD_Y: 183 case HID_GD_Y:
184 if (quirks & MT_QUIRK_EGALAX_XYZ_FIXUP)
185 field->logical_maximum = 32760;
163 hid_map_usage(hi, usage, bit, max, 186 hid_map_usage(hi, usage, bit, max,
164 EV_ABS, ABS_MT_POSITION_Y); 187 EV_ABS, ABS_MT_POSITION_Y);
165 set_abs(hi->input, ABS_MT_POSITION_Y, field, 188 set_abs(hi->input, ABS_MT_POSITION_Y, field,
@@ -203,6 +226,8 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
203 td->last_slot_field = usage->hid; 226 td->last_slot_field = usage->hid;
204 return 1; 227 return 1;
205 case HID_DG_TIPPRESSURE: 228 case HID_DG_TIPPRESSURE:
229 if (quirks & MT_QUIRK_EGALAX_XYZ_FIXUP)
230 field->logical_minimum = 0;
206 hid_map_usage(hi, usage, bit, max, 231 hid_map_usage(hi, usage, bit, max,
207 EV_ABS, ABS_MT_PRESSURE); 232 EV_ABS, ABS_MT_PRESSURE);
208 set_abs(hi->input, ABS_MT_PRESSURE, field, 233 set_abs(hi->input, ABS_MT_PRESSURE, field,
@@ -363,8 +388,11 @@ static int mt_event(struct hid_device *hid, struct hid_field *field,
363 return 0; 388 return 0;
364 } 389 }
365 390
366 if (usage->hid == td->last_slot_field) 391 if (usage->hid == td->last_slot_field) {
367 mt_complete_slot(td); 392 mt_complete_slot(td);
393 if (!td->last_field_index)
394 mt_emit_event(td, field->hidinput->input);
395 }
368 396
369 if (field->index == td->last_field_index 397 if (field->index == td->last_field_index
370 && td->num_received >= td->num_expected) 398 && td->num_received >= td->num_expected)
@@ -466,18 +494,42 @@ static const struct hid_device_id mt_devices[] = {
466 USB_DEVICE_ID_CYPRESS_TRUETOUCH) }, 494 USB_DEVICE_ID_CYPRESS_TRUETOUCH) },
467 495
468 /* GeneralTouch panel */ 496 /* GeneralTouch panel */
469 { .driver_data = MT_CLS_DUAL2, 497 { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
470 HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 498 HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
471 USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS) }, 499 USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS) },
472 500
501 /* IRTOUCH panels */
502 { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID,
503 HID_USB_DEVICE(USB_VENDOR_ID_IRTOUCHSYSTEMS,
504 USB_DEVICE_ID_IRTOUCH_INFRARED_USB) },
505
473 /* PixCir-based panels */ 506 /* PixCir-based panels */
474 { .driver_data = MT_CLS_DUAL1, 507 { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID,
475 HID_USB_DEVICE(USB_VENDOR_ID_HANVON, 508 HID_USB_DEVICE(USB_VENDOR_ID_HANVON,
476 USB_DEVICE_ID_HANVON_MULTITOUCH) }, 509 USB_DEVICE_ID_HANVON_MULTITOUCH) },
477 { .driver_data = MT_CLS_DUAL1, 510 { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID,
478 HID_USB_DEVICE(USB_VENDOR_ID_CANDO, 511 HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
479 USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) }, 512 USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) },
480 513
514 /* Resistive eGalax devices */
515 { .driver_data = MT_CLS_EGALAX,
516 HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
517 USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH) },
518 { .driver_data = MT_CLS_EGALAX,
519 HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
520 USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH3) },
521
522 /* Capacitive eGalax devices */
523 { .driver_data = MT_CLS_EGALAX,
524 HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
525 USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1) },
526 { .driver_data = MT_CLS_EGALAX,
527 HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
528 USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH2) },
529 { .driver_data = MT_CLS_EGALAX,
530 HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
531 USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH4) },
532
481 { } 533 { }
482}; 534};
483MODULE_DEVICE_TABLE(hid, mt_devices); 535MODULE_DEVICE_TABLE(hid, mt_devices);
diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c
index beb403421e72..9fae2ebdd758 100644
--- a/drivers/hid/hid-ntrig.c
+++ b/drivers/hid/hid-ntrig.c
@@ -110,6 +110,36 @@ static int ntrig_version_string(unsigned char *raw, char *buf)
110 return sprintf(buf, "%u.%u.%u.%u.%u", a, b, c, d, e); 110 return sprintf(buf, "%u.%u.%u.%u.%u", a, b, c, d, e);
111} 111}
112 112
113static 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
126static 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
113static void ntrig_report_version(struct hid_device *hdev) 143static void ntrig_report_version(struct hid_device *hdev)
114{ 144{
115 int ret; 145 int ret;
@@ -539,277 +569,288 @@ static int ntrig_input_mapped(struct hid_device *hdev, struct hid_input *hi,
539static int ntrig_event (struct hid_device *hid, struct hid_field *field, 569static int ntrig_event (struct hid_device *hid, struct hid_field *field,
540 struct hid_usage *usage, __s32 value) 570 struct hid_usage *usage, __s32 value)
541{ 571{
542 struct input_dev *input = field->hidinput->input;
543 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;
544 585
545 /* No special handling needed for the pen */ 586 /* No special handling needed for the pen */
546 if (field->application == HID_DG_PEN) 587 if (field->application == HID_DG_PEN)
547 return 0; 588 return 0;
548 589
549 if (hid->claimed & HID_CLAIMED_INPUT) { 590 switch (usage->hid) {
550 switch (usage->hid) { 591 case 0xff000001:
551 case 0xff000001: 592 /* Tag indicating the start of a multitouch group */
552 /* Tag indicating the start of a multitouch group */ 593 nd->reading_mt = 1;
553 nd->reading_mt = 1; 594 nd->first_contact_touch = 0;
554 nd->first_contact_touch = 0; 595 break;
555 break; 596 case HID_DG_TIPSWITCH:
556 case HID_DG_TIPSWITCH: 597 nd->tipswitch = value;
557 nd->tipswitch = value; 598 /* Prevent emission of touch until validated */
558 /* Prevent emission of touch until validated */ 599 return 1;
559 return 1; 600 case HID_DG_CONFIDENCE:
560 case HID_DG_CONFIDENCE: 601 nd->confidence = value;
561 nd->confidence = value; 602 break;
562 break; 603 case HID_GD_X:
563 case HID_GD_X: 604 nd->x = value;
564 nd->x = value; 605 /* Clear the contact footer */
565 /* Clear the contact footer */ 606 nd->mt_foot_count = 0;
566 nd->mt_foot_count = 0; 607 break;
567 break; 608 case HID_GD_Y:
568 case HID_GD_Y: 609 nd->y = value;
569 nd->y = value; 610 break;
570 break; 611 case HID_DG_CONTACTID:
571 case HID_DG_CONTACTID: 612 nd->id = value;
572 nd->id = value; 613 break;
573 break; 614 case HID_DG_WIDTH:
574 case HID_DG_WIDTH: 615 nd->w = value;
575 nd->w = value; 616 break;
576 break; 617 case HID_DG_HEIGHT:
577 case HID_DG_HEIGHT: 618 nd->h = value;
578 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) {
579 /* 625 /*
580 * when in single touch mode, this is the last 626 * TipSwitch indicates the presence of a
581 * report received in a finger event. We want 627 * finger in single touch mode.
582 * to emit a normal (X, Y) position
583 */ 628 */
584 if (!nd->reading_mt) { 629 input_report_key(input, BTN_TOUCH,
585 /* 630 nd->tipswitch);
586 * TipSwitch indicates the presence of a 631 input_report_key(input, BTN_TOOL_DOUBLETAP,
587 * finger in single touch mode. 632 nd->tipswitch);
588 */ 633 input_event(input, EV_ABS, ABS_X, nd->x);
589 input_report_key(input, BTN_TOUCH, 634 input_event(input, EV_ABS, ABS_Y, nd->y);
590 nd->tipswitch); 635 }
591 input_report_key(input, BTN_TOOL_DOUBLETAP, 636 break;
592 nd->tipswitch); 637 case 0xff000002:
593 input_event(input, EV_ABS, ABS_X, nd->x); 638 /*
594 input_event(input, EV_ABS, ABS_Y, nd->y); 639 * we receive this when the device is in multitouch
595 } 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)
596 break; 647 break;
597 case 0xff000002:
598 /*
599 * we receive this when the device is in multitouch
600 * mode. The first of the three values tagged with
601 * this usage tells if the contact point is real
602 * or a placeholder
603 */
604 648
605 /* Shouldn't get more than 4 footer packets, so skip */ 649 nd->mt_footer[nd->mt_foot_count++] = value;
606 if (nd->mt_foot_count >= 4)
607 break;
608 650
609 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;
610 654
611 /* if the footer isn't complete break */ 655 /* Pen activity signal. */
612 if (nd->mt_foot_count != 4) 656 if (nd->mt_footer[2]) {
613 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 }
614 668
615 /* Pen activity signal. */ 669 /*
616 if (nd->mt_footer[2]) { 670 * The first footer value indicates the presence of a
617 /* 671 * finger.
618 * When the pen deactivates touch, we see a 672 */
619 * bogus frame with ContactCount > 0. 673 if (nd->mt_footer[0]) {
620 * We can 674 /*
621 * save a bit of work by ensuring act_state < 0 675 * We do not want to process contacts under
622 * even if deactivation slack is turned off. 676 * the size threshold, but do not want to
623 */ 677 * ignore them for activation state
624 nd->act_state = deactivate_slack - 1; 678 */
679 if (nd->w < nd->min_width ||
680 nd->h < nd->min_height)
625 nd->confidence = 0; 681 nd->confidence = 0;
626 break; 682 } else
627 } 683 break;
628 684
685 if (nd->act_state > 0) {
629 /* 686 /*
630 * The first footer value indicates the presence of a 687 * Contact meets the activation size threshold
631 * finger.
632 */ 688 */
633 if (nd->mt_footer[0]) { 689 if (nd->w >= nd->activation_width &&
634 /* 690 nd->h >= nd->activation_height) {
635 * We do not want to process contacts under 691 if (nd->id)
636 * the size threshold, but do not want to
637 * ignore them for activation state
638 */
639 if (nd->w < nd->min_width ||
640 nd->h < nd->min_height)
641 nd->confidence = 0;
642 } else
643 break;
644
645 if (nd->act_state > 0) {
646 /*
647 * Contact meets the activation size threshold
648 */
649 if (nd->w >= nd->activation_width &&
650 nd->h >= nd->activation_height) {
651 if (nd->id)
652 /*
653 * first contact, activate now
654 */
655 nd->act_state = 0;
656 else {
657 /*
658 * avoid corrupting this frame
659 * but ensure next frame will
660 * be active
661 */
662 nd->act_state = 1;
663 break;
664 }
665 } else
666 /* 692 /*
667 * Defer adjusting the activation state 693 * first contact, activate now
668 * until the end of the frame.
669 */ 694 */
695 nd->act_state = 0;
696 else {
697 /*
698 * avoid corrupting this frame
699 * but ensure next frame will
700 * be active
701 */
702 nd->act_state = 1;
670 break; 703 break;
671 } 704 }
672 705 } else
673 /* Discarding this contact */
674 if (!nd->confidence)
675 break;
676
677 /* emit a normal (X, Y) for the first point only */
678 if (nd->id == 0) {
679 /* 706 /*
680 * TipSwitch is superfluous in multitouch 707 * Defer adjusting the activation state
681 * mode. The footer events tell us 708 * until the end of the frame.
682 * if there is a finger on the screen or
683 * not.
684 */ 709 */
685 nd->first_contact_touch = nd->confidence; 710 break;
686 input_event(input, EV_ABS, ABS_X, nd->x); 711 }
687 input_event(input, EV_ABS, ABS_Y, nd->y);
688 }
689 712
690 /* Emit MT events */ 713 /* Discarding this contact */
691 input_event(input, EV_ABS, ABS_MT_POSITION_X, nd->x); 714 if (!nd->confidence)
692 input_event(input, EV_ABS, ABS_MT_POSITION_Y, nd->y); 715 break;
693 716
717 /* emit a normal (X, Y) for the first point only */
718 if (nd->id == 0) {
694 /* 719 /*
695 * Translate from height and width to size 720 * TipSwitch is superfluous in multitouch
696 * and orientation. 721 * mode. The footer events tell us
722 * if there is a finger on the screen or
723 * not.
697 */ 724 */
698 if (nd->w > nd->h) { 725 nd->first_contact_touch = nd->confidence;
699 input_event(input, EV_ABS, 726 input_event(input, EV_ABS, ABS_X, nd->x);
700 ABS_MT_ORIENTATION, 1); 727 input_event(input, EV_ABS, ABS_Y, nd->y);
701 input_event(input, EV_ABS, 728 }
702 ABS_MT_TOUCH_MAJOR, nd->w);
703 input_event(input, EV_ABS,
704 ABS_MT_TOUCH_MINOR, nd->h);
705 } else {
706 input_event(input, EV_ABS,
707 ABS_MT_ORIENTATION, 0);
708 input_event(input, EV_ABS,
709 ABS_MT_TOUCH_MAJOR, nd->h);
710 input_event(input, EV_ABS,
711 ABS_MT_TOUCH_MINOR, nd->w);
712 }
713 input_mt_sync(field->hidinput->input);
714 break;
715 729
716 case HID_DG_CONTACTCOUNT: /* End of a multitouch group */ 730 /* Emit MT events */
717 if (!nd->reading_mt) /* Just to be sure */ 731 input_event(input, EV_ABS, ABS_MT_POSITION_X, nd->x);
718 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;
719 755
720 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;
721 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;
722 799
723 /* 800 /*
724 * Activation state machine logic: 801 * Entered this block inactive and no
725 * 802 * coordinates sent this frame, so hold off
726 * Fundamental states: 803 * on button state.
727 * state > 0: Inactive
728 * state <= 0: Active
729 * state < -deactivate_slack:
730 * Pen termination of touch
731 *
732 * Specific values of interest
733 * state == activate_slack
734 * no valid input since the last reset
735 *
736 * state == 0
737 * general operational state
738 *
739 * state == -deactivate_slack
740 * read sufficient empty frames to accept
741 * the end of input and reset
742 */ 804 */
743 805 break;
744 if (nd->act_state > 0) { /* Currently inactive */ 806 } else { /* Currently active */
745 if (value) 807 if (value && nd->act_state >=
746 /* 808 nd->deactivate_slack)
747 * Consider each live contact as
748 * evidence of intentional activity.
749 */
750 nd->act_state = (nd->act_state > value)
751 ? nd->act_state - value
752 : 0;
753 else
754 /*
755 * Empty frame before we hit the
756 * activity threshold, reset.
757 */
758 nd->act_state = nd->activate_slack;
759
760 /* 809 /*
761 * Entered this block inactive and no 810 * Live point: clear accumulated
762 * coordinates sent this frame, so hold off 811 * deactivation count.
763 * on button state.
764 */ 812 */
765 break; 813 nd->act_state = 0;
766 } else { /* Currently active */ 814 else if (nd->act_state <= nd->deactivate_slack)
767 if (value && nd->act_state >=
768 nd->deactivate_slack)
769 /*
770 * Live point: clear accumulated
771 * deactivation count.
772 */
773 nd->act_state = 0;
774 else if (nd->act_state <= nd->deactivate_slack)
775 /*
776 * We've consumed the deactivation
777 * slack, time to deactivate and reset.
778 */
779 nd->act_state =
780 nd->activate_slack;
781 else { /* Move towards deactivation */
782 nd->act_state--;
783 break;
784 }
785 }
786
787 if (nd->first_contact_touch && nd->act_state <= 0) {
788 /* 815 /*
789 * Check to see if we're ready to start 816 * We've consumed the deactivation
790 * emitting touch events. 817 * slack, time to deactivate and reset.
791 *
792 * Note: activation slack will decrease over
793 * the course of the frame, and it will be
794 * inconsistent from the start to the end of
795 * the frame. However if the frame starts
796 * with slack, first_contact_touch will still
797 * be 0 and we will not get to this point.
798 */ 818 */
799 input_report_key(input, BTN_TOOL_DOUBLETAP, 1); 819 nd->act_state =
800 input_report_key(input, BTN_TOUCH, 1); 820 nd->activate_slack;
801 } else { 821 else { /* Move towards deactivation */
802 input_report_key(input, BTN_TOOL_DOUBLETAP, 0); 822 nd->act_state--;
803 input_report_key(input, BTN_TOUCH, 0); 823 break;
804 } 824 }
805 break; 825 }
806 826
807 default: 827 if (nd->first_contact_touch && nd->act_state <= 0) {
808 /* fall-back to the generic hidinput handling */ 828 /*
809 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);
810 } 844 }
845 break;
846
847 default:
848 /* fall-back to the generic hidinput handling */
849 return 0;
811 } 850 }
812 851
852not_claimed_input:
853
813 /* we have handled the hidinput part, now remains hiddev */ 854 /* we have handled the hidinput part, now remains hiddev */
814 if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_hid_event) 855 if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_hid_event)
815 hid->hiddev_hid_event(hid, field, usage, value); 856 hid->hiddev_hid_event(hid, field, usage, value);
@@ -826,7 +867,8 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id)
826 struct hid_report *report; 867 struct hid_report *report;
827 868
828 if (id->driver_data) 869 if (id->driver_data)
829 hdev->quirks |= HID_QUIRK_MULTI_INPUT; 870 hdev->quirks |= HID_QUIRK_MULTI_INPUT
871 | HID_QUIRK_NO_INIT_REPORTS;
830 872
831 nd = kmalloc(sizeof(struct ntrig_data), GFP_KERNEL); 873 nd = kmalloc(sizeof(struct ntrig_data), GFP_KERNEL);
832 if (!nd) { 874 if (!nd) {
@@ -893,8 +935,19 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id)
893 935
894 /* This is needed for devices with more recent firmware versions */ 936 /* This is needed for devices with more recent firmware versions */
895 report = hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[0x0a]; 937 report = hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[0x0a];
896 if (report) 938 if (report) {
897 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 }
898 951
899 ntrig_report_version(hdev); 952 ntrig_report_version(hdev);
900 953
diff --git a/drivers/hid/hid-ortek.c b/drivers/hid/hid-ortek.c
index e90edfc63051..f9b7dd4f607f 100644
--- a/drivers/hid/hid-ortek.c
+++ b/drivers/hid/hid-ortek.c
@@ -1,7 +1,6 @@
1/* 1/*
2 * HID driver for Ortek WKB-2000 (wireless keyboard + mouse trackpad). 2 * HID driver for Ortek PKB-1700/WKB-2000 (wireless keyboard + mouse trackpad).
3 * Fixes LogicalMaximum error in USB report description, see 3 * Fixes LogicalMaximum error in HID report description.
4 * http://bugzilla.kernel.org/show_bug.cgi?id=14787
5 * 4 *
6 * Copyright (c) 2010 Johnathon Harris <jmharris@gmail.com> 5 * Copyright (c) 2010 Johnathon Harris <jmharris@gmail.com>
7 */ 6 */
@@ -30,6 +29,7 @@ static __u8 *ortek_report_fixup(struct hid_device *hdev, __u8 *rdesc,
30} 29}
31 30
32static const struct hid_device_id ortek_devices[] = { 31static const struct hid_device_id ortek_devices[] = {
32 { 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) }, 33 { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) },
34 { } 34 { }
35}; 35};
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
29static struct class *arvo_class;
30
31static 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
51static 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
79static 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
99static 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 */
128static 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
142static 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
151static 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
180static 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
200static 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
223static 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
231static 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
240static 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
251static 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
265static 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
280static 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;
316exit_free:
317 kfree(arvo);
318 return retval;
319}
320
321static 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
336static 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
361exit_stop:
362 hid_hw_stop(hdev);
363exit:
364 return retval;
365}
366
367static void arvo_remove(struct hid_device *hdev)
368{
369 arvo_remove_specials(hdev);
370 hid_hw_stop(hdev);
371}
372
373static 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
394static 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
408static const struct hid_device_id arvo_devices[] = {
409 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ARVO) },
410 { }
411};
412
413MODULE_DEVICE_TABLE(hid, arvo_devices);
414
415static 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
423static 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
439static void __exit arvo_exit(void)
440{
441 hid_unregister_driver(&arvo_driver);
442 class_destroy(arvo_class);
443}
444
445module_init(arvo_init);
446module_exit(arvo_exit);
447
448MODULE_AUTHOR("Stefan Achatz");
449MODULE_DESCRIPTION("USB Roccat Arvo driver");
450MODULE_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
17struct arvo_mode_key { /* 2 bytes */
18 uint8_t command; /* ARVO_COMMAND_MODE_KEY */
19 uint8_t state;
20} __packed;
21
22struct arvo_button {
23 uint8_t unknown[24];
24} __packed;
25
26struct arvo_info {
27 uint8_t unknown[8];
28} __packed;
29
30struct 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 */
36struct arvo_actual_profile { /* 2 bytes */
37 uint8_t command; /* ARVO_COMMAND_ACTUAL_PROFILE */
38 uint8_t actual_profile;
39} __packed;
40
41enum 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
49enum 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
62struct arvo_special_report {
63 uint8_t unknown1; /* always 0x01 */
64 uint8_t event;
65 uint8_t unknown2; /* always 0x70 */
66} __packed;
67
68enum arvo_special_report_events {
69 ARVO_SPECIAL_REPORT_EVENT_ACTION_PRESS = 0x10,
70 ARVO_SPECIAL_REPORT_EVENT_ACTION_RELEASE = 0x0,
71};
72
73enum arvo_special_report_event_masks {
74 ARVO_SPECIAL_REPORT_EVENT_MASK_ACTION = 0xf0,
75 ARVO_SPECIAL_REPORT_EVENT_MASK_BUTTON = 0x0f,
76};
77
78struct arvo_roccat_report {
79 uint8_t profile;
80 uint8_t button;
81 uint8_t action;
82} __packed;
83
84enum arvo_roccat_report_action {
85 ARVO_ROCCAT_REPORT_ACTION_RELEASE = 0,
86 ARVO_ROCCAT_REPORT_ACTION_PRESS = 1,
87};
88
89struct 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
17int 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}
36EXPORT_SYMBOL_GPL(roccat_common_receive);
37
38int 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}
58EXPORT_SYMBOL_GPL(roccat_common_send);
59
60MODULE_AUTHOR("Stefan Achatz");
61MODULE_DESCRIPTION("USB Roccat common driver");
62MODULE_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
18int roccat_common_receive(struct usb_device *usb_dev, uint usb_command,
19 void *data, uint size);
20int 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 cbd8cc42e75a..a57838d15267 100644
--- a/drivers/hid/hid-roccat-kone.c
+++ b/drivers/hid/hid-roccat-kone.c
@@ -28,11 +28,11 @@
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
38static uint profile_numbers[5] = {0, 1, 2, 3, 4}; 38static uint profile_numbers[5] = {0, 1, 2, 3, 4};
@@ -58,12 +58,8 @@ static void kone_set_settings_checksum(struct kone_settings *settings)
58 */ 58 */
59static int kone_check_write(struct usb_device *usb_dev) 59static int kone_check_write(struct usb_device *usb_dev)
60{ 60{
61 int len; 61 int retval;
62 unsigned char *data; 62 uint8_t data;
63
64 data = kmalloc(1, GFP_KERNEL);
65 if (!data)
66 return -ENOMEM;
67 63
68 do { 64 do {
69 /* 65 /*
@@ -72,56 +68,36 @@ static int kone_check_write(struct usb_device *usb_dev)
72 */ 68 */
73 msleep(80); 69 msleep(80);
74 70
75 len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), 71 retval = roccat_common_receive(usb_dev,
76 USB_REQ_CLEAR_FEATURE, 72 kone_command_confirm_write, &data, 1);
77 USB_TYPE_CLASS | USB_RECIP_INTERFACE | 73 if (retval)
78 USB_DIR_IN, 74 return retval;
79 kone_command_confirm_write, 0, data, 1,
80 USB_CTRL_SET_TIMEOUT);
81
82 if (len != 1) {
83 kfree(data);
84 return -EIO;
85 }
86 75
87 /* 76 /*
88 * value of 3 seems to mean something like 77 * value of 3 seems to mean something like
89 * "not finished yet, but it looks good" 78 * "not finished yet, but it looks good"
90 * So check again after a moment. 79 * So check again after a moment.
91 */ 80 */
92 } while (*data == 3); 81 } while (data == 3);
93 82
94 if (*data == 1) { /* everything alright */ 83 if (data == 1) /* everything alright */
95 kfree(data);
96 return 0; 84 return 0;
97 } else { /* unknown answer */ 85
98 hid_err(usb_dev, "got retval %d when checking write\n", *data); 86 /* unknown answer */
99 kfree(data); 87 hid_err(usb_dev, "got retval %d when checking write\n", data);
100 return -EIO; 88 return -EIO;
101 }
102} 89}
103 90
104/* 91/*
105 * Reads settings from mouse and stores it in @buf 92 * Reads settings from mouse and stores it in @buf
106 * @buf has to be alloced with GFP_KERNEL
107 * On success returns 0 93 * On success returns 0
108 * On failure returns errno 94 * On failure returns errno
109 */ 95 */
110static int kone_get_settings(struct usb_device *usb_dev, 96static int kone_get_settings(struct usb_device *usb_dev,
111 struct kone_settings *buf) 97 struct kone_settings *buf)
112{ 98{
113 int len; 99 return roccat_common_receive(usb_dev, kone_command_settings, buf,
114 100 sizeof(struct kone_settings));
115 len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
116 USB_REQ_CLEAR_FEATURE,
117 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
118 kone_command_settings, 0, buf,
119 sizeof(struct kone_settings), USB_CTRL_SET_TIMEOUT);
120
121 if (len != sizeof(struct kone_settings))
122 return -EIO;
123
124 return 0;
125} 101}
126 102
127/* 103/*
@@ -132,22 +108,12 @@ static int kone_get_settings(struct usb_device *usb_dev,
132static int kone_set_settings(struct usb_device *usb_dev, 108static int kone_set_settings(struct usb_device *usb_dev,
133 struct kone_settings const *settings) 109 struct kone_settings const *settings)
134{ 110{
135 int len; 111 int retval;
136 112 retval = roccat_common_send(usb_dev, kone_command_settings,
137 len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), 113 settings, sizeof(struct kone_settings));
138 USB_REQ_SET_CONFIGURATION, 114 if (retval)
139 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, 115 return retval;
140 kone_command_settings, 0, (char *)settings, 116 return kone_check_write(usb_dev);
141 sizeof(struct kone_settings),
142 USB_CTRL_SET_TIMEOUT);
143
144 if (len != sizeof(struct kone_settings))
145 return -EIO;
146
147 if (kone_check_write(usb_dev))
148 return -EIO;
149
150 return 0;
151} 117}
152 118
153/* 119/*
@@ -193,7 +159,7 @@ static int kone_set_profile(struct usb_device *usb_dev,
193 len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), 159 len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
194 USB_REQ_SET_CONFIGURATION, 160 USB_REQ_SET_CONFIGURATION,
195 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, 161 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
196 kone_command_profile, number, (char *)profile, 162 kone_command_profile, number, (void *)profile,
197 sizeof(struct kone_profile), 163 sizeof(struct kone_profile),
198 USB_CTRL_SET_TIMEOUT); 164 USB_CTRL_SET_TIMEOUT);
199 165
@@ -213,24 +179,15 @@ static int kone_set_profile(struct usb_device *usb_dev,
213 */ 179 */
214static int kone_get_weight(struct usb_device *usb_dev, int *result) 180static int kone_get_weight(struct usb_device *usb_dev, int *result)
215{ 181{
216 int len; 182 int retval;
217 uint8_t *data; 183 uint8_t data;
218 184
219 data = kmalloc(1, GFP_KERNEL); 185 retval = roccat_common_receive(usb_dev, kone_command_weight, &data, 1);
220 if (!data)
221 return -ENOMEM;
222 186
223 len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), 187 if (retval)
224 USB_REQ_CLEAR_FEATURE, 188 return retval;
225 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
226 kone_command_weight, 0, data, 1, USB_CTRL_SET_TIMEOUT);
227 189
228 if (len != 1) { 190 *result = (int)data;
229 kfree(data);
230 return -EIO;
231 }
232 *result = (int)*data;
233 kfree(data);
234 return 0; 191 return 0;
235} 192}
236 193
@@ -241,25 +198,15 @@ static int kone_get_weight(struct usb_device *usb_dev, int *result)
241 */ 198 */
242static int kone_get_firmware_version(struct usb_device *usb_dev, int *result) 199static int kone_get_firmware_version(struct usb_device *usb_dev, int *result)
243{ 200{
244 int len; 201 int retval;
245 unsigned char *data; 202 uint16_t data;
246
247 data = kmalloc(2, GFP_KERNEL);
248 if (!data)
249 return -ENOMEM;
250 203
251 len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), 204 retval = roccat_common_receive(usb_dev, kone_command_firmware_version,
252 USB_REQ_CLEAR_FEATURE, 205 &data, 2);
253 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, 206 if (retval)
254 kone_command_firmware_version, 0, data, 2, 207 return retval;
255 USB_CTRL_SET_TIMEOUT);
256 208
257 if (len != 2) { 209 *result = le16_to_cpu(data);
258 kfree(data);
259 return -EIO;
260 }
261 *result = le16_to_cpu(*data);
262 kfree(data);
263 return 0; 210 return 0;
264} 211}
265 212
@@ -435,23 +382,9 @@ static ssize_t kone_sysfs_show_tcu(struct device *dev,
435 382
436static int kone_tcu_command(struct usb_device *usb_dev, int number) 383static int kone_tcu_command(struct usb_device *usb_dev, int number)
437{ 384{
438 int len; 385 unsigned char value;
439 char *value; 386 value = number;
440 387 return roccat_common_send(usb_dev, kone_command_calibrate, &value, 1);
441 value = kmalloc(1, GFP_KERNEL);
442 if (!value)
443 return -ENOMEM;
444
445 *value = number;
446
447 len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
448 USB_REQ_SET_CONFIGURATION,
449 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
450 kone_command_calibrate, 0, value, 1,
451 USB_CTRL_SET_TIMEOUT);
452
453 kfree(value);
454 return ((len != 1) ? -EIO : 0);
455} 388}
456 389
457/* 390/*
@@ -727,7 +660,8 @@ static int kone_init_specials(struct hid_device *hdev)
727 goto exit_free; 660 goto exit_free;
728 } 661 }
729 662
730 retval = roccat_connect(kone_class, hdev); 663 retval = roccat_connect(kone_class, hdev,
664 sizeof(struct kone_roccat_report));
731 if (retval < 0) { 665 if (retval < 0) {
732 hid_err(hdev, "couldn't init char dev\n"); 666 hid_err(hdev, "couldn't init char dev\n");
733 /* be tolerant about not getting chrdev */ 667 /* be tolerant about not getting chrdev */
@@ -827,8 +761,7 @@ static void kone_report_to_chrdev(struct kone_device const *kone,
827 roccat_report.value = event->value; 761 roccat_report.value = event->value;
828 roccat_report.key = 0; 762 roccat_report.key = 0;
829 roccat_report_event(kone->chrdev_minor, 763 roccat_report_event(kone->chrdev_minor,
830 (uint8_t *)&roccat_report, 764 (uint8_t *)&roccat_report);
831 sizeof(struct kone_roccat_report));
832 break; 765 break;
833 case kone_mouse_event_call_overlong_macro: 766 case kone_mouse_event_call_overlong_macro:
834 if (event->value == kone_keystroke_action_press) { 767 if (event->value == kone_keystroke_action_press) {
@@ -836,8 +769,7 @@ static void kone_report_to_chrdev(struct kone_device const *kone,
836 roccat_report.value = kone->actual_profile; 769 roccat_report.value = kone->actual_profile;
837 roccat_report.key = event->macro_key; 770 roccat_report.key = event->macro_key;
838 roccat_report_event(kone->chrdev_minor, 771 roccat_report_event(kone->chrdev_minor,
839 (uint8_t *)&roccat_report, 772 (uint8_t *)&roccat_report);
840 sizeof(struct kone_roccat_report));
841 } 773 }
842 break; 774 break;
843 } 775 }
@@ -912,8 +844,8 @@ static int __init kone_init(void)
912 844
913static void __exit kone_exit(void) 845static void __exit kone_exit(void)
914{ 846{
915 class_destroy(kone_class);
916 hid_unregister_driver(&kone_driver); 847 hid_unregister_driver(&kone_driver);
848 class_destroy(kone_class);
917} 849}
918 850
919module_init(kone_init); 851module_init(kone_init);
diff --git a/drivers/hid/hid-roccat-koneplus.c b/drivers/hid/hid-roccat-koneplus.c
index 1608c8d1efd6..33eec74e0615 100644
--- a/drivers/hid/hid-roccat-koneplus.c
+++ b/drivers/hid/hid-roccat-koneplus.c
@@ -19,11 +19,11 @@
19#include <linux/device.h> 19#include <linux/device.h>
20#include <linux/input.h> 20#include <linux/input.h>
21#include <linux/hid.h> 21#include <linux/hid.h>
22#include <linux/usb.h>
23#include <linux/module.h> 22#include <linux/module.h>
24#include <linux/slab.h> 23#include <linux/slab.h>
24#include <linux/hid-roccat.h>
25#include "hid-ids.h" 25#include "hid-ids.h"
26#include "hid-roccat.h" 26#include "hid-roccat-common.h"
27#include "hid-roccat-koneplus.h" 27#include "hid-roccat-koneplus.h"
28 28
29static uint profile_numbers[5] = {0, 1, 2, 3, 4}; 29static uint profile_numbers[5] = {0, 1, 2, 3, 4};
@@ -39,110 +39,63 @@ static void koneplus_profile_activated(struct koneplus_device *koneplus,
39static int koneplus_send_control(struct usb_device *usb_dev, uint value, 39static int koneplus_send_control(struct usb_device *usb_dev, uint value,
40 enum koneplus_control_requests request) 40 enum koneplus_control_requests request)
41{ 41{
42 int len; 42 struct koneplus_control control;
43 struct koneplus_control *control;
44 43
45 if ((request == KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS || 44 if ((request == KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS ||
46 request == KONEPLUS_CONTROL_REQUEST_PROFILE_BUTTONS) && 45 request == KONEPLUS_CONTROL_REQUEST_PROFILE_BUTTONS) &&
47 value > 4) 46 value > 4)
48 return -EINVAL; 47 return -EINVAL;
49 48
50 control = kmalloc(sizeof(struct koneplus_control), GFP_KERNEL); 49 control.command = KONEPLUS_COMMAND_CONTROL;
51 if (!control) 50 control.value = value;
52 return -ENOMEM; 51 control.request = request;
53 52
54 control->command = KONEPLUS_COMMAND_CONTROL; 53 return roccat_common_send(usb_dev, KONEPLUS_USB_COMMAND_CONTROL,
55 control->value = value; 54 &control, sizeof(struct koneplus_control));
56 control->request = request;
57
58 len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
59 USB_REQ_SET_CONFIGURATION,
60 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
61 KONEPLUS_USB_COMMAND_CONTROL, 0, control,
62 sizeof(struct koneplus_control),
63 USB_CTRL_SET_TIMEOUT);
64
65 kfree(control);
66
67 if (len != sizeof(struct koneplus_control))
68 return len;
69
70 return 0;
71}
72
73static int koneplus_receive(struct usb_device *usb_dev, uint usb_command,
74 void *buf, uint size) {
75 int len;
76
77 len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
78 USB_REQ_CLEAR_FEATURE,
79 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
80 usb_command, 0, buf, size, USB_CTRL_SET_TIMEOUT);
81
82 return (len != size) ? -EIO : 0;
83} 55}
84 56
85static int koneplus_receive_control_status(struct usb_device *usb_dev) 57static int koneplus_receive_control_status(struct usb_device *usb_dev)
86{ 58{
87 int retval; 59 int retval;
88 struct koneplus_control *control; 60 struct koneplus_control control;
89
90 control = kmalloc(sizeof(struct koneplus_control), GFP_KERNEL);
91 if (!control)
92 return -ENOMEM;
93 61
94 do { 62 do {
95 retval = koneplus_receive(usb_dev, KONEPLUS_USB_COMMAND_CONTROL, 63 retval = roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_CONTROL,
96 control, sizeof(struct koneplus_control)); 64 &control, sizeof(struct koneplus_control));
97 65
98 /* check if we get a completely wrong answer */ 66 /* check if we get a completely wrong answer */
99 if (retval) 67 if (retval)
100 goto out; 68 return retval;
101 69
102 if (control->value == KONEPLUS_CONTROL_REQUEST_STATUS_OK) { 70 if (control.value == KONEPLUS_CONTROL_REQUEST_STATUS_OK)
103 retval = 0; 71 return 0;
104 goto out;
105 }
106 72
107 /* indicates that hardware needs some more time to complete action */ 73 /* indicates that hardware needs some more time to complete action */
108 if (control->value == KONEPLUS_CONTROL_REQUEST_STATUS_WAIT) { 74 if (control.value == KONEPLUS_CONTROL_REQUEST_STATUS_WAIT) {
109 msleep(500); /* windows driver uses 1000 */ 75 msleep(500); /* windows driver uses 1000 */
110 continue; 76 continue;
111 } 77 }
112 78
113 /* seems to be critical - replug necessary */ 79 /* seems to be critical - replug necessary */
114 if (control->value == KONEPLUS_CONTROL_REQUEST_STATUS_OVERLOAD) { 80 if (control.value == KONEPLUS_CONTROL_REQUEST_STATUS_OVERLOAD)
115 retval = -EINVAL; 81 return -EINVAL;
116 goto out;
117 }
118
119 dev_err(&usb_dev->dev, "koneplus_receive_control_status: "
120 "unknown response value 0x%x\n", control->value);
121 retval = -EINVAL;
122 goto out;
123 82
83 hid_err(usb_dev, "koneplus_receive_control_status: "
84 "unknown response value 0x%x\n", control.value);
85 return -EINVAL;
124 } while (1); 86 } while (1);
125out:
126 kfree(control);
127 return retval;
128} 87}
129 88
130static int koneplus_send(struct usb_device *usb_dev, uint command, 89static int koneplus_send(struct usb_device *usb_dev, uint command,
131 void *buf, uint size) { 90 void const *buf, uint size)
132 int len; 91{
133 92 int retval;
134 len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
135 USB_REQ_SET_CONFIGURATION,
136 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
137 command, 0, buf, size, USB_CTRL_SET_TIMEOUT);
138
139 if (len != size)
140 return -EIO;
141 93
142 if (koneplus_receive_control_status(usb_dev)) 94 retval = roccat_common_send(usb_dev, command, buf, size);
143 return -EIO; 95 if (retval)
96 return retval;
144 97
145 return 0; 98 return koneplus_receive_control_status(usb_dev);
146} 99}
147 100
148static int koneplus_select_profile(struct usb_device *usb_dev, uint number, 101static int koneplus_select_profile(struct usb_device *usb_dev, uint number,
@@ -167,7 +120,7 @@ static int koneplus_select_profile(struct usb_device *usb_dev, uint number,
167static int koneplus_get_info(struct usb_device *usb_dev, 120static int koneplus_get_info(struct usb_device *usb_dev,
168 struct koneplus_info *buf) 121 struct koneplus_info *buf)
169{ 122{
170 return koneplus_receive(usb_dev, KONEPLUS_USB_COMMAND_INFO, 123 return roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_INFO,
171 buf, sizeof(struct koneplus_info)); 124 buf, sizeof(struct koneplus_info));
172} 125}
173 126
@@ -181,7 +134,7 @@ static int koneplus_get_profile_settings(struct usb_device *usb_dev,
181 if (retval) 134 if (retval)
182 return retval; 135 return retval;
183 136
184 return koneplus_receive(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_SETTINGS, 137 return roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_SETTINGS,
185 buf, sizeof(struct koneplus_profile_settings)); 138 buf, sizeof(struct koneplus_profile_settings));
186} 139}
187 140
@@ -189,7 +142,7 @@ static int koneplus_set_profile_settings(struct usb_device *usb_dev,
189 struct koneplus_profile_settings const *settings) 142 struct koneplus_profile_settings const *settings)
190{ 143{
191 return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_SETTINGS, 144 return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_SETTINGS,
192 (void *)settings, sizeof(struct koneplus_profile_settings)); 145 settings, sizeof(struct koneplus_profile_settings));
193} 146}
194 147
195static int koneplus_get_profile_buttons(struct usb_device *usb_dev, 148static int koneplus_get_profile_buttons(struct usb_device *usb_dev,
@@ -202,7 +155,7 @@ static int koneplus_get_profile_buttons(struct usb_device *usb_dev,
202 if (retval) 155 if (retval)
203 return retval; 156 return retval;
204 157
205 return koneplus_receive(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_BUTTONS, 158 return roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_BUTTONS,
206 buf, sizeof(struct koneplus_profile_buttons)); 159 buf, sizeof(struct koneplus_profile_buttons));
207} 160}
208 161
@@ -210,27 +163,19 @@ static int koneplus_set_profile_buttons(struct usb_device *usb_dev,
210 struct koneplus_profile_buttons const *buttons) 163 struct koneplus_profile_buttons const *buttons)
211{ 164{
212 return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_BUTTONS, 165 return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_BUTTONS,
213 (void *)buttons, sizeof(struct koneplus_profile_buttons)); 166 buttons, sizeof(struct koneplus_profile_buttons));
214} 167}
215 168
216/* retval is 0-4 on success, < 0 on error */ 169/* retval is 0-4 on success, < 0 on error */
217static int koneplus_get_startup_profile(struct usb_device *usb_dev) 170static int koneplus_get_startup_profile(struct usb_device *usb_dev)
218{ 171{
219 struct koneplus_startup_profile *buf; 172 struct koneplus_startup_profile buf;
220 int retval; 173 int retval;
221 174
222 buf = kmalloc(sizeof(struct koneplus_startup_profile), GFP_KERNEL); 175 retval = roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_STARTUP_PROFILE,
176 &buf, sizeof(struct koneplus_startup_profile));
223 177
224 retval = koneplus_receive(usb_dev, KONEPLUS_USB_COMMAND_STARTUP_PROFILE, 178 return retval ? retval : buf.startup_profile;
225 buf, sizeof(struct koneplus_startup_profile));
226
227 if (retval)
228 goto out;
229
230 retval = buf->startup_profile;
231out:
232 kfree(buf);
233 return retval;
234} 179}
235 180
236static int koneplus_set_startup_profile(struct usb_device *usb_dev, 181static int koneplus_set_startup_profile(struct usb_device *usb_dev,
@@ -243,7 +188,7 @@ static int koneplus_set_startup_profile(struct usb_device *usb_dev,
243 buf.startup_profile = startup_profile; 188 buf.startup_profile = startup_profile;
244 189
245 return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_STARTUP_PROFILE, 190 return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_STARTUP_PROFILE,
246 (char *)&buf, sizeof(struct koneplus_profile_buttons)); 191 &buf, sizeof(struct koneplus_profile_buttons));
247} 192}
248 193
249static ssize_t koneplus_sysfs_read(struct file *fp, struct kobject *kobj, 194static ssize_t koneplus_sysfs_read(struct file *fp, struct kobject *kobj,
@@ -256,11 +201,14 @@ static ssize_t koneplus_sysfs_read(struct file *fp, struct kobject *kobj,
256 struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); 201 struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
257 int retval; 202 int retval;
258 203
204 if (off >= real_size)
205 return 0;
206
259 if (off != 0 || count != real_size) 207 if (off != 0 || count != real_size)
260 return -EINVAL; 208 return -EINVAL;
261 209
262 mutex_lock(&koneplus->koneplus_lock); 210 mutex_lock(&koneplus->koneplus_lock);
263 retval = koneplus_receive(usb_dev, command, buf, real_size); 211 retval = roccat_common_receive(usb_dev, command, buf, real_size);
264 mutex_unlock(&koneplus->koneplus_lock); 212 mutex_unlock(&koneplus->koneplus_lock);
265 213
266 if (retval) 214 if (retval)
@@ -283,7 +231,7 @@ static ssize_t koneplus_sysfs_write(struct file *fp, struct kobject *kobj,
283 return -EINVAL; 231 return -EINVAL;
284 232
285 mutex_lock(&koneplus->koneplus_lock); 233 mutex_lock(&koneplus->koneplus_lock);
286 retval = koneplus_send(usb_dev, command, (void *)buf, real_size); 234 retval = koneplus_send(usb_dev, command, buf, real_size);
287 mutex_unlock(&koneplus->koneplus_lock); 235 mutex_unlock(&koneplus->koneplus_lock);
288 236
289 if (retval) 237 if (retval)
@@ -347,7 +295,7 @@ static ssize_t koneplus_sysfs_read_profilex_settings(struct file *fp,
347 count = sizeof(struct koneplus_profile_settings) - off; 295 count = sizeof(struct koneplus_profile_settings) - off;
348 296
349 mutex_lock(&koneplus->koneplus_lock); 297 mutex_lock(&koneplus->koneplus_lock);
350 memcpy(buf, ((void const *)&koneplus->profile_settings[*(uint *)(attr->private)]) + off, 298 memcpy(buf, ((char const *)&koneplus->profile_settings[*(uint *)(attr->private)]) + off,
351 count); 299 count);
352 mutex_unlock(&koneplus->koneplus_lock); 300 mutex_unlock(&koneplus->koneplus_lock);
353 301
@@ -406,7 +354,7 @@ static ssize_t koneplus_sysfs_read_profilex_buttons(struct file *fp,
406 count = sizeof(struct koneplus_profile_buttons) - off; 354 count = sizeof(struct koneplus_profile_buttons) - off;
407 355
408 mutex_lock(&koneplus->koneplus_lock); 356 mutex_lock(&koneplus->koneplus_lock);
409 memcpy(buf, ((void const *)&koneplus->profile_buttons[*(uint *)(attr->private)]) + off, 357 memcpy(buf, ((char const *)&koneplus->profile_buttons[*(uint *)(attr->private)]) + off,
410 count); 358 count);
411 mutex_unlock(&koneplus->koneplus_lock); 359 mutex_unlock(&koneplus->koneplus_lock);
412 360
@@ -512,7 +460,7 @@ static struct device_attribute koneplus_attributes[] = {
512 460
513static struct bin_attribute koneplus_bin_attributes[] = { 461static struct bin_attribute koneplus_bin_attributes[] = {
514 { 462 {
515 .attr = { .name = "sensor", .mode = 0220 }, 463 .attr = { .name = "sensor", .mode = 0660 },
516 .size = sizeof(struct koneplus_sensor), 464 .size = sizeof(struct koneplus_sensor),
517 .read = koneplus_sysfs_read_sensor, 465 .read = koneplus_sysfs_read_sensor,
518 .write = koneplus_sysfs_write_sensor 466 .write = koneplus_sysfs_write_sensor
@@ -609,11 +557,13 @@ static int koneplus_init_koneplus_device_struct(struct usb_device *usb_dev,
609 struct koneplus_device *koneplus) 557 struct koneplus_device *koneplus)
610{ 558{
611 int retval, i; 559 int retval, i;
612 static uint wait = 70; /* device will freeze with just 60 */ 560 static uint wait = 100; /* device will freeze with just 60 */
613 561
614 mutex_init(&koneplus->koneplus_lock); 562 mutex_init(&koneplus->koneplus_lock);
615 563
616 koneplus->startup_profile = koneplus_get_startup_profile(usb_dev); 564 koneplus->startup_profile = koneplus_get_startup_profile(usb_dev);
565 if (koneplus->startup_profile < 0)
566 return koneplus->startup_profile;
617 567
618 msleep(wait); 568 msleep(wait);
619 retval = koneplus_get_info(usb_dev, &koneplus->info); 569 retval = koneplus_get_info(usb_dev, &koneplus->info);
@@ -651,21 +601,21 @@ static int koneplus_init_specials(struct hid_device *hdev)
651 601
652 koneplus = kzalloc(sizeof(*koneplus), GFP_KERNEL); 602 koneplus = kzalloc(sizeof(*koneplus), GFP_KERNEL);
653 if (!koneplus) { 603 if (!koneplus) {
654 dev_err(&hdev->dev, "can't alloc device descriptor\n"); 604 hid_err(hdev, "can't alloc device descriptor\n");
655 return -ENOMEM; 605 return -ENOMEM;
656 } 606 }
657 hid_set_drvdata(hdev, koneplus); 607 hid_set_drvdata(hdev, koneplus);
658 608
659 retval = koneplus_init_koneplus_device_struct(usb_dev, koneplus); 609 retval = koneplus_init_koneplus_device_struct(usb_dev, koneplus);
660 if (retval) { 610 if (retval) {
661 dev_err(&hdev->dev, 611 hid_err(hdev, "couldn't init struct koneplus_device\n");
662 "couldn't init struct koneplus_device\n");
663 goto exit_free; 612 goto exit_free;
664 } 613 }
665 614
666 retval = roccat_connect(koneplus_class, hdev); 615 retval = roccat_connect(koneplus_class, hdev,
616 sizeof(struct koneplus_roccat_report));
667 if (retval < 0) { 617 if (retval < 0) {
668 dev_err(&hdev->dev, "couldn't init char dev\n"); 618 hid_err(hdev, "couldn't init char dev\n");
669 } else { 619 } else {
670 koneplus->chrdev_minor = retval; 620 koneplus->chrdev_minor = retval;
671 koneplus->roccat_claimed = 1; 621 koneplus->roccat_claimed = 1;
@@ -701,19 +651,19 @@ static int koneplus_probe(struct hid_device *hdev,
701 651
702 retval = hid_parse(hdev); 652 retval = hid_parse(hdev);
703 if (retval) { 653 if (retval) {
704 dev_err(&hdev->dev, "parse failed\n"); 654 hid_err(hdev, "parse failed\n");
705 goto exit; 655 goto exit;
706 } 656 }
707 657
708 retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT); 658 retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
709 if (retval) { 659 if (retval) {
710 dev_err(&hdev->dev, "hw start failed\n"); 660 hid_err(hdev, "hw start failed\n");
711 goto exit; 661 goto exit;
712 } 662 }
713 663
714 retval = koneplus_init_specials(hdev); 664 retval = koneplus_init_specials(hdev);
715 if (retval) { 665 if (retval) {
716 dev_err(&hdev->dev, "couldn't install mouse\n"); 666 hid_err(hdev, "couldn't install mouse\n");
717 goto exit_stop; 667 goto exit_stop;
718 } 668 }
719 669
@@ -769,8 +719,7 @@ static void koneplus_report_to_chrdev(struct koneplus_device const *koneplus,
769 roccat_report.data2 = button_report->data2; 719 roccat_report.data2 = button_report->data2;
770 roccat_report.profile = koneplus->actual_profile + 1; 720 roccat_report.profile = koneplus->actual_profile + 1;
771 roccat_report_event(koneplus->chrdev_minor, 721 roccat_report_event(koneplus->chrdev_minor,
772 (uint8_t const *)&roccat_report, 722 (uint8_t const *)&roccat_report);
773 sizeof(struct koneplus_roccat_report));
774} 723}
775 724
776static int koneplus_raw_event(struct hid_device *hdev, 725static int koneplus_raw_event(struct hid_device *hdev,
@@ -825,8 +774,8 @@ static int __init koneplus_init(void)
825 774
826static void __exit koneplus_exit(void) 775static void __exit koneplus_exit(void)
827{ 776{
828 class_destroy(koneplus_class);
829 hid_unregister_driver(&koneplus_driver); 777 hid_unregister_driver(&koneplus_driver);
778 class_destroy(koneplus_class);
830} 779}
831 780
832module_init(koneplus_init); 781module_init(koneplus_init);
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
28static uint profile_numbers[5] = {0, 1, 2, 3, 4};
29
30static struct class *kovaplus_class;
31
32static uint kovaplus_convert_event_cpi(uint value)
33{
34 return (value == 7 ? 4 : (value == 4 ? 3 : value));
35}
36
37static 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
46static 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
67static 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
99static 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
113static 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
119static 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
126static 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
140static 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
147static 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
161static 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 */
169static 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
180static 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
193static 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
215static 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
252static 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
274static 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
311static 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
319static 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
348static 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
356static 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
364static 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
372static 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
380static 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
395static 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
469static 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
504static 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;
541exit_free:
542 kfree(kovaplus);
543 return retval;
544}
545
546static 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
560static 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
585exit_stop:
586 hid_hw_stop(hdev);
587exit:
588 return retval;
589}
590
591static void kovaplus_remove(struct hid_device *hdev)
592{
593 kovaplus_remove_specials(hdev);
594 hid_hw_stop(hdev);
595}
596
597static 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
619static 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
655static 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
673static const struct hid_device_id kovaplus_devices[] = {
674 { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KOVAPLUS) },
675 { }
676};
677
678MODULE_DEVICE_TABLE(hid, kovaplus_devices);
679
680static 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
688static 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
704static void __exit kovaplus_exit(void)
705{
706 hid_unregister_driver(&kovaplus_driver);
707 class_destroy(kovaplus_class);
708}
709
710module_init(kovaplus_init);
711module_exit(kovaplus_exit);
712
713MODULE_AUTHOR("Stefan Achatz");
714MODULE_DESCRIPTION("USB Roccat Kova[+] driver");
715MODULE_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
17struct kovaplus_control {
18 uint8_t command; /* KOVAPLUS_COMMAND_CONTROL */
19 uint8_t value;
20 uint8_t request;
21} __packed;
22
23enum 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
32enum 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
38struct 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
44struct 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
56struct 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
63struct 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 */
71struct kovaplus_a {
72 uint8_t command; /* KOVAPLUS_COMMAND_A */
73 uint8_t size; /* 3 */
74 uint8_t unknown;
75} __packed;
76
77enum 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
86enum 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
95enum 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
102struct 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
110enum 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
131enum kovaplus_mouse_report_button_actions {
132 KOVAPLUS_MOUSE_REPORT_BUTTON_ACTION_PRESS = 0,
133 KOVAPLUS_MOUSE_REPORT_BUTTON_ACTION_RELEASE = 1,
134};
135
136struct 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
144struct 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
index 02c58e015bee..160f481344f6 100644
--- a/drivers/hid/hid-roccat-pyra.c
+++ b/drivers/hid/hid-roccat-pyra.c
@@ -20,11 +20,11 @@
20#include <linux/device.h> 20#include <linux/device.h>
21#include <linux/input.h> 21#include <linux/input.h>
22#include <linux/hid.h> 22#include <linux/hid.h>
23#include <linux/usb.h>
24#include <linux/module.h> 23#include <linux/module.h>
25#include <linux/slab.h> 24#include <linux/slab.h>
25#include <linux/hid-roccat.h>
26#include "hid-ids.h" 26#include "hid-ids.h"
27#include "hid-roccat.h" 27#include "hid-roccat-common.h"
28#include "hid-roccat-pyra.h" 28#include "hid-roccat-pyra.h"
29 29
30static uint profile_numbers[5] = {0, 1, 2, 3, 4}; 30static uint profile_numbers[5] = {0, 1, 2, 3, 4};
@@ -42,7 +42,6 @@ static void profile_activated(struct pyra_device *pyra,
42static int pyra_send_control(struct usb_device *usb_dev, int value, 42static int pyra_send_control(struct usb_device *usb_dev, int value,
43 enum pyra_control_requests request) 43 enum pyra_control_requests request)
44{ 44{
45 int len;
46 struct pyra_control control; 45 struct pyra_control control;
47 46
48 if ((request == PYRA_CONTROL_REQUEST_PROFILE_SETTINGS || 47 if ((request == PYRA_CONTROL_REQUEST_PROFILE_SETTINGS ||
@@ -54,47 +53,31 @@ static int pyra_send_control(struct usb_device *usb_dev, int value,
54 control.value = value; 53 control.value = value;
55 control.request = request; 54 control.request = request;
56 55
57 len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), 56 return roccat_common_send(usb_dev, PYRA_USB_COMMAND_CONTROL,
58 USB_REQ_SET_CONFIGURATION, 57 &control, sizeof(struct pyra_control));
59 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
60 PYRA_USB_COMMAND_CONTROL, 0, (char *)&control,
61 sizeof(struct pyra_control),
62 USB_CTRL_SET_TIMEOUT);
63
64 if (len != sizeof(struct pyra_control))
65 return len;
66
67 return 0;
68} 58}
69 59
70static int pyra_receive_control_status(struct usb_device *usb_dev) 60static int pyra_receive_control_status(struct usb_device *usb_dev)
71{ 61{
72 int len; 62 int retval;
73 struct pyra_control control; 63 struct pyra_control control;
74 64
75 do { 65 do {
76 msleep(10); 66 msleep(10);
77 67 retval = roccat_common_receive(usb_dev, PYRA_USB_COMMAND_CONTROL,
78 len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), 68 &control, sizeof(struct pyra_control));
79 USB_REQ_CLEAR_FEATURE,
80 USB_TYPE_CLASS | USB_RECIP_INTERFACE |
81 USB_DIR_IN,
82 PYRA_USB_COMMAND_CONTROL, 0, (char *)&control,
83 sizeof(struct pyra_control),
84 USB_CTRL_SET_TIMEOUT);
85 69
86 /* requested too early, try again */ 70 /* requested too early, try again */
87 } while (len == -EPROTO); 71 } while (retval == -EPROTO);
88 72
89 if (len == sizeof(struct pyra_control) && 73 if (!retval && control.command == PYRA_COMMAND_CONTROL &&
90 control.command == PYRA_COMMAND_CONTROL &&
91 control.request == PYRA_CONTROL_REQUEST_STATUS && 74 control.request == PYRA_CONTROL_REQUEST_STATUS &&
92 control.value == 1) 75 control.value == 1)
93 return 0; 76 return 0;
94 else { 77 else {
95 hid_err(usb_dev, "receive control status: unknown response 0x%x 0x%x\n", 78 hid_err(usb_dev, "receive control status: unknown response 0x%x 0x%x\n",
96 control.request, control.value); 79 control.request, control.value);
97 return -EINVAL; 80 return retval ? retval : -EINVAL;
98 } 81 }
99} 82}
100 83
@@ -102,125 +85,72 @@ static int pyra_get_profile_settings(struct usb_device *usb_dev,
102 struct pyra_profile_settings *buf, int number) 85 struct pyra_profile_settings *buf, int number)
103{ 86{
104 int retval; 87 int retval;
105
106 retval = pyra_send_control(usb_dev, number, 88 retval = pyra_send_control(usb_dev, number,
107 PYRA_CONTROL_REQUEST_PROFILE_SETTINGS); 89 PYRA_CONTROL_REQUEST_PROFILE_SETTINGS);
108
109 if (retval) 90 if (retval)
110 return retval; 91 return retval;
111 92 return roccat_common_receive(usb_dev, PYRA_USB_COMMAND_PROFILE_SETTINGS,
112 retval = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), 93 buf, sizeof(struct pyra_profile_settings));
113 USB_REQ_CLEAR_FEATURE,
114 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
115 PYRA_USB_COMMAND_PROFILE_SETTINGS, 0, (char *)buf,
116 sizeof(struct pyra_profile_settings),
117 USB_CTRL_SET_TIMEOUT);
118
119 if (retval != sizeof(struct pyra_profile_settings))
120 return retval;
121
122 return 0;
123} 94}
124 95
125static int pyra_get_profile_buttons(struct usb_device *usb_dev, 96static int pyra_get_profile_buttons(struct usb_device *usb_dev,
126 struct pyra_profile_buttons *buf, int number) 97 struct pyra_profile_buttons *buf, int number)
127{ 98{
128 int retval; 99 int retval;
129
130 retval = pyra_send_control(usb_dev, number, 100 retval = pyra_send_control(usb_dev, number,
131 PYRA_CONTROL_REQUEST_PROFILE_BUTTONS); 101 PYRA_CONTROL_REQUEST_PROFILE_BUTTONS);
132
133 if (retval) 102 if (retval)
134 return retval; 103 return retval;
135 104 return roccat_common_receive(usb_dev, PYRA_USB_COMMAND_PROFILE_BUTTONS,
136 retval = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), 105 buf, sizeof(struct pyra_profile_buttons));
137 USB_REQ_CLEAR_FEATURE,
138 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
139 PYRA_USB_COMMAND_PROFILE_BUTTONS, 0, (char *)buf,
140 sizeof(struct pyra_profile_buttons),
141 USB_CTRL_SET_TIMEOUT);
142
143 if (retval != sizeof(struct pyra_profile_buttons))
144 return retval;
145
146 return 0;
147} 106}
148 107
149static int pyra_get_settings(struct usb_device *usb_dev, 108static int pyra_get_settings(struct usb_device *usb_dev,
150 struct pyra_settings *buf) 109 struct pyra_settings *buf)
151{ 110{
152 int len; 111 return roccat_common_receive(usb_dev, PYRA_USB_COMMAND_SETTINGS,
153 len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), 112 buf, sizeof(struct pyra_settings));
154 USB_REQ_CLEAR_FEATURE,
155 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
156 PYRA_USB_COMMAND_SETTINGS, 0, buf,
157 sizeof(struct pyra_settings), USB_CTRL_SET_TIMEOUT);
158 if (len != sizeof(struct pyra_settings))
159 return -EIO;
160 return 0;
161} 113}
162 114
163static int pyra_get_info(struct usb_device *usb_dev, struct pyra_info *buf) 115static int pyra_get_info(struct usb_device *usb_dev, struct pyra_info *buf)
164{ 116{
165 int len; 117 return roccat_common_receive(usb_dev, PYRA_USB_COMMAND_INFO,
166 len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), 118 buf, sizeof(struct pyra_info));
167 USB_REQ_CLEAR_FEATURE, 119}
168 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, 120
169 PYRA_USB_COMMAND_INFO, 0, buf, 121static int pyra_send(struct usb_device *usb_dev, uint command,
170 sizeof(struct pyra_info), USB_CTRL_SET_TIMEOUT); 122 void const *buf, uint size)
171 if (len != sizeof(struct pyra_info)) 123{
172 return -EIO; 124 int retval;
173 return 0; 125 retval = roccat_common_send(usb_dev, command, buf, size);
126 if (retval)
127 return retval;
128 return pyra_receive_control_status(usb_dev);
174} 129}
175 130
176static int pyra_set_profile_settings(struct usb_device *usb_dev, 131static int pyra_set_profile_settings(struct usb_device *usb_dev,
177 struct pyra_profile_settings const *settings) 132 struct pyra_profile_settings const *settings)
178{ 133{
179 int len; 134 return pyra_send(usb_dev, PYRA_USB_COMMAND_PROFILE_SETTINGS, settings,
180 len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), 135 sizeof(struct pyra_profile_settings));
181 USB_REQ_SET_CONFIGURATION,
182 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
183 PYRA_USB_COMMAND_PROFILE_SETTINGS, 0, (char *)settings,
184 sizeof(struct pyra_profile_settings),
185 USB_CTRL_SET_TIMEOUT);
186 if (len != sizeof(struct pyra_profile_settings))
187 return -EIO;
188 if (pyra_receive_control_status(usb_dev))
189 return -EIO;
190 return 0;
191} 136}
192 137
193static int pyra_set_profile_buttons(struct usb_device *usb_dev, 138static int pyra_set_profile_buttons(struct usb_device *usb_dev,
194 struct pyra_profile_buttons const *buttons) 139 struct pyra_profile_buttons const *buttons)
195{ 140{
196 int len; 141 return pyra_send(usb_dev, PYRA_USB_COMMAND_PROFILE_BUTTONS, buttons,
197 len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), 142 sizeof(struct pyra_profile_buttons));
198 USB_REQ_SET_CONFIGURATION,
199 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
200 PYRA_USB_COMMAND_PROFILE_BUTTONS, 0, (char *)buttons,
201 sizeof(struct pyra_profile_buttons),
202 USB_CTRL_SET_TIMEOUT);
203 if (len != sizeof(struct pyra_profile_buttons))
204 return -EIO;
205 if (pyra_receive_control_status(usb_dev))
206 return -EIO;
207 return 0;
208} 143}
209 144
210static int pyra_set_settings(struct usb_device *usb_dev, 145static int pyra_set_settings(struct usb_device *usb_dev,
211 struct pyra_settings const *settings) 146 struct pyra_settings const *settings)
212{ 147{
213 int len; 148 int retval;
214 len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), 149 retval = roccat_common_send(usb_dev, PYRA_USB_COMMAND_SETTINGS, settings,
215 USB_REQ_SET_CONFIGURATION, 150 sizeof(struct pyra_settings));
216 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, 151 if (retval)
217 PYRA_USB_COMMAND_SETTINGS, 0, (char *)settings, 152 return retval;
218 sizeof(struct pyra_settings), USB_CTRL_SET_TIMEOUT); 153 return pyra_receive_control_status(usb_dev);
219 if (len != sizeof(struct pyra_settings))
220 return -EIO;
221 if (pyra_receive_control_status(usb_dev))
222 return -EIO;
223 return 0;
224} 154}
225 155
226static ssize_t pyra_sysfs_read_profilex_settings(struct file *fp, 156static ssize_t pyra_sysfs_read_profilex_settings(struct file *fp,
@@ -521,21 +451,16 @@ static struct bin_attribute pyra_bin_attributes[] = {
521static int pyra_init_pyra_device_struct(struct usb_device *usb_dev, 451static int pyra_init_pyra_device_struct(struct usb_device *usb_dev,
522 struct pyra_device *pyra) 452 struct pyra_device *pyra)
523{ 453{
524 struct pyra_info *info; 454 struct pyra_info info;
525 int retval, i; 455 int retval, i;
526 456
527 mutex_init(&pyra->pyra_lock); 457 mutex_init(&pyra->pyra_lock);
528 458
529 info = kmalloc(sizeof(struct pyra_info), GFP_KERNEL); 459 retval = pyra_get_info(usb_dev, &info);
530 if (!info) 460 if (retval)
531 return -ENOMEM;
532 retval = pyra_get_info(usb_dev, info);
533 if (retval) {
534 kfree(info);
535 return retval; 461 return retval;
536 } 462
537 pyra->firmware_version = info->firmware_version; 463 pyra->firmware_version = info.firmware_version;
538 kfree(info);
539 464
540 retval = pyra_get_settings(usb_dev, &pyra->settings); 465 retval = pyra_get_settings(usb_dev, &pyra->settings);
541 if (retval) 466 if (retval)
@@ -581,7 +506,8 @@ static int pyra_init_specials(struct hid_device *hdev)
581 goto exit_free; 506 goto exit_free;
582 } 507 }
583 508
584 retval = roccat_connect(pyra_class, hdev); 509 retval = roccat_connect(pyra_class, hdev,
510 sizeof(struct pyra_roccat_report));
585 if (retval < 0) { 511 if (retval < 0) {
586 hid_err(hdev, "couldn't init char dev\n"); 512 hid_err(hdev, "couldn't init char dev\n");
587 } else { 513 } else {
@@ -685,8 +611,7 @@ static void pyra_report_to_chrdev(struct pyra_device const *pyra,
685 roccat_report.value = button_event->data1; 611 roccat_report.value = button_event->data1;
686 roccat_report.key = 0; 612 roccat_report.key = 0;
687 roccat_report_event(pyra->chrdev_minor, 613 roccat_report_event(pyra->chrdev_minor,
688 (uint8_t const *)&roccat_report, 614 (uint8_t const *)&roccat_report);
689 sizeof(struct pyra_roccat_report));
690 break; 615 break;
691 case PYRA_MOUSE_EVENT_BUTTON_TYPE_MACRO: 616 case PYRA_MOUSE_EVENT_BUTTON_TYPE_MACRO:
692 case PYRA_MOUSE_EVENT_BUTTON_TYPE_SHORTCUT: 617 case PYRA_MOUSE_EVENT_BUTTON_TYPE_SHORTCUT:
@@ -700,8 +625,7 @@ static void pyra_report_to_chrdev(struct pyra_device const *pyra,
700 */ 625 */
701 roccat_report.value = pyra->actual_profile + 1; 626 roccat_report.value = pyra->actual_profile + 1;
702 roccat_report_event(pyra->chrdev_minor, 627 roccat_report_event(pyra->chrdev_minor,
703 (uint8_t const *)&roccat_report, 628 (uint8_t const *)&roccat_report);
704 sizeof(struct pyra_roccat_report));
705 } 629 }
706 break; 630 break;
707 } 631 }
@@ -761,8 +685,8 @@ static int __init pyra_init(void)
761 685
762static void __exit pyra_exit(void) 686static void __exit pyra_exit(void)
763{ 687{
764 class_destroy(pyra_class);
765 hid_unregister_driver(&pyra_driver); 688 hid_unregister_driver(&pyra_driver);
689 class_destroy(pyra_class);
766} 690}
767 691
768module_init(pyra_init); 692module_init(pyra_init);
diff --git a/drivers/hid/hid-roccat.c b/drivers/hid/hid-roccat.c
index a14c579ea781..5666e7587b18 100644
--- a/drivers/hid/hid-roccat.c
+++ b/drivers/hid/hid-roccat.c
@@ -26,8 +26,7 @@
26#include <linux/cdev.h> 26#include <linux/cdev.h>
27#include <linux/poll.h> 27#include <linux/poll.h>
28#include <linux/sched.h> 28#include <linux/sched.h>
29 29#include <linux/hid-roccat.h>
30#include "hid-roccat.h"
31 30
32#define ROCCAT_FIRST_MINOR 0 31#define ROCCAT_FIRST_MINOR 0
33#define ROCCAT_MAX_DEVICES 8 32#define ROCCAT_MAX_DEVICES 8
@@ -37,11 +36,11 @@
37 36
38struct roccat_report { 37struct roccat_report {
39 uint8_t *value; 38 uint8_t *value;
40 int len;
41}; 39};
42 40
43struct roccat_device { 41struct roccat_device {
44 unsigned int minor; 42 unsigned int minor;
43 int report_size;
45 int open; 44 int open;
46 int exist; 45 int exist;
47 wait_queue_head_t wait; 46 wait_queue_head_t wait;
@@ -123,7 +122,7 @@ static ssize_t roccat_read(struct file *file, char __user *buffer,
123 * 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
124 * is lost! 123 * is lost!
125 */ 124 */
126 len = report->len > count ? count : report->len; 125 len = device->report_size > count ? count : device->report_size;
127 126
128 if (copy_to_user(buffer, report->value, len)) { 127 if (copy_to_user(buffer, report->value, len)) {
129 retval = -EFAULT; 128 retval = -EFAULT;
@@ -248,26 +247,25 @@ static int roccat_release(struct inode *inode, struct file *file)
248 * 247 *
249 * This is called from interrupt handler. 248 * This is called from interrupt handler.
250 */ 249 */
251int roccat_report_event(int minor, u8 const *data, int len) 250int roccat_report_event(int minor, u8 const *data)
252{ 251{
253 struct roccat_device *device; 252 struct roccat_device *device;
254 struct roccat_reader *reader; 253 struct roccat_reader *reader;
255 struct roccat_report *report; 254 struct roccat_report *report;
256 uint8_t *new_value; 255 uint8_t *new_value;
257 256
258 new_value = kmemdup(data, len, GFP_ATOMIC); 257 device = devices[minor];
258
259 new_value = kmemdup(data, device->report_size, GFP_ATOMIC);
259 if (!new_value) 260 if (!new_value)
260 return -ENOMEM; 261 return -ENOMEM;
261 262
262 device = devices[minor];
263
264 report = &device->cbuf[device->cbuf_end]; 263 report = &device->cbuf[device->cbuf_end];
265 264
266 /* passing NULL is safe */ 265 /* passing NULL is safe */
267 kfree(report->value); 266 kfree(report->value);
268 267
269 report->value = new_value; 268 report->value = new_value;
270 report->len = len;
271 device->cbuf_end = (device->cbuf_end + 1) % ROCCAT_CBUF_SIZE; 269 device->cbuf_end = (device->cbuf_end + 1) % ROCCAT_CBUF_SIZE;
272 270
273 list_for_each_entry(reader, &device->readers, node) { 271 list_for_each_entry(reader, &device->readers, node) {
@@ -295,7 +293,7 @@ EXPORT_SYMBOL_GPL(roccat_report_event);
295 * 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
296 * success, a negative error code on failure. 294 * success, a negative error code on failure.
297 */ 295 */
298int roccat_connect(struct class *klass, struct hid_device *hid) 296int roccat_connect(struct class *klass, struct hid_device *hid, int report_size)
299{ 297{
300 unsigned int minor; 298 unsigned int minor;
301 struct roccat_device *device; 299 struct roccat_device *device;
@@ -343,6 +341,7 @@ int roccat_connect(struct class *klass, struct hid_device *hid)
343 device->hid = hid; 341 device->hid = hid;
344 device->exist = 1; 342 device->exist = 1;
345 device->cbuf_end = 0; 343 device->cbuf_end = 0;
344 device->report_size = report_size;
346 345
347 return minor; 346 return minor;
348} 347}
@@ -357,13 +356,16 @@ void roccat_disconnect(int minor)
357 356
358 mutex_lock(&devices_lock); 357 mutex_lock(&devices_lock);
359 device = devices[minor]; 358 device = devices[minor];
360 devices[minor] = NULL;
361 mutex_unlock(&devices_lock); 359 mutex_unlock(&devices_lock);
362 360
363 device->exist = 0; /* TODO exist maybe not needed */ 361 device->exist = 0; /* TODO exist maybe not needed */
364 362
365 device_destroy(device->dev->class, MKDEV(roccat_major, minor)); 363 device_destroy(device->dev->class, MKDEV(roccat_major, minor));
366 364
365 mutex_lock(&devices_lock);
366 devices[minor] = NULL;
367 mutex_unlock(&devices_lock);
368
367 if (device->open) { 369 if (device->open) {
368 hid_hw_close(device->hid); 370 hid_hw_close(device->hid);
369 wake_up_interruptible(&device->wait); 371 wake_up_interruptible(&device->wait);
@@ -373,6 +375,34 @@ void roccat_disconnect(int minor)
373} 375}
374EXPORT_SYMBOL_GPL(roccat_disconnect); 376EXPORT_SYMBOL_GPL(roccat_disconnect);
375 377
378static 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 }
401out:
402 mutex_unlock(&devices_lock);
403 return retval;
404}
405
376static const struct file_operations roccat_ops = { 406static const struct file_operations roccat_ops = {
377 .owner = THIS_MODULE, 407 .owner = THIS_MODULE,
378 .read = roccat_read, 408 .read = roccat_read,
@@ -380,6 +410,7 @@ static const struct file_operations roccat_ops = {
380 .open = roccat_open, 410 .open = roccat_open,
381 .release = roccat_release, 411 .release = roccat_release,
382 .llseek = noop_llseek, 412 .llseek = noop_llseek,
413 .unlocked_ioctl = roccat_ioctl,
383}; 414};
384 415
385static int __init roccat_init(void) 416static int __init roccat_init(void)
diff --git a/drivers/hid/hid-roccat.h b/drivers/hid/hid-roccat.h
deleted file mode 100644
index 5784281d613f..000000000000
--- a/drivers/hid/hid-roccat.h
+++ /dev/null
@@ -1,32 +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)
19int roccat_connect(struct class *klass, struct hid_device *hid);
20void roccat_disconnect(int minor);
21int roccat_report_event(int minor, u8 const *data, int len);
22#else
23static inline int roccat_connect(struct class *klass,
24 struct hid_device *hid) { return -1; }
25static inline void roccat_disconnect(int minor) {}
26static inline int roccat_report_event(int minor, u8 const *data, int len)
27{
28 return 0;
29}
30#endif
31
32#endif
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index 66fbcbae5343..54409cba018c 100644
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -102,15 +102,14 @@ out:
102} 102}
103 103
104/* the first byte is expected to be a report number */ 104/* the first byte is expected to be a report number */
105static 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 */
106static ssize_t hidraw_send_report(struct file *file, const char __user *buffer, size_t count, unsigned char report_type)
106{ 107{
107 unsigned int minor = iminor(file->f_path.dentry->d_inode); 108 unsigned int minor = iminor(file->f_path.dentry->d_inode);
108 struct hid_device *dev; 109 struct hid_device *dev;
109 __u8 *buf; 110 __u8 *buf;
110 int ret = 0; 111 int ret = 0;
111 112
112 mutex_lock(&minors_lock);
113
114 if (!hidraw_table[minor]) { 113 if (!hidraw_table[minor]) {
115 ret = -ENODEV; 114 ret = -ENODEV;
116 goto out; 115 goto out;
@@ -148,14 +147,92 @@ static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t
148 goto out_free; 147 goto out_free;
149 } 148 }
150 149
151 ret = dev->hid_output_raw_report(dev, buf, count, HID_OUTPUT_REPORT); 150 ret = dev->hid_output_raw_report(dev, buf, count, report_type);
152out_free: 151out_free:
153 kfree(buf); 152 kfree(buf);
154out: 153out:
154 return ret;
155}
156
157/* the first byte is expected to be a report number */
158static 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);
155 mutex_unlock(&minors_lock); 163 mutex_unlock(&minors_lock);
156 return ret; 164 return ret;
157} 165}
158 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. */
174static 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) {
190 printk(KERN_WARNING "hidraw: pid %d passed too large report\n",
191 task_pid_nr(current));
192 ret = -EINVAL;
193 goto out;
194 }
195
196 if (count < 2) {
197 printk(KERN_WARNING "hidraw: pid %d passed too short report\n",
198 task_pid_nr(current));
199 ret = -EINVAL;
200 goto out;
201 }
202
203 buf = kmalloc(count * sizeof(__u8), GFP_KERNEL);
204 if (!buf) {
205 ret = -ENOMEM;
206 goto out;
207 }
208
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)) {
224 ret = -EFAULT;
225 goto out_free;
226 }
227
228 ret = len;
229
230out_free:
231 kfree(buf);
232out:
233 return ret;
234}
235
159static unsigned int hidraw_poll(struct file *file, poll_table *wait) 236static unsigned int hidraw_poll(struct file *file, poll_table *wait)
160{ 237{
161 struct hidraw_list *list = file->private_data; 238 struct hidraw_list *list = file->private_data;
@@ -295,7 +372,24 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd,
295 default: 372 default:
296 { 373 {
297 struct hid_device *hid = dev->hid; 374 struct hid_device *hid = dev->hid;
298 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) {
299 ret = -EINVAL; 393 ret = -EINVAL;
300 break; 394 break;
301 } 395 }
@@ -327,7 +421,7 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd,
327 -EFAULT : len; 421 -EFAULT : len;
328 break; 422 break;
329 } 423 }
330 } 424 }
331 425
332 ret = -ENOTTY; 426 ret = -ENOTTY;
333 } 427 }
@@ -428,12 +522,12 @@ void hidraw_disconnect(struct hid_device *hid)
428 522
429 hidraw->exist = 0; 523 hidraw->exist = 0;
430 524
525 device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor));
526
431 mutex_lock(&minors_lock); 527 mutex_lock(&minors_lock);
432 hidraw_table[hidraw->minor] = NULL; 528 hidraw_table[hidraw->minor] = NULL;
433 mutex_unlock(&minors_lock); 529 mutex_unlock(&minors_lock);
434 530
435 device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor));
436
437 if (hidraw->open) { 531 if (hidraw->open) {
438 hid_hw_close(hid); 532 hid_hw_close(hid);
439 wake_up_interruptible(&hidraw->wait); 533 wake_up_interruptible(&hidraw->wait);
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index b336dd84036f..38c261a40c74 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -799,6 +799,40 @@ static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid)
799 return 0; 799 return 0;
800} 800}
801 801
802static 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
802static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t count, 836static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t count,
803 unsigned char report_type) 837 unsigned char report_type)
804{ 838{
@@ -1139,6 +1173,7 @@ static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id *
1139 1173
1140 usb_set_intfdata(intf, hid); 1174 usb_set_intfdata(intf, hid);
1141 hid->ll_driver = &usb_hid_driver; 1175 hid->ll_driver = &usb_hid_driver;
1176 hid->hid_get_raw_report = usbhid_get_raw_report;
1142 hid->hid_output_raw_report = usbhid_output_raw_report; 1177 hid->hid_output_raw_report = usbhid_output_raw_report;
1143 hid->ff_init = hid_pidff_init; 1178 hid->ff_init = hid_pidff_init;
1144#ifdef CONFIG_USB_HIDDEV 1179#ifdef CONFIG_USB_HIDDEV