diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-04-30 11:58:21 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-04-30 11:58:21 -0400 |
commit | d6454706c382ab74e2ecad7803c434cc6bd30343 (patch) | |
tree | 2a380b28eb948d114c491f0b6799c10406030849 /drivers/hid | |
parent | 152a6a9da1bd3ed5dcbbf6ff17c7ebde0eb9a754 (diff) | |
parent | 11941a321d49cd2cafc8e64f66cbfed60fc1c691 (diff) |
Merge branch 'for-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jikos/hid
* 'for-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jikos/hid: (21 commits)
USB HID: don't warn on idVendor == 0
USB HID: add 'quirks' module parameter
USB HID: add support for dynamically-created quirks
USB HID: clarify static quirk handling as squirks
USB HID: encapsulate quirk handling into hid-quirks.c
USB HID: EMS USBII device needs HID_QUIRK_MULTI_INPUT
HID: update copyright and authorship macro
HID: introduce proper zeroing of unused bits in output reports
USB HID: add support for WiseGroup MP-8800 Quad Joypad
USB HID: add FF support for Logitech Force 3D Pro Joystick
USB HID: numlock quirk for dell W7658 keyboard
USB HID: Logitech MX3000 keyboard needs report descriptor quirk
USB HID: extend quirk for Logitech S510 keyboard
USB HID: usbkbd/usbmouse - handle errors when registering devices
USB HID: add QUIRK_HIDDEV for Belkin Flip KVM
HID: enable dead keys on a belkin wireless keyboard
USB HID: Thustmaster firestorm dual power v1 support
USB HID: specify explicit size for hid_blacklist.quirks
USB HID: fix retry & reset logic
USB HID: consolidate vendor/product ids
...
Diffstat (limited to 'drivers/hid')
-rw-r--r-- | drivers/hid/Kconfig | 2 | ||||
-rw-r--r-- | drivers/hid/Makefile | 4 | ||||
-rw-r--r-- | drivers/hid/hid-core.c | 9 | ||||
-rw-r--r-- | drivers/hid/hid-input.c | 27 | ||||
-rw-r--r-- | drivers/hid/usbhid/Kconfig | 149 | ||||
-rw-r--r-- | drivers/hid/usbhid/Makefile | 35 | ||||
-rw-r--r-- | drivers/hid/usbhid/hid-core.c | 1114 | ||||
-rw-r--r-- | drivers/hid/usbhid/hid-ff.c | 91 | ||||
-rw-r--r-- | drivers/hid/usbhid/hid-lgff.c | 151 | ||||
-rw-r--r-- | drivers/hid/usbhid/hid-pidff.c | 1331 | ||||
-rw-r--r-- | drivers/hid/usbhid/hid-plff.c | 129 | ||||
-rw-r--r-- | drivers/hid/usbhid/hid-quirks.c | 681 | ||||
-rw-r--r-- | drivers/hid/usbhid/hid-tmff.c | 147 | ||||
-rw-r--r-- | drivers/hid/usbhid/hid-zpff.c | 111 | ||||
-rw-r--r-- | drivers/hid/usbhid/hiddev.c | 847 | ||||
-rw-r--r-- | drivers/hid/usbhid/usbhid.h | 87 | ||||
-rw-r--r-- | drivers/hid/usbhid/usbkbd.c | 367 | ||||
-rw-r--r-- | drivers/hid/usbhid/usbmouse.c | 252 |
18 files changed, 5531 insertions, 3 deletions
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 850788f4dd2e..8fbe9fdac128 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig | |||
@@ -36,5 +36,7 @@ config HID_DEBUG | |||
36 | 36 | ||
37 | If unsure, say N | 37 | If unsure, say N |
38 | 38 | ||
39 | source "drivers/hid/usbhid/Kconfig" | ||
40 | |||
39 | endmenu | 41 | endmenu |
40 | 42 | ||
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index 52e97d8f3c95..68d1376a53fb 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile | |||
@@ -6,3 +6,7 @@ hid-objs := hid-core.o hid-input.o | |||
6 | obj-$(CONFIG_HID) += hid.o | 6 | obj-$(CONFIG_HID) += hid.o |
7 | hid-$(CONFIG_HID_DEBUG) += hid-debug.o | 7 | hid-$(CONFIG_HID_DEBUG) += hid-debug.o |
8 | 8 | ||
9 | obj-$(CONFIG_USB_HID) += usbhid/ | ||
10 | obj-$(CONFIG_USB_MOUSE) += usbhid/ | ||
11 | obj-$(CONFIG_USB_KBD) += usbhid/ | ||
12 | |||
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 1cca32f46947..62e21cc73938 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * Copyright (c) 1999 Andreas Gal | 4 | * Copyright (c) 1999 Andreas Gal |
5 | * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> | 5 | * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> |
6 | * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc | 6 | * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc |
7 | * Copyright (c) 2006 Jiri Kosina | 7 | * Copyright (c) 2006-2007 Jiri Kosina |
8 | */ | 8 | */ |
9 | 9 | ||
10 | /* | 10 | /* |
@@ -37,7 +37,7 @@ | |||
37 | */ | 37 | */ |
38 | 38 | ||
39 | #define DRIVER_VERSION "v2.6" | 39 | #define DRIVER_VERSION "v2.6" |
40 | #define DRIVER_AUTHOR "Andreas Gal, Vojtech Pavlik" | 40 | #define DRIVER_AUTHOR "Andreas Gal, Vojtech Pavlik, Jiri Kosina" |
41 | #define DRIVER_DESC "HID core driver" | 41 | #define DRIVER_DESC "HID core driver" |
42 | #define DRIVER_LICENSE "GPL" | 42 | #define DRIVER_LICENSE "GPL" |
43 | 43 | ||
@@ -872,8 +872,13 @@ static void hid_output_field(struct hid_field *field, __u8 *data) | |||
872 | unsigned count = field->report_count; | 872 | unsigned count = field->report_count; |
873 | unsigned offset = field->report_offset; | 873 | unsigned offset = field->report_offset; |
874 | unsigned size = field->report_size; | 874 | unsigned size = field->report_size; |
875 | unsigned bitsused = offset + count * size; | ||
875 | unsigned n; | 876 | unsigned n; |
876 | 877 | ||
878 | /* make sure the unused bits in the last byte are zeros */ | ||
879 | if (count > 0 && size > 0 && (bitsused % 8) != 0) | ||
880 | data[(bitsused-1)/8] &= (1 << (bitsused % 8)) - 1; | ||
881 | |||
877 | for (n = 0; n < count; n++) { | 882 | for (n = 0; n < count; n++) { |
878 | if (field->logical_minimum < 0) /* signed values */ | 883 | if (field->logical_minimum < 0) /* signed values */ |
879 | implement(data, offset + n * size, size, s32ton(field->value[n], size)); | 884 | implement(data, offset + n * size, size, s32ton(field->value[n], size)); |
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index c8434023ba65..a19b65ed3119 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c | |||
@@ -431,6 +431,15 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
431 | case 0x000: goto ignore; | 431 | case 0x000: goto ignore; |
432 | case 0x034: map_key_clear(KEY_SLEEP); break; | 432 | case 0x034: map_key_clear(KEY_SLEEP); break; |
433 | case 0x036: map_key_clear(BTN_MISC); break; | 433 | case 0x036: map_key_clear(BTN_MISC); break; |
434 | /* | ||
435 | * The next three are reported by Belkin wireless | ||
436 | * keyboard (1020:0006). These values are "reserved" | ||
437 | * in HUT 1.12. | ||
438 | */ | ||
439 | case 0x03a: map_key_clear(KEY_SOUND); break; | ||
440 | case 0x03b: map_key_clear(KEY_CAMERA); break; | ||
441 | case 0x03c: map_key_clear(KEY_DOCUMENTS); break; | ||
442 | |||
434 | case 0x040: map_key_clear(KEY_MENU); break; | 443 | case 0x040: map_key_clear(KEY_MENU); break; |
435 | case 0x045: map_key_clear(KEY_RADIO); break; | 444 | case 0x045: map_key_clear(KEY_RADIO); break; |
436 | 445 | ||
@@ -531,10 +540,26 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
531 | case 0x302: map_key_clear(KEY_PROG2); break; | 540 | case 0x302: map_key_clear(KEY_PROG2); break; |
532 | case 0x303: map_key_clear(KEY_PROG3); break; | 541 | case 0x303: map_key_clear(KEY_PROG3); break; |
533 | 542 | ||
534 | /* Reported on Logitech S510 wireless keyboard */ | 543 | /* Reported on certain Logitech wireless keyboards */ |
544 | case 0x1001: map_key_clear(KEY_MESSENGER); break; | ||
545 | case 0x1003: map_key_clear(KEY_SOUND); break; | ||
546 | case 0x1004: map_key_clear(KEY_VIDEO); break; | ||
547 | case 0x1005: map_key_clear(KEY_AUDIO); break; | ||
548 | case 0x100a: map_key_clear(KEY_DOCUMENTS); break; | ||
549 | case 0x1011: map_key_clear(KEY_PREVIOUSSONG); break; | ||
550 | case 0x1012: map_key_clear(KEY_NEXTSONG); break; | ||
551 | case 0x1013: map_key_clear(KEY_CAMERA); break; | ||
552 | case 0x1014: map_key_clear(KEY_MESSENGER); break; | ||
553 | case 0x1015: map_key_clear(KEY_RECORD); break; | ||
554 | case 0x1016: map_key_clear(KEY_PLAYER); break; | ||
555 | case 0x1017: map_key_clear(KEY_EJECTCD); break; | ||
556 | case 0x1019: map_key_clear(KEY_PROG1); break; | ||
557 | case 0x101a: map_key_clear(KEY_PROG2); break; | ||
558 | case 0x101b: map_key_clear(KEY_PROG3); break; | ||
535 | case 0x101f: map_key_clear(KEY_ZOOMIN); break; | 559 | case 0x101f: map_key_clear(KEY_ZOOMIN); break; |
536 | case 0x1020: map_key_clear(KEY_ZOOMOUT); break; | 560 | case 0x1020: map_key_clear(KEY_ZOOMOUT); break; |
537 | case 0x1021: map_key_clear(KEY_ZOOMRESET); break; | 561 | case 0x1021: map_key_clear(KEY_ZOOMRESET); break; |
562 | case 0x1023: map_key_clear(KEY_CLOSE); break; | ||
538 | /* this one is marked as 'Rotate' */ | 563 | /* this one is marked as 'Rotate' */ |
539 | case 0x1028: map_key_clear(KEY_ANGLE); break; | 564 | case 0x1028: map_key_clear(KEY_ANGLE); break; |
540 | case 0x1029: map_key_clear(KEY_SHUFFLE); break; | 565 | case 0x1029: map_key_clear(KEY_SHUFFLE); break; |
diff --git a/drivers/hid/usbhid/Kconfig b/drivers/hid/usbhid/Kconfig new file mode 100644 index 000000000000..7c87bdc538bc --- /dev/null +++ b/drivers/hid/usbhid/Kconfig | |||
@@ -0,0 +1,149 @@ | |||
1 | comment "USB Input Devices" | ||
2 | depends on USB | ||
3 | |||
4 | config USB_HID | ||
5 | tristate "USB Human Interface Device (full HID) support" | ||
6 | default y | ||
7 | depends on USB && INPUT | ||
8 | select HID | ||
9 | ---help--- | ||
10 | Say Y here if you want full HID support to connect USB keyboards, | ||
11 | mice, joysticks, graphic tablets, or any other HID based devices | ||
12 | to your computer via USB, as well as Uninterruptible Power Supply | ||
13 | (UPS) and monitor control devices. | ||
14 | |||
15 | You can't use this driver and the HIDBP (Boot Protocol) keyboard | ||
16 | and mouse drivers at the same time. More information is available: | ||
17 | <file:Documentation/input/input.txt>. | ||
18 | |||
19 | If unsure, say Y. | ||
20 | |||
21 | To compile this driver as a module, choose M here: the | ||
22 | module will be called usbhid. | ||
23 | |||
24 | comment "Input core support is needed for USB HID input layer or HIDBP support" | ||
25 | depends on USB_HID && INPUT=n | ||
26 | |||
27 | config USB_HIDINPUT_POWERBOOK | ||
28 | bool "Enable support for iBook/PowerBook special keys" | ||
29 | default n | ||
30 | depends on USB_HID | ||
31 | help | ||
32 | Say Y here if you want support for the special keys (Fn, Numlock) on | ||
33 | Apple iBooks and PowerBooks. | ||
34 | |||
35 | If unsure, say N. | ||
36 | |||
37 | config HID_FF | ||
38 | bool "Force feedback support (EXPERIMENTAL)" | ||
39 | depends on USB_HID && EXPERIMENTAL | ||
40 | help | ||
41 | Say Y here is you want force feedback support for a few HID devices. | ||
42 | See below for a list of supported devices. | ||
43 | |||
44 | See <file:Documentation/input/ff.txt> for a description of the force | ||
45 | feedback API. | ||
46 | |||
47 | If unsure, say N. | ||
48 | |||
49 | config HID_PID | ||
50 | bool "PID device support" | ||
51 | depends on HID_FF | ||
52 | help | ||
53 | Say Y here if you have a PID-compliant device and wish to enable force | ||
54 | feedback for it. Microsoft Sidewinder Force Feedback 2 is one of such | ||
55 | devices. | ||
56 | |||
57 | config LOGITECH_FF | ||
58 | bool "Logitech devices support" | ||
59 | depends on HID_FF | ||
60 | select INPUT_FF_MEMLESS if USB_HID | ||
61 | help | ||
62 | Say Y here if you have one of these devices: | ||
63 | - Logitech WingMan Cordless RumblePad | ||
64 | - Logitech WingMan Cordless RumblePad 2 | ||
65 | - Logitech WingMan Force 3D | ||
66 | - Logitech Formula Force EX | ||
67 | - Logitech MOMO Force wheel | ||
68 | |||
69 | and if you want to enable force feedback for them. | ||
70 | Note: if you say N here, this device will still be supported, but without | ||
71 | force feedback. | ||
72 | |||
73 | config PANTHERLORD_FF | ||
74 | bool "PantherLord USB/PS2 2in1 Adapter support" | ||
75 | depends on HID_FF | ||
76 | select INPUT_FF_MEMLESS if USB_HID | ||
77 | help | ||
78 | Say Y here if you have a PantherLord USB/PS2 2in1 Adapter and want | ||
79 | to enable force feedback support for it. | ||
80 | |||
81 | config THRUSTMASTER_FF | ||
82 | bool "ThrustMaster FireStorm Dual Power 2 support (EXPERIMENTAL)" | ||
83 | depends on HID_FF && EXPERIMENTAL | ||
84 | select INPUT_FF_MEMLESS if USB_HID | ||
85 | help | ||
86 | Say Y here if you have a THRUSTMASTER FireStore Dual Power 2, | ||
87 | and want to enable force feedback support for it. | ||
88 | Note: if you say N here, this device will still be supported, but without | ||
89 | force feedback. | ||
90 | |||
91 | config ZEROPLUS_FF | ||
92 | bool "Zeroplus based game controller support" | ||
93 | depends on HID_FF | ||
94 | select INPUT_FF_MEMLESS if USB_HID | ||
95 | help | ||
96 | Say Y here if you have a Zeroplus based game controller and want to | ||
97 | enable force feedback for it. | ||
98 | |||
99 | config USB_HIDDEV | ||
100 | bool "/dev/hiddev raw HID device support" | ||
101 | depends on USB_HID | ||
102 | help | ||
103 | Say Y here if you want to support HID devices (from the USB | ||
104 | specification standpoint) that aren't strictly user interface | ||
105 | devices, like monitor controls and Uninterruptable Power Supplies. | ||
106 | |||
107 | This module supports these devices separately using a separate | ||
108 | event interface on /dev/usb/hiddevX (char 180:96 to 180:111). | ||
109 | |||
110 | If unsure, say Y. | ||
111 | |||
112 | menu "USB HID Boot Protocol drivers" | ||
113 | depends on USB!=n && USB_HID!=y | ||
114 | |||
115 | config USB_KBD | ||
116 | tristate "USB HIDBP Keyboard (simple Boot) support" | ||
117 | depends on USB && INPUT | ||
118 | ---help--- | ||
119 | Say Y here only if you are absolutely sure that you don't want | ||
120 | to use the generic HID driver for your USB keyboard and prefer | ||
121 | to use the keyboard in its limited Boot Protocol mode instead. | ||
122 | |||
123 | This is almost certainly not what you want. This is mostly | ||
124 | useful for embedded applications or simple keyboards. | ||
125 | |||
126 | To compile this driver as a module, choose M here: the | ||
127 | module will be called usbkbd. | ||
128 | |||
129 | If even remotely unsure, say N. | ||
130 | |||
131 | config USB_MOUSE | ||
132 | tristate "USB HIDBP Mouse (simple Boot) support" | ||
133 | depends on USB && INPUT | ||
134 | ---help--- | ||
135 | Say Y here only if you are absolutely sure that you don't want | ||
136 | to use the generic HID driver for your USB mouse and prefer | ||
137 | to use the mouse in its limited Boot Protocol mode instead. | ||
138 | |||
139 | This is almost certainly not what you want. This is mostly | ||
140 | useful for embedded applications or simple mice. | ||
141 | |||
142 | To compile this driver as a module, choose M here: the | ||
143 | module will be called usbmouse. | ||
144 | |||
145 | If even remotely unsure, say N. | ||
146 | |||
147 | endmenu | ||
148 | |||
149 | |||
diff --git a/drivers/hid/usbhid/Makefile b/drivers/hid/usbhid/Makefile new file mode 100644 index 000000000000..8e6ab5b164a2 --- /dev/null +++ b/drivers/hid/usbhid/Makefile | |||
@@ -0,0 +1,35 @@ | |||
1 | # | ||
2 | # Makefile for the USB input drivers | ||
3 | # | ||
4 | |||
5 | # Multipart objects. | ||
6 | usbhid-objs := hid-core.o hid-quirks.o | ||
7 | |||
8 | # Optional parts of multipart objects. | ||
9 | |||
10 | ifeq ($(CONFIG_USB_HIDDEV),y) | ||
11 | usbhid-objs += hiddev.o | ||
12 | endif | ||
13 | ifeq ($(CONFIG_HID_PID),y) | ||
14 | usbhid-objs += hid-pidff.o | ||
15 | endif | ||
16 | ifeq ($(CONFIG_LOGITECH_FF),y) | ||
17 | usbhid-objs += hid-lgff.o | ||
18 | endif | ||
19 | ifeq ($(CONFIG_PANTHERLORD_FF),y) | ||
20 | usbhid-objs += hid-plff.o | ||
21 | endif | ||
22 | ifeq ($(CONFIG_THRUSTMASTER_FF),y) | ||
23 | usbhid-objs += hid-tmff.o | ||
24 | endif | ||
25 | ifeq ($(CONFIG_ZEROPLUS_FF),y) | ||
26 | usbhid-objs += hid-zpff.o | ||
27 | endif | ||
28 | ifeq ($(CONFIG_HID_FF),y) | ||
29 | usbhid-objs += hid-ff.o | ||
30 | endif | ||
31 | |||
32 | obj-$(CONFIG_USB_HID) += usbhid.o | ||
33 | obj-$(CONFIG_USB_KBD) += usbkbd.o | ||
34 | obj-$(CONFIG_USB_MOUSE) += usbmouse.o | ||
35 | |||
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c new file mode 100644 index 000000000000..91d610358d57 --- /dev/null +++ b/drivers/hid/usbhid/hid-core.c | |||
@@ -0,0 +1,1114 @@ | |||
1 | /* | ||
2 | * USB HID support for Linux | ||
3 | * | ||
4 | * Copyright (c) 1999 Andreas Gal | ||
5 | * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> | ||
6 | * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc | ||
7 | * Copyright (c) 2006-2007 Jiri Kosina | ||
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/module.h> | ||
18 | #include <linux/slab.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/list.h> | ||
22 | #include <linux/mm.h> | ||
23 | #include <linux/smp_lock.h> | ||
24 | #include <linux/spinlock.h> | ||
25 | #include <asm/unaligned.h> | ||
26 | #include <asm/byteorder.h> | ||
27 | #include <linux/input.h> | ||
28 | #include <linux/wait.h> | ||
29 | |||
30 | #include <linux/usb.h> | ||
31 | |||
32 | #include <linux/hid.h> | ||
33 | #include <linux/hiddev.h> | ||
34 | #include <linux/hid-debug.h> | ||
35 | #include "usbhid.h" | ||
36 | |||
37 | /* | ||
38 | * Version Information | ||
39 | */ | ||
40 | |||
41 | #define DRIVER_VERSION "v2.6" | ||
42 | #define DRIVER_AUTHOR "Andreas Gal, Vojtech Pavlik, Jiri Kosina" | ||
43 | #define DRIVER_DESC "USB HID core driver" | ||
44 | #define DRIVER_LICENSE "GPL" | ||
45 | |||
46 | static char *hid_types[] = {"Device", "Pointer", "Mouse", "Device", "Joystick", | ||
47 | "Gamepad", "Keyboard", "Keypad", "Multi-Axis Controller"}; | ||
48 | /* | ||
49 | * Module parameters. | ||
50 | */ | ||
51 | |||
52 | static unsigned int hid_mousepoll_interval; | ||
53 | module_param_named(mousepoll, hid_mousepoll_interval, uint, 0644); | ||
54 | MODULE_PARM_DESC(mousepoll, "Polling interval of mice"); | ||
55 | |||
56 | /* Quirks specified at module load time */ | ||
57 | static char *quirks_param[MAX_USBHID_BOOT_QUIRKS] = { [ 0 ... (MAX_USBHID_BOOT_QUIRKS - 1) ] = NULL }; | ||
58 | module_param_array_named(quirks, quirks_param, charp, NULL, 0444); | ||
59 | MODULE_PARM_DESC(quirks, "Add/modify USB HID quirks by specifying " | ||
60 | " quirks=vendorID:productID:quirks" | ||
61 | " where vendorID, productID, and quirks are all in" | ||
62 | " 0x-prefixed hex"); | ||
63 | /* | ||
64 | * Input submission and I/O error handler. | ||
65 | */ | ||
66 | |||
67 | static void hid_io_error(struct hid_device *hid); | ||
68 | |||
69 | /* Start up the input URB */ | ||
70 | static int hid_start_in(struct hid_device *hid) | ||
71 | { | ||
72 | unsigned long flags; | ||
73 | int rc = 0; | ||
74 | struct usbhid_device *usbhid = hid->driver_data; | ||
75 | |||
76 | spin_lock_irqsave(&usbhid->inlock, flags); | ||
77 | if (hid->open > 0 && !test_bit(HID_SUSPENDED, &usbhid->iofl) && | ||
78 | !test_and_set_bit(HID_IN_RUNNING, &usbhid->iofl)) { | ||
79 | rc = usb_submit_urb(usbhid->urbin, GFP_ATOMIC); | ||
80 | if (rc != 0) | ||
81 | clear_bit(HID_IN_RUNNING, &usbhid->iofl); | ||
82 | } | ||
83 | spin_unlock_irqrestore(&usbhid->inlock, flags); | ||
84 | return rc; | ||
85 | } | ||
86 | |||
87 | /* I/O retry timer routine */ | ||
88 | static void hid_retry_timeout(unsigned long _hid) | ||
89 | { | ||
90 | struct hid_device *hid = (struct hid_device *) _hid; | ||
91 | struct usbhid_device *usbhid = hid->driver_data; | ||
92 | |||
93 | dev_dbg(&usbhid->intf->dev, "retrying intr urb\n"); | ||
94 | if (hid_start_in(hid)) | ||
95 | hid_io_error(hid); | ||
96 | } | ||
97 | |||
98 | /* Workqueue routine to reset the device or clear a halt */ | ||
99 | static void hid_reset(struct work_struct *work) | ||
100 | { | ||
101 | struct usbhid_device *usbhid = | ||
102 | container_of(work, struct usbhid_device, reset_work); | ||
103 | struct hid_device *hid = usbhid->hid; | ||
104 | int rc_lock, rc = 0; | ||
105 | |||
106 | if (test_bit(HID_CLEAR_HALT, &usbhid->iofl)) { | ||
107 | dev_dbg(&usbhid->intf->dev, "clear halt\n"); | ||
108 | rc = usb_clear_halt(hid_to_usb_dev(hid), usbhid->urbin->pipe); | ||
109 | clear_bit(HID_CLEAR_HALT, &usbhid->iofl); | ||
110 | hid_start_in(hid); | ||
111 | } | ||
112 | |||
113 | else if (test_bit(HID_RESET_PENDING, &usbhid->iofl)) { | ||
114 | dev_dbg(&usbhid->intf->dev, "resetting device\n"); | ||
115 | rc = rc_lock = usb_lock_device_for_reset(hid_to_usb_dev(hid), usbhid->intf); | ||
116 | if (rc_lock >= 0) { | ||
117 | rc = usb_reset_composite_device(hid_to_usb_dev(hid), usbhid->intf); | ||
118 | if (rc_lock) | ||
119 | usb_unlock_device(hid_to_usb_dev(hid)); | ||
120 | } | ||
121 | clear_bit(HID_RESET_PENDING, &usbhid->iofl); | ||
122 | } | ||
123 | |||
124 | switch (rc) { | ||
125 | case 0: | ||
126 | if (!test_bit(HID_IN_RUNNING, &usbhid->iofl)) | ||
127 | hid_io_error(hid); | ||
128 | break; | ||
129 | default: | ||
130 | err("can't reset device, %s-%s/input%d, status %d", | ||
131 | hid_to_usb_dev(hid)->bus->bus_name, | ||
132 | hid_to_usb_dev(hid)->devpath, | ||
133 | usbhid->ifnum, rc); | ||
134 | /* FALLTHROUGH */ | ||
135 | case -EHOSTUNREACH: | ||
136 | case -ENODEV: | ||
137 | case -EINTR: | ||
138 | break; | ||
139 | } | ||
140 | } | ||
141 | |||
142 | /* Main I/O error handler */ | ||
143 | static void hid_io_error(struct hid_device *hid) | ||
144 | { | ||
145 | unsigned long flags; | ||
146 | struct usbhid_device *usbhid = hid->driver_data; | ||
147 | |||
148 | spin_lock_irqsave(&usbhid->inlock, flags); | ||
149 | |||
150 | /* Stop when disconnected */ | ||
151 | if (usb_get_intfdata(usbhid->intf) == NULL) | ||
152 | goto done; | ||
153 | |||
154 | /* If it has been a while since the last error, we'll assume | ||
155 | * this a brand new error and reset the retry timeout. */ | ||
156 | if (time_after(jiffies, usbhid->stop_retry + HZ/2)) | ||
157 | usbhid->retry_delay = 0; | ||
158 | |||
159 | /* When an error occurs, retry at increasing intervals */ | ||
160 | if (usbhid->retry_delay == 0) { | ||
161 | usbhid->retry_delay = 13; /* Then 26, 52, 104, 104, ... */ | ||
162 | usbhid->stop_retry = jiffies + msecs_to_jiffies(1000); | ||
163 | } else if (usbhid->retry_delay < 100) | ||
164 | usbhid->retry_delay *= 2; | ||
165 | |||
166 | if (time_after(jiffies, usbhid->stop_retry)) { | ||
167 | |||
168 | /* Retries failed, so do a port reset */ | ||
169 | if (!test_and_set_bit(HID_RESET_PENDING, &usbhid->iofl)) { | ||
170 | schedule_work(&usbhid->reset_work); | ||
171 | goto done; | ||
172 | } | ||
173 | } | ||
174 | |||
175 | mod_timer(&usbhid->io_retry, | ||
176 | jiffies + msecs_to_jiffies(usbhid->retry_delay)); | ||
177 | done: | ||
178 | spin_unlock_irqrestore(&usbhid->inlock, flags); | ||
179 | } | ||
180 | |||
181 | /* | ||
182 | * Input interrupt completion handler. | ||
183 | */ | ||
184 | |||
185 | static void hid_irq_in(struct urb *urb) | ||
186 | { | ||
187 | struct hid_device *hid = urb->context; | ||
188 | struct usbhid_device *usbhid = hid->driver_data; | ||
189 | int status; | ||
190 | |||
191 | switch (urb->status) { | ||
192 | case 0: /* success */ | ||
193 | usbhid->retry_delay = 0; | ||
194 | hid_input_report(urb->context, HID_INPUT_REPORT, | ||
195 | urb->transfer_buffer, | ||
196 | urb->actual_length, 1); | ||
197 | break; | ||
198 | case -EPIPE: /* stall */ | ||
199 | clear_bit(HID_IN_RUNNING, &usbhid->iofl); | ||
200 | set_bit(HID_CLEAR_HALT, &usbhid->iofl); | ||
201 | schedule_work(&usbhid->reset_work); | ||
202 | return; | ||
203 | case -ECONNRESET: /* unlink */ | ||
204 | case -ENOENT: | ||
205 | case -ESHUTDOWN: /* unplug */ | ||
206 | clear_bit(HID_IN_RUNNING, &usbhid->iofl); | ||
207 | return; | ||
208 | case -EILSEQ: /* protocol error or unplug */ | ||
209 | case -EPROTO: /* protocol error or unplug */ | ||
210 | case -ETIME: /* protocol error or unplug */ | ||
211 | case -ETIMEDOUT: /* Should never happen, but... */ | ||
212 | clear_bit(HID_IN_RUNNING, &usbhid->iofl); | ||
213 | hid_io_error(hid); | ||
214 | return; | ||
215 | default: /* error */ | ||
216 | warn("input irq status %d received", urb->status); | ||
217 | } | ||
218 | |||
219 | status = usb_submit_urb(urb, GFP_ATOMIC); | ||
220 | if (status) { | ||
221 | clear_bit(HID_IN_RUNNING, &usbhid->iofl); | ||
222 | if (status != -EPERM) { | ||
223 | err("can't resubmit intr, %s-%s/input%d, status %d", | ||
224 | hid_to_usb_dev(hid)->bus->bus_name, | ||
225 | hid_to_usb_dev(hid)->devpath, | ||
226 | usbhid->ifnum, status); | ||
227 | hid_io_error(hid); | ||
228 | } | ||
229 | } | ||
230 | } | ||
231 | |||
232 | static int hid_submit_out(struct hid_device *hid) | ||
233 | { | ||
234 | struct hid_report *report; | ||
235 | struct usbhid_device *usbhid = hid->driver_data; | ||
236 | |||
237 | report = usbhid->out[usbhid->outtail]; | ||
238 | |||
239 | hid_output_report(report, usbhid->outbuf); | ||
240 | usbhid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + (report->id > 0); | ||
241 | usbhid->urbout->dev = hid_to_usb_dev(hid); | ||
242 | |||
243 | dbg("submitting out urb"); | ||
244 | |||
245 | if (usb_submit_urb(usbhid->urbout, GFP_ATOMIC)) { | ||
246 | err("usb_submit_urb(out) failed"); | ||
247 | return -1; | ||
248 | } | ||
249 | |||
250 | return 0; | ||
251 | } | ||
252 | |||
253 | static int hid_submit_ctrl(struct hid_device *hid) | ||
254 | { | ||
255 | struct hid_report *report; | ||
256 | unsigned char dir; | ||
257 | int len; | ||
258 | struct usbhid_device *usbhid = hid->driver_data; | ||
259 | |||
260 | report = usbhid->ctrl[usbhid->ctrltail].report; | ||
261 | dir = usbhid->ctrl[usbhid->ctrltail].dir; | ||
262 | |||
263 | len = ((report->size - 1) >> 3) + 1 + (report->id > 0); | ||
264 | if (dir == USB_DIR_OUT) { | ||
265 | hid_output_report(report, usbhid->ctrlbuf); | ||
266 | usbhid->urbctrl->pipe = usb_sndctrlpipe(hid_to_usb_dev(hid), 0); | ||
267 | usbhid->urbctrl->transfer_buffer_length = len; | ||
268 | } else { | ||
269 | int maxpacket, padlen; | ||
270 | |||
271 | usbhid->urbctrl->pipe = usb_rcvctrlpipe(hid_to_usb_dev(hid), 0); | ||
272 | maxpacket = usb_maxpacket(hid_to_usb_dev(hid), usbhid->urbctrl->pipe, 0); | ||
273 | if (maxpacket > 0) { | ||
274 | padlen = (len + maxpacket - 1) / maxpacket; | ||
275 | padlen *= maxpacket; | ||
276 | if (padlen > usbhid->bufsize) | ||
277 | padlen = usbhid->bufsize; | ||
278 | } else | ||
279 | padlen = 0; | ||
280 | usbhid->urbctrl->transfer_buffer_length = padlen; | ||
281 | } | ||
282 | usbhid->urbctrl->dev = hid_to_usb_dev(hid); | ||
283 | |||
284 | usbhid->cr->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE | dir; | ||
285 | usbhid->cr->bRequest = (dir == USB_DIR_OUT) ? HID_REQ_SET_REPORT : HID_REQ_GET_REPORT; | ||
286 | usbhid->cr->wValue = cpu_to_le16(((report->type + 1) << 8) | report->id); | ||
287 | usbhid->cr->wIndex = cpu_to_le16(usbhid->ifnum); | ||
288 | usbhid->cr->wLength = cpu_to_le16(len); | ||
289 | |||
290 | dbg("submitting ctrl urb: %s wValue=0x%04x wIndex=0x%04x wLength=%u", | ||
291 | usbhid->cr->bRequest == HID_REQ_SET_REPORT ? "Set_Report" : "Get_Report", | ||
292 | usbhid->cr->wValue, usbhid->cr->wIndex, usbhid->cr->wLength); | ||
293 | |||
294 | if (usb_submit_urb(usbhid->urbctrl, GFP_ATOMIC)) { | ||
295 | err("usb_submit_urb(ctrl) failed"); | ||
296 | return -1; | ||
297 | } | ||
298 | |||
299 | return 0; | ||
300 | } | ||
301 | |||
302 | /* | ||
303 | * Output interrupt completion handler. | ||
304 | */ | ||
305 | |||
306 | static void hid_irq_out(struct urb *urb) | ||
307 | { | ||
308 | struct hid_device *hid = urb->context; | ||
309 | struct usbhid_device *usbhid = hid->driver_data; | ||
310 | unsigned long flags; | ||
311 | int unplug = 0; | ||
312 | |||
313 | switch (urb->status) { | ||
314 | case 0: /* success */ | ||
315 | break; | ||
316 | case -ESHUTDOWN: /* unplug */ | ||
317 | unplug = 1; | ||
318 | case -EILSEQ: /* protocol error or unplug */ | ||
319 | case -EPROTO: /* protocol error or unplug */ | ||
320 | case -ECONNRESET: /* unlink */ | ||
321 | case -ENOENT: | ||
322 | break; | ||
323 | default: /* error */ | ||
324 | warn("output irq status %d received", urb->status); | ||
325 | } | ||
326 | |||
327 | spin_lock_irqsave(&usbhid->outlock, flags); | ||
328 | |||
329 | if (unplug) | ||
330 | usbhid->outtail = usbhid->outhead; | ||
331 | else | ||
332 | usbhid->outtail = (usbhid->outtail + 1) & (HID_OUTPUT_FIFO_SIZE - 1); | ||
333 | |||
334 | if (usbhid->outhead != usbhid->outtail) { | ||
335 | if (hid_submit_out(hid)) { | ||
336 | clear_bit(HID_OUT_RUNNING, &usbhid->iofl); | ||
337 | wake_up(&hid->wait); | ||
338 | } | ||
339 | spin_unlock_irqrestore(&usbhid->outlock, flags); | ||
340 | return; | ||
341 | } | ||
342 | |||
343 | clear_bit(HID_OUT_RUNNING, &usbhid->iofl); | ||
344 | spin_unlock_irqrestore(&usbhid->outlock, flags); | ||
345 | wake_up(&hid->wait); | ||
346 | } | ||
347 | |||
348 | /* | ||
349 | * Control pipe completion handler. | ||
350 | */ | ||
351 | |||
352 | static void hid_ctrl(struct urb *urb) | ||
353 | { | ||
354 | struct hid_device *hid = urb->context; | ||
355 | struct usbhid_device *usbhid = hid->driver_data; | ||
356 | unsigned long flags; | ||
357 | int unplug = 0; | ||
358 | |||
359 | spin_lock_irqsave(&usbhid->ctrllock, flags); | ||
360 | |||
361 | switch (urb->status) { | ||
362 | case 0: /* success */ | ||
363 | if (usbhid->ctrl[usbhid->ctrltail].dir == USB_DIR_IN) | ||
364 | hid_input_report(urb->context, usbhid->ctrl[usbhid->ctrltail].report->type, | ||
365 | urb->transfer_buffer, urb->actual_length, 0); | ||
366 | break; | ||
367 | case -ESHUTDOWN: /* unplug */ | ||
368 | unplug = 1; | ||
369 | case -EILSEQ: /* protocol error or unplug */ | ||
370 | case -EPROTO: /* protocol error or unplug */ | ||
371 | case -ECONNRESET: /* unlink */ | ||
372 | case -ENOENT: | ||
373 | case -EPIPE: /* report not available */ | ||
374 | break; | ||
375 | default: /* error */ | ||
376 | warn("ctrl urb status %d received", urb->status); | ||
377 | } | ||
378 | |||
379 | if (unplug) | ||
380 | usbhid->ctrltail = usbhid->ctrlhead; | ||
381 | else | ||
382 | usbhid->ctrltail = (usbhid->ctrltail + 1) & (HID_CONTROL_FIFO_SIZE - 1); | ||
383 | |||
384 | if (usbhid->ctrlhead != usbhid->ctrltail) { | ||
385 | if (hid_submit_ctrl(hid)) { | ||
386 | clear_bit(HID_CTRL_RUNNING, &usbhid->iofl); | ||
387 | wake_up(&hid->wait); | ||
388 | } | ||
389 | spin_unlock_irqrestore(&usbhid->ctrllock, flags); | ||
390 | return; | ||
391 | } | ||
392 | |||
393 | clear_bit(HID_CTRL_RUNNING, &usbhid->iofl); | ||
394 | spin_unlock_irqrestore(&usbhid->ctrllock, flags); | ||
395 | wake_up(&hid->wait); | ||
396 | } | ||
397 | |||
398 | void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir) | ||
399 | { | ||
400 | int head; | ||
401 | unsigned long flags; | ||
402 | struct usbhid_device *usbhid = hid->driver_data; | ||
403 | |||
404 | if ((hid->quirks & HID_QUIRK_NOGET) && dir == USB_DIR_IN) | ||
405 | return; | ||
406 | |||
407 | if (usbhid->urbout && dir == USB_DIR_OUT && report->type == HID_OUTPUT_REPORT) { | ||
408 | |||
409 | spin_lock_irqsave(&usbhid->outlock, flags); | ||
410 | |||
411 | if ((head = (usbhid->outhead + 1) & (HID_OUTPUT_FIFO_SIZE - 1)) == usbhid->outtail) { | ||
412 | spin_unlock_irqrestore(&usbhid->outlock, flags); | ||
413 | warn("output queue full"); | ||
414 | return; | ||
415 | } | ||
416 | |||
417 | usbhid->out[usbhid->outhead] = report; | ||
418 | usbhid->outhead = head; | ||
419 | |||
420 | if (!test_and_set_bit(HID_OUT_RUNNING, &usbhid->iofl)) | ||
421 | if (hid_submit_out(hid)) | ||
422 | clear_bit(HID_OUT_RUNNING, &usbhid->iofl); | ||
423 | |||
424 | spin_unlock_irqrestore(&usbhid->outlock, flags); | ||
425 | return; | ||
426 | } | ||
427 | |||
428 | spin_lock_irqsave(&usbhid->ctrllock, flags); | ||
429 | |||
430 | if ((head = (usbhid->ctrlhead + 1) & (HID_CONTROL_FIFO_SIZE - 1)) == usbhid->ctrltail) { | ||
431 | spin_unlock_irqrestore(&usbhid->ctrllock, flags); | ||
432 | warn("control queue full"); | ||
433 | return; | ||
434 | } | ||
435 | |||
436 | usbhid->ctrl[usbhid->ctrlhead].report = report; | ||
437 | usbhid->ctrl[usbhid->ctrlhead].dir = dir; | ||
438 | usbhid->ctrlhead = head; | ||
439 | |||
440 | if (!test_and_set_bit(HID_CTRL_RUNNING, &usbhid->iofl)) | ||
441 | if (hid_submit_ctrl(hid)) | ||
442 | clear_bit(HID_CTRL_RUNNING, &usbhid->iofl); | ||
443 | |||
444 | spin_unlock_irqrestore(&usbhid->ctrllock, flags); | ||
445 | } | ||
446 | |||
447 | static int usb_hidinput_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) | ||
448 | { | ||
449 | struct hid_device *hid = dev->private; | ||
450 | struct hid_field *field; | ||
451 | int offset; | ||
452 | |||
453 | if (type == EV_FF) | ||
454 | return input_ff_event(dev, type, code, value); | ||
455 | |||
456 | if (type != EV_LED) | ||
457 | return -1; | ||
458 | |||
459 | if ((offset = hidinput_find_field(hid, type, code, &field)) == -1) { | ||
460 | warn("event field not found"); | ||
461 | return -1; | ||
462 | } | ||
463 | |||
464 | hid_set_field(field, offset, value); | ||
465 | usbhid_submit_report(hid, field->report, USB_DIR_OUT); | ||
466 | |||
467 | return 0; | ||
468 | } | ||
469 | |||
470 | int usbhid_wait_io(struct hid_device *hid) | ||
471 | { | ||
472 | struct usbhid_device *usbhid = hid->driver_data; | ||
473 | |||
474 | if (!wait_event_timeout(hid->wait, (!test_bit(HID_CTRL_RUNNING, &usbhid->iofl) && | ||
475 | !test_bit(HID_OUT_RUNNING, &usbhid->iofl)), | ||
476 | 10*HZ)) { | ||
477 | dbg("timeout waiting for ctrl or out queue to clear"); | ||
478 | return -1; | ||
479 | } | ||
480 | |||
481 | return 0; | ||
482 | } | ||
483 | |||
484 | static int hid_set_idle(struct usb_device *dev, int ifnum, int report, int idle) | ||
485 | { | ||
486 | return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | ||
487 | HID_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE, (idle << 8) | report, | ||
488 | ifnum, NULL, 0, USB_CTRL_SET_TIMEOUT); | ||
489 | } | ||
490 | |||
491 | static int hid_get_class_descriptor(struct usb_device *dev, int ifnum, | ||
492 | unsigned char type, void *buf, int size) | ||
493 | { | ||
494 | int result, retries = 4; | ||
495 | |||
496 | memset(buf, 0, size); | ||
497 | |||
498 | do { | ||
499 | result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), | ||
500 | USB_REQ_GET_DESCRIPTOR, USB_RECIP_INTERFACE | USB_DIR_IN, | ||
501 | (type << 8), ifnum, buf, size, USB_CTRL_GET_TIMEOUT); | ||
502 | retries--; | ||
503 | } while (result < size && retries); | ||
504 | return result; | ||
505 | } | ||
506 | |||
507 | int usbhid_open(struct hid_device *hid) | ||
508 | { | ||
509 | ++hid->open; | ||
510 | if (hid_start_in(hid)) | ||
511 | hid_io_error(hid); | ||
512 | return 0; | ||
513 | } | ||
514 | |||
515 | void usbhid_close(struct hid_device *hid) | ||
516 | { | ||
517 | struct usbhid_device *usbhid = hid->driver_data; | ||
518 | |||
519 | if (!--hid->open) | ||
520 | usb_kill_urb(usbhid->urbin); | ||
521 | } | ||
522 | |||
523 | /* | ||
524 | * Initialize all reports | ||
525 | */ | ||
526 | |||
527 | void usbhid_init_reports(struct hid_device *hid) | ||
528 | { | ||
529 | struct hid_report *report; | ||
530 | struct usbhid_device *usbhid = hid->driver_data; | ||
531 | int err, ret; | ||
532 | |||
533 | list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].report_list, list) | ||
534 | usbhid_submit_report(hid, report, USB_DIR_IN); | ||
535 | |||
536 | list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].report_list, list) | ||
537 | usbhid_submit_report(hid, report, USB_DIR_IN); | ||
538 | |||
539 | err = 0; | ||
540 | ret = usbhid_wait_io(hid); | ||
541 | while (ret) { | ||
542 | err |= ret; | ||
543 | if (test_bit(HID_CTRL_RUNNING, &usbhid->iofl)) | ||
544 | usb_kill_urb(usbhid->urbctrl); | ||
545 | if (test_bit(HID_OUT_RUNNING, &usbhid->iofl)) | ||
546 | usb_kill_urb(usbhid->urbout); | ||
547 | ret = usbhid_wait_io(hid); | ||
548 | } | ||
549 | |||
550 | if (err) | ||
551 | warn("timeout initializing reports"); | ||
552 | } | ||
553 | |||
554 | /* | ||
555 | * Reset LEDs which BIOS might have left on. For now, just NumLock (0x01). | ||
556 | */ | ||
557 | static int hid_find_field_early(struct hid_device *hid, unsigned int page, | ||
558 | unsigned int hid_code, struct hid_field **pfield) | ||
559 | { | ||
560 | struct hid_report *report; | ||
561 | struct hid_field *field; | ||
562 | struct hid_usage *usage; | ||
563 | int i, j; | ||
564 | |||
565 | list_for_each_entry(report, &hid->report_enum[HID_OUTPUT_REPORT].report_list, list) { | ||
566 | for (i = 0; i < report->maxfield; i++) { | ||
567 | field = report->field[i]; | ||
568 | for (j = 0; j < field->maxusage; j++) { | ||
569 | usage = &field->usage[j]; | ||
570 | if ((usage->hid & HID_USAGE_PAGE) == page && | ||
571 | (usage->hid & 0xFFFF) == hid_code) { | ||
572 | *pfield = field; | ||
573 | return j; | ||
574 | } | ||
575 | } | ||
576 | } | ||
577 | } | ||
578 | return -1; | ||
579 | } | ||
580 | |||
581 | static void usbhid_set_leds(struct hid_device *hid) | ||
582 | { | ||
583 | struct hid_field *field; | ||
584 | int offset; | ||
585 | |||
586 | if ((offset = hid_find_field_early(hid, HID_UP_LED, 0x01, &field)) != -1) { | ||
587 | hid_set_field(field, offset, 0); | ||
588 | usbhid_submit_report(hid, field->report, USB_DIR_OUT); | ||
589 | } | ||
590 | } | ||
591 | |||
592 | /* | ||
593 | * Traverse the supplied list of reports and find the longest | ||
594 | */ | ||
595 | static void hid_find_max_report(struct hid_device *hid, unsigned int type, int *max) | ||
596 | { | ||
597 | struct hid_report *report; | ||
598 | int size; | ||
599 | |||
600 | list_for_each_entry(report, &hid->report_enum[type].report_list, list) { | ||
601 | size = ((report->size - 1) >> 3) + 1; | ||
602 | if (type == HID_INPUT_REPORT && hid->report_enum[type].numbered) | ||
603 | size++; | ||
604 | if (*max < size) | ||
605 | *max = size; | ||
606 | } | ||
607 | } | ||
608 | |||
609 | static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid) | ||
610 | { | ||
611 | struct usbhid_device *usbhid = hid->driver_data; | ||
612 | |||
613 | if (!(usbhid->inbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_ATOMIC, &usbhid->inbuf_dma))) | ||
614 | return -1; | ||
615 | if (!(usbhid->outbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_ATOMIC, &usbhid->outbuf_dma))) | ||
616 | return -1; | ||
617 | if (!(usbhid->cr = usb_buffer_alloc(dev, sizeof(*(usbhid->cr)), GFP_ATOMIC, &usbhid->cr_dma))) | ||
618 | return -1; | ||
619 | if (!(usbhid->ctrlbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_ATOMIC, &usbhid->ctrlbuf_dma))) | ||
620 | return -1; | ||
621 | |||
622 | return 0; | ||
623 | } | ||
624 | |||
625 | static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid) | ||
626 | { | ||
627 | struct usbhid_device *usbhid = hid->driver_data; | ||
628 | |||
629 | if (usbhid->inbuf) | ||
630 | usb_buffer_free(dev, usbhid->bufsize, usbhid->inbuf, usbhid->inbuf_dma); | ||
631 | if (usbhid->outbuf) | ||
632 | usb_buffer_free(dev, usbhid->bufsize, usbhid->outbuf, usbhid->outbuf_dma); | ||
633 | if (usbhid->cr) | ||
634 | usb_buffer_free(dev, sizeof(*(usbhid->cr)), usbhid->cr, usbhid->cr_dma); | ||
635 | if (usbhid->ctrlbuf) | ||
636 | usb_buffer_free(dev, usbhid->bufsize, usbhid->ctrlbuf, usbhid->ctrlbuf_dma); | ||
637 | } | ||
638 | |||
639 | /* | ||
640 | * Cherry Cymotion keyboard have an invalid HID report descriptor, | ||
641 | * that needs fixing before we can parse it. | ||
642 | */ | ||
643 | |||
644 | static void hid_fixup_cymotion_descriptor(char *rdesc, int rsize) | ||
645 | { | ||
646 | if (rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) { | ||
647 | info("Fixing up Cherry Cymotion report descriptor"); | ||
648 | rdesc[11] = rdesc[16] = 0xff; | ||
649 | rdesc[12] = rdesc[17] = 0x03; | ||
650 | } | ||
651 | } | ||
652 | |||
653 | /* | ||
654 | * Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller | ||
655 | * to "operational". Without this, the ps3 controller will not report any | ||
656 | * events. | ||
657 | */ | ||
658 | static void hid_fixup_sony_ps3_controller(struct usb_device *dev, int ifnum) | ||
659 | { | ||
660 | int result; | ||
661 | char *buf = kmalloc(18, GFP_KERNEL); | ||
662 | |||
663 | if (!buf) | ||
664 | return; | ||
665 | |||
666 | result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), | ||
667 | HID_REQ_GET_REPORT, | ||
668 | USB_DIR_IN | USB_TYPE_CLASS | | ||
669 | USB_RECIP_INTERFACE, | ||
670 | (3 << 8) | 0xf2, ifnum, buf, 17, | ||
671 | USB_CTRL_GET_TIMEOUT); | ||
672 | |||
673 | if (result < 0) | ||
674 | err("%s failed: %d\n", __func__, result); | ||
675 | |||
676 | kfree(buf); | ||
677 | } | ||
678 | |||
679 | /* | ||
680 | * Certain Logitech keyboards send in report #3 keys which are far | ||
681 | * above the logical maximum described in descriptor. This extends | ||
682 | * the original value of 0x28c of logical maximum to 0x104d | ||
683 | */ | ||
684 | static void hid_fixup_logitech_descriptor(unsigned char *rdesc, int rsize) | ||
685 | { | ||
686 | if (rsize >= 90 && rdesc[83] == 0x26 | ||
687 | && rdesc[84] == 0x8c | ||
688 | && rdesc[85] == 0x02) { | ||
689 | info("Fixing up Logitech keyboard report descriptor"); | ||
690 | rdesc[84] = rdesc[89] = 0x4d; | ||
691 | rdesc[85] = rdesc[90] = 0x10; | ||
692 | } | ||
693 | } | ||
694 | |||
695 | static struct hid_device *usb_hid_configure(struct usb_interface *intf) | ||
696 | { | ||
697 | struct usb_host_interface *interface = intf->cur_altsetting; | ||
698 | struct usb_device *dev = interface_to_usbdev (intf); | ||
699 | struct hid_descriptor *hdesc; | ||
700 | struct hid_device *hid; | ||
701 | u32 quirks = 0; | ||
702 | unsigned rsize = 0; | ||
703 | char *rdesc; | ||
704 | int n, len, insize = 0; | ||
705 | struct usbhid_device *usbhid; | ||
706 | |||
707 | quirks = usbhid_lookup_quirk(le16_to_cpu(dev->descriptor.idVendor), | ||
708 | le16_to_cpu(dev->descriptor.idProduct)); | ||
709 | |||
710 | /* Many keyboards and mice don't like to be polled for reports, | ||
711 | * so we will always set the HID_QUIRK_NOGET flag for them. */ | ||
712 | if (interface->desc.bInterfaceSubClass == USB_INTERFACE_SUBCLASS_BOOT) { | ||
713 | if (interface->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_KEYBOARD || | ||
714 | interface->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_MOUSE) | ||
715 | quirks |= HID_QUIRK_NOGET; | ||
716 | } | ||
717 | |||
718 | if (quirks & HID_QUIRK_IGNORE) | ||
719 | return NULL; | ||
720 | |||
721 | if ((quirks & HID_QUIRK_IGNORE_MOUSE) && | ||
722 | (interface->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_MOUSE)) | ||
723 | return NULL; | ||
724 | |||
725 | |||
726 | if (usb_get_extra_descriptor(interface, HID_DT_HID, &hdesc) && | ||
727 | (!interface->desc.bNumEndpoints || | ||
728 | usb_get_extra_descriptor(&interface->endpoint[0], HID_DT_HID, &hdesc))) { | ||
729 | dbg("class descriptor not present\n"); | ||
730 | return NULL; | ||
731 | } | ||
732 | |||
733 | for (n = 0; n < hdesc->bNumDescriptors; n++) | ||
734 | if (hdesc->desc[n].bDescriptorType == HID_DT_REPORT) | ||
735 | rsize = le16_to_cpu(hdesc->desc[n].wDescriptorLength); | ||
736 | |||
737 | if (!rsize || rsize > HID_MAX_DESCRIPTOR_SIZE) { | ||
738 | dbg("weird size of report descriptor (%u)", rsize); | ||
739 | return NULL; | ||
740 | } | ||
741 | |||
742 | if (!(rdesc = kmalloc(rsize, GFP_KERNEL))) { | ||
743 | dbg("couldn't allocate rdesc memory"); | ||
744 | return NULL; | ||
745 | } | ||
746 | |||
747 | hid_set_idle(dev, interface->desc.bInterfaceNumber, 0, 0); | ||
748 | |||
749 | if ((n = hid_get_class_descriptor(dev, interface->desc.bInterfaceNumber, HID_DT_REPORT, rdesc, rsize)) < 0) { | ||
750 | dbg("reading report descriptor failed"); | ||
751 | kfree(rdesc); | ||
752 | return NULL; | ||
753 | } | ||
754 | |||
755 | if ((quirks & HID_QUIRK_CYMOTION)) | ||
756 | hid_fixup_cymotion_descriptor(rdesc, rsize); | ||
757 | |||
758 | if (quirks & HID_QUIRK_LOGITECH_DESCRIPTOR) | ||
759 | hid_fixup_logitech_descriptor(rdesc, rsize); | ||
760 | |||
761 | #ifdef CONFIG_HID_DEBUG | ||
762 | printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n); | ||
763 | for (n = 0; n < rsize; n++) | ||
764 | printk(" %02x", (unsigned char) rdesc[n]); | ||
765 | printk("\n"); | ||
766 | #endif | ||
767 | |||
768 | if (!(hid = hid_parse_report(rdesc, n))) { | ||
769 | dbg("parsing report descriptor failed"); | ||
770 | kfree(rdesc); | ||
771 | return NULL; | ||
772 | } | ||
773 | |||
774 | kfree(rdesc); | ||
775 | hid->quirks = quirks; | ||
776 | |||
777 | if (!(usbhid = kzalloc(sizeof(struct usbhid_device), GFP_KERNEL))) | ||
778 | goto fail; | ||
779 | |||
780 | hid->driver_data = usbhid; | ||
781 | usbhid->hid = hid; | ||
782 | |||
783 | usbhid->bufsize = HID_MIN_BUFFER_SIZE; | ||
784 | hid_find_max_report(hid, HID_INPUT_REPORT, &usbhid->bufsize); | ||
785 | hid_find_max_report(hid, HID_OUTPUT_REPORT, &usbhid->bufsize); | ||
786 | hid_find_max_report(hid, HID_FEATURE_REPORT, &usbhid->bufsize); | ||
787 | |||
788 | if (usbhid->bufsize > HID_MAX_BUFFER_SIZE) | ||
789 | usbhid->bufsize = HID_MAX_BUFFER_SIZE; | ||
790 | |||
791 | hid_find_max_report(hid, HID_INPUT_REPORT, &insize); | ||
792 | |||
793 | if (insize > HID_MAX_BUFFER_SIZE) | ||
794 | insize = HID_MAX_BUFFER_SIZE; | ||
795 | |||
796 | if (hid_alloc_buffers(dev, hid)) { | ||
797 | hid_free_buffers(dev, hid); | ||
798 | goto fail; | ||
799 | } | ||
800 | |||
801 | for (n = 0; n < interface->desc.bNumEndpoints; n++) { | ||
802 | |||
803 | struct usb_endpoint_descriptor *endpoint; | ||
804 | int pipe; | ||
805 | int interval; | ||
806 | |||
807 | endpoint = &interface->endpoint[n].desc; | ||
808 | if ((endpoint->bmAttributes & 3) != 3) /* Not an interrupt endpoint */ | ||
809 | continue; | ||
810 | |||
811 | interval = endpoint->bInterval; | ||
812 | |||
813 | /* Change the polling interval of mice. */ | ||
814 | if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0) | ||
815 | interval = hid_mousepoll_interval; | ||
816 | |||
817 | if (usb_endpoint_dir_in(endpoint)) { | ||
818 | if (usbhid->urbin) | ||
819 | continue; | ||
820 | if (!(usbhid->urbin = usb_alloc_urb(0, GFP_KERNEL))) | ||
821 | goto fail; | ||
822 | pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); | ||
823 | usb_fill_int_urb(usbhid->urbin, dev, pipe, usbhid->inbuf, insize, | ||
824 | hid_irq_in, hid, interval); | ||
825 | usbhid->urbin->transfer_dma = usbhid->inbuf_dma; | ||
826 | usbhid->urbin->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
827 | } else { | ||
828 | if (usbhid->urbout) | ||
829 | continue; | ||
830 | if (!(usbhid->urbout = usb_alloc_urb(0, GFP_KERNEL))) | ||
831 | goto fail; | ||
832 | pipe = usb_sndintpipe(dev, endpoint->bEndpointAddress); | ||
833 | usb_fill_int_urb(usbhid->urbout, dev, pipe, usbhid->outbuf, 0, | ||
834 | hid_irq_out, hid, interval); | ||
835 | usbhid->urbout->transfer_dma = usbhid->outbuf_dma; | ||
836 | usbhid->urbout->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
837 | } | ||
838 | } | ||
839 | |||
840 | if (!usbhid->urbin) { | ||
841 | err("couldn't find an input interrupt endpoint"); | ||
842 | goto fail; | ||
843 | } | ||
844 | |||
845 | init_waitqueue_head(&hid->wait); | ||
846 | |||
847 | INIT_WORK(&usbhid->reset_work, hid_reset); | ||
848 | setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid); | ||
849 | |||
850 | spin_lock_init(&usbhid->inlock); | ||
851 | spin_lock_init(&usbhid->outlock); | ||
852 | spin_lock_init(&usbhid->ctrllock); | ||
853 | |||
854 | hid->version = le16_to_cpu(hdesc->bcdHID); | ||
855 | hid->country = hdesc->bCountryCode; | ||
856 | hid->dev = &intf->dev; | ||
857 | usbhid->intf = intf; | ||
858 | usbhid->ifnum = interface->desc.bInterfaceNumber; | ||
859 | |||
860 | hid->name[0] = 0; | ||
861 | |||
862 | if (dev->manufacturer) | ||
863 | strlcpy(hid->name, dev->manufacturer, sizeof(hid->name)); | ||
864 | |||
865 | if (dev->product) { | ||
866 | if (dev->manufacturer) | ||
867 | strlcat(hid->name, " ", sizeof(hid->name)); | ||
868 | strlcat(hid->name, dev->product, sizeof(hid->name)); | ||
869 | } | ||
870 | |||
871 | if (!strlen(hid->name)) | ||
872 | snprintf(hid->name, sizeof(hid->name), "HID %04x:%04x", | ||
873 | le16_to_cpu(dev->descriptor.idVendor), | ||
874 | le16_to_cpu(dev->descriptor.idProduct)); | ||
875 | |||
876 | hid->bus = BUS_USB; | ||
877 | hid->vendor = le16_to_cpu(dev->descriptor.idVendor); | ||
878 | hid->product = le16_to_cpu(dev->descriptor.idProduct); | ||
879 | |||
880 | usb_make_path(dev, hid->phys, sizeof(hid->phys)); | ||
881 | strlcat(hid->phys, "/input", sizeof(hid->phys)); | ||
882 | len = strlen(hid->phys); | ||
883 | if (len < sizeof(hid->phys) - 1) | ||
884 | snprintf(hid->phys + len, sizeof(hid->phys) - len, | ||
885 | "%d", intf->altsetting[0].desc.bInterfaceNumber); | ||
886 | |||
887 | if (usb_string(dev, dev->descriptor.iSerialNumber, hid->uniq, 64) <= 0) | ||
888 | hid->uniq[0] = 0; | ||
889 | |||
890 | usbhid->urbctrl = usb_alloc_urb(0, GFP_KERNEL); | ||
891 | if (!usbhid->urbctrl) | ||
892 | goto fail; | ||
893 | |||
894 | usb_fill_control_urb(usbhid->urbctrl, dev, 0, (void *) usbhid->cr, | ||
895 | usbhid->ctrlbuf, 1, hid_ctrl, hid); | ||
896 | usbhid->urbctrl->setup_dma = usbhid->cr_dma; | ||
897 | usbhid->urbctrl->transfer_dma = usbhid->ctrlbuf_dma; | ||
898 | usbhid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP); | ||
899 | hid->hidinput_input_event = usb_hidinput_input_event; | ||
900 | hid->hid_open = usbhid_open; | ||
901 | hid->hid_close = usbhid_close; | ||
902 | #ifdef CONFIG_USB_HIDDEV | ||
903 | hid->hiddev_hid_event = hiddev_hid_event; | ||
904 | hid->hiddev_report_event = hiddev_report_event; | ||
905 | #endif | ||
906 | return hid; | ||
907 | |||
908 | fail: | ||
909 | usb_free_urb(usbhid->urbin); | ||
910 | usb_free_urb(usbhid->urbout); | ||
911 | usb_free_urb(usbhid->urbctrl); | ||
912 | hid_free_buffers(dev, hid); | ||
913 | hid_free_device(hid); | ||
914 | |||
915 | return NULL; | ||
916 | } | ||
917 | |||
918 | static void hid_disconnect(struct usb_interface *intf) | ||
919 | { | ||
920 | struct hid_device *hid = usb_get_intfdata (intf); | ||
921 | struct usbhid_device *usbhid; | ||
922 | |||
923 | if (!hid) | ||
924 | return; | ||
925 | |||
926 | usbhid = hid->driver_data; | ||
927 | |||
928 | spin_lock_irq(&usbhid->inlock); /* Sync with error handler */ | ||
929 | usb_set_intfdata(intf, NULL); | ||
930 | spin_unlock_irq(&usbhid->inlock); | ||
931 | usb_kill_urb(usbhid->urbin); | ||
932 | usb_kill_urb(usbhid->urbout); | ||
933 | usb_kill_urb(usbhid->urbctrl); | ||
934 | |||
935 | del_timer_sync(&usbhid->io_retry); | ||
936 | flush_scheduled_work(); | ||
937 | |||
938 | if (hid->claimed & HID_CLAIMED_INPUT) | ||
939 | hidinput_disconnect(hid); | ||
940 | if (hid->claimed & HID_CLAIMED_HIDDEV) | ||
941 | hiddev_disconnect(hid); | ||
942 | |||
943 | usb_free_urb(usbhid->urbin); | ||
944 | usb_free_urb(usbhid->urbctrl); | ||
945 | usb_free_urb(usbhid->urbout); | ||
946 | |||
947 | hid_free_buffers(hid_to_usb_dev(hid), hid); | ||
948 | hid_free_device(hid); | ||
949 | } | ||
950 | |||
951 | static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id) | ||
952 | { | ||
953 | struct hid_device *hid; | ||
954 | char path[64]; | ||
955 | int i; | ||
956 | char *c; | ||
957 | |||
958 | dbg("HID probe called for ifnum %d", | ||
959 | intf->altsetting->desc.bInterfaceNumber); | ||
960 | |||
961 | if (!(hid = usb_hid_configure(intf))) | ||
962 | return -ENODEV; | ||
963 | |||
964 | usbhid_init_reports(hid); | ||
965 | hid_dump_device(hid); | ||
966 | if (hid->quirks & HID_QUIRK_RESET_LEDS) | ||
967 | usbhid_set_leds(hid); | ||
968 | |||
969 | if (!hidinput_connect(hid)) | ||
970 | hid->claimed |= HID_CLAIMED_INPUT; | ||
971 | if (!hiddev_connect(hid)) | ||
972 | hid->claimed |= HID_CLAIMED_HIDDEV; | ||
973 | |||
974 | usb_set_intfdata(intf, hid); | ||
975 | |||
976 | if (!hid->claimed) { | ||
977 | printk ("HID device not claimed by input or hiddev\n"); | ||
978 | hid_disconnect(intf); | ||
979 | return -ENODEV; | ||
980 | } | ||
981 | |||
982 | if ((hid->claimed & HID_CLAIMED_INPUT)) | ||
983 | hid_ff_init(hid); | ||
984 | |||
985 | if (hid->quirks & HID_QUIRK_SONY_PS3_CONTROLLER) | ||
986 | hid_fixup_sony_ps3_controller(interface_to_usbdev(intf), | ||
987 | intf->cur_altsetting->desc.bInterfaceNumber); | ||
988 | |||
989 | printk(KERN_INFO); | ||
990 | |||
991 | if (hid->claimed & HID_CLAIMED_INPUT) | ||
992 | printk("input"); | ||
993 | if (hid->claimed == (HID_CLAIMED_INPUT | HID_CLAIMED_HIDDEV)) | ||
994 | printk(","); | ||
995 | if (hid->claimed & HID_CLAIMED_HIDDEV) | ||
996 | printk("hiddev%d", hid->minor); | ||
997 | |||
998 | c = "Device"; | ||
999 | for (i = 0; i < hid->maxcollection; i++) { | ||
1000 | if (hid->collection[i].type == HID_COLLECTION_APPLICATION && | ||
1001 | (hid->collection[i].usage & HID_USAGE_PAGE) == HID_UP_GENDESK && | ||
1002 | (hid->collection[i].usage & 0xffff) < ARRAY_SIZE(hid_types)) { | ||
1003 | c = hid_types[hid->collection[i].usage & 0xffff]; | ||
1004 | break; | ||
1005 | } | ||
1006 | } | ||
1007 | |||
1008 | usb_make_path(interface_to_usbdev(intf), path, 63); | ||
1009 | |||
1010 | printk(": USB HID v%x.%02x %s [%s] on %s\n", | ||
1011 | hid->version >> 8, hid->version & 0xff, c, hid->name, path); | ||
1012 | |||
1013 | return 0; | ||
1014 | } | ||
1015 | |||
1016 | static int hid_suspend(struct usb_interface *intf, pm_message_t message) | ||
1017 | { | ||
1018 | struct hid_device *hid = usb_get_intfdata (intf); | ||
1019 | struct usbhid_device *usbhid = hid->driver_data; | ||
1020 | |||
1021 | spin_lock_irq(&usbhid->inlock); /* Sync with error handler */ | ||
1022 | set_bit(HID_SUSPENDED, &usbhid->iofl); | ||
1023 | spin_unlock_irq(&usbhid->inlock); | ||
1024 | del_timer(&usbhid->io_retry); | ||
1025 | usb_kill_urb(usbhid->urbin); | ||
1026 | dev_dbg(&intf->dev, "suspend\n"); | ||
1027 | return 0; | ||
1028 | } | ||
1029 | |||
1030 | static int hid_resume(struct usb_interface *intf) | ||
1031 | { | ||
1032 | struct hid_device *hid = usb_get_intfdata (intf); | ||
1033 | struct usbhid_device *usbhid = hid->driver_data; | ||
1034 | int status; | ||
1035 | |||
1036 | clear_bit(HID_SUSPENDED, &usbhid->iofl); | ||
1037 | usbhid->retry_delay = 0; | ||
1038 | status = hid_start_in(hid); | ||
1039 | dev_dbg(&intf->dev, "resume status %d\n", status); | ||
1040 | return status; | ||
1041 | } | ||
1042 | |||
1043 | /* Treat USB reset pretty much the same as suspend/resume */ | ||
1044 | static void hid_pre_reset(struct usb_interface *intf) | ||
1045 | { | ||
1046 | /* FIXME: What if the interface is already suspended? */ | ||
1047 | hid_suspend(intf, PMSG_ON); | ||
1048 | } | ||
1049 | |||
1050 | static void hid_post_reset(struct usb_interface *intf) | ||
1051 | { | ||
1052 | struct usb_device *dev = interface_to_usbdev (intf); | ||
1053 | |||
1054 | hid_set_idle(dev, intf->cur_altsetting->desc.bInterfaceNumber, 0, 0); | ||
1055 | /* FIXME: Any more reinitialization needed? */ | ||
1056 | |||
1057 | hid_resume(intf); | ||
1058 | } | ||
1059 | |||
1060 | static struct usb_device_id hid_usb_ids [] = { | ||
1061 | { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS, | ||
1062 | .bInterfaceClass = USB_INTERFACE_CLASS_HID }, | ||
1063 | { } /* Terminating entry */ | ||
1064 | }; | ||
1065 | |||
1066 | MODULE_DEVICE_TABLE (usb, hid_usb_ids); | ||
1067 | |||
1068 | static struct usb_driver hid_driver = { | ||
1069 | .name = "usbhid", | ||
1070 | .probe = hid_probe, | ||
1071 | .disconnect = hid_disconnect, | ||
1072 | .suspend = hid_suspend, | ||
1073 | .resume = hid_resume, | ||
1074 | .pre_reset = hid_pre_reset, | ||
1075 | .post_reset = hid_post_reset, | ||
1076 | .id_table = hid_usb_ids, | ||
1077 | }; | ||
1078 | |||
1079 | static int __init hid_init(void) | ||
1080 | { | ||
1081 | int retval; | ||
1082 | retval = usbhid_quirks_init(quirks_param); | ||
1083 | if (retval) | ||
1084 | goto usbhid_quirks_init_fail; | ||
1085 | retval = hiddev_init(); | ||
1086 | if (retval) | ||
1087 | goto hiddev_init_fail; | ||
1088 | retval = usb_register(&hid_driver); | ||
1089 | if (retval) | ||
1090 | goto usb_register_fail; | ||
1091 | info(DRIVER_VERSION ":" DRIVER_DESC); | ||
1092 | |||
1093 | return 0; | ||
1094 | usb_register_fail: | ||
1095 | hiddev_exit(); | ||
1096 | hiddev_init_fail: | ||
1097 | usbhid_quirks_exit(); | ||
1098 | usbhid_quirks_init_fail: | ||
1099 | return retval; | ||
1100 | } | ||
1101 | |||
1102 | static void __exit hid_exit(void) | ||
1103 | { | ||
1104 | usb_deregister(&hid_driver); | ||
1105 | hiddev_exit(); | ||
1106 | usbhid_quirks_exit(); | ||
1107 | } | ||
1108 | |||
1109 | module_init(hid_init); | ||
1110 | module_exit(hid_exit); | ||
1111 | |||
1112 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
1113 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
1114 | MODULE_LICENSE(DRIVER_LICENSE); | ||
diff --git a/drivers/hid/usbhid/hid-ff.c b/drivers/hid/usbhid/hid-ff.c new file mode 100644 index 000000000000..23431fbbc3d7 --- /dev/null +++ b/drivers/hid/usbhid/hid-ff.c | |||
@@ -0,0 +1,91 @@ | |||
1 | /* | ||
2 | * $Id: hid-ff.c,v 1.2 2002/04/18 22:02:47 jdeneux Exp $ | ||
3 | * | ||
4 | * Force feedback support for hid devices. | ||
5 | * Not all hid devices use the same protocol. For example, some use PID, | ||
6 | * other use their own proprietary procotol. | ||
7 | * | ||
8 | * Copyright (c) 2002-2004 Johann Deneux | ||
9 | */ | ||
10 | |||
11 | /* | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
25 | * | ||
26 | * Should you need to contact me, the author, you can do so by | ||
27 | * e-mail - mail your message to <johann.deneux@it.uu.se> | ||
28 | */ | ||
29 | |||
30 | #include <linux/input.h> | ||
31 | |||
32 | #undef DEBUG | ||
33 | #include <linux/usb.h> | ||
34 | |||
35 | #include <linux/hid.h> | ||
36 | #include "usbhid.h" | ||
37 | |||
38 | /* | ||
39 | * This table contains pointers to initializers. To add support for new | ||
40 | * devices, you need to add the USB vendor and product ids here. | ||
41 | */ | ||
42 | struct hid_ff_initializer { | ||
43 | u16 idVendor; | ||
44 | u16 idProduct; | ||
45 | int (*init)(struct hid_device*); | ||
46 | }; | ||
47 | |||
48 | /* | ||
49 | * We try pidff when no other driver is found because PID is the | ||
50 | * standards compliant way of implementing force feedback in HID. | ||
51 | * pidff_init() will quickly abort if the device doesn't appear to | ||
52 | * be a PID device | ||
53 | */ | ||
54 | static struct hid_ff_initializer inits[] = { | ||
55 | #ifdef CONFIG_LOGITECH_FF | ||
56 | { 0x46d, 0xc211, hid_lgff_init }, /* Logitech Cordless rumble pad */ | ||
57 | { 0x46d, 0xc219, hid_lgff_init }, /* Logitech Cordless rumble pad 2 */ | ||
58 | { 0x46d, 0xc283, hid_lgff_init }, /* Logitech Wingman Force 3d */ | ||
59 | { 0x46d, 0xc286, hid_lgff_init }, /* Logitech Force 3D Pro Joystick */ | ||
60 | { 0x46d, 0xc294, hid_lgff_init }, /* Logitech Formula Force EX */ | ||
61 | { 0x46d, 0xc295, hid_lgff_init }, /* Logitech MOMO force wheel */ | ||
62 | { 0x46d, 0xca03, hid_lgff_init }, /* Logitech MOMO force wheel */ | ||
63 | #endif | ||
64 | #ifdef CONFIG_PANTHERLORD_FF | ||
65 | { 0x810, 0x0001, hid_plff_init }, | ||
66 | #endif | ||
67 | #ifdef CONFIG_THRUSTMASTER_FF | ||
68 | { 0x44f, 0xb300, hid_tmff_init }, | ||
69 | { 0x44f, 0xb304, hid_tmff_init }, | ||
70 | #endif | ||
71 | #ifdef CONFIG_ZEROPLUS_FF | ||
72 | { 0xc12, 0x0005, hid_zpff_init }, | ||
73 | { 0xc12, 0x0030, hid_zpff_init }, | ||
74 | #endif | ||
75 | { 0, 0, hid_pidff_init} /* Matches anything */ | ||
76 | }; | ||
77 | |||
78 | int hid_ff_init(struct hid_device* hid) | ||
79 | { | ||
80 | struct hid_ff_initializer *init; | ||
81 | int vendor = le16_to_cpu(hid_to_usb_dev(hid)->descriptor.idVendor); | ||
82 | int product = le16_to_cpu(hid_to_usb_dev(hid)->descriptor.idProduct); | ||
83 | |||
84 | for (init = inits; init->idVendor; init++) | ||
85 | if (init->idVendor == vendor && init->idProduct == product) | ||
86 | break; | ||
87 | |||
88 | return init->init(hid); | ||
89 | } | ||
90 | EXPORT_SYMBOL_GPL(hid_ff_init); | ||
91 | |||
diff --git a/drivers/hid/usbhid/hid-lgff.c b/drivers/hid/usbhid/hid-lgff.c new file mode 100644 index 000000000000..92d2553f17b6 --- /dev/null +++ b/drivers/hid/usbhid/hid-lgff.c | |||
@@ -0,0 +1,151 @@ | |||
1 | /* | ||
2 | * Force feedback support for hid-compliant for some of the devices from | ||
3 | * Logitech, namely: | ||
4 | * - WingMan Cordless RumblePad | ||
5 | * - WingMan Force 3D | ||
6 | * | ||
7 | * Copyright (c) 2002-2004 Johann Deneux | ||
8 | * Copyright (c) 2006 Anssi Hannula <anssi.hannula@gmail.com> | ||
9 | */ | ||
10 | |||
11 | /* | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
25 | * | ||
26 | * Should you need to contact me, the author, you can do so by | ||
27 | * e-mail - mail your message to <johann.deneux@it.uu.se> | ||
28 | */ | ||
29 | |||
30 | #include <linux/input.h> | ||
31 | #include <linux/usb.h> | ||
32 | #include <linux/hid.h> | ||
33 | #include "usbhid.h" | ||
34 | |||
35 | struct dev_type { | ||
36 | u16 idVendor; | ||
37 | u16 idProduct; | ||
38 | const signed short *ff; | ||
39 | }; | ||
40 | |||
41 | static const signed short ff_rumble[] = { | ||
42 | FF_RUMBLE, | ||
43 | -1 | ||
44 | }; | ||
45 | |||
46 | static const signed short ff_joystick[] = { | ||
47 | FF_CONSTANT, | ||
48 | -1 | ||
49 | }; | ||
50 | |||
51 | static const struct dev_type devices[] = { | ||
52 | { 0x046d, 0xc211, ff_rumble }, | ||
53 | { 0x046d, 0xc219, ff_rumble }, | ||
54 | { 0x046d, 0xc283, ff_joystick }, | ||
55 | { 0x046d, 0xc286, ff_joystick }, | ||
56 | { 0x046d, 0xc294, ff_joystick }, | ||
57 | { 0x046d, 0xc295, ff_joystick }, | ||
58 | { 0x046d, 0xca03, ff_joystick }, | ||
59 | }; | ||
60 | |||
61 | static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *effect) | ||
62 | { | ||
63 | struct hid_device *hid = dev->private; | ||
64 | struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; | ||
65 | struct hid_report *report = list_entry(report_list->next, struct hid_report, list); | ||
66 | int x, y; | ||
67 | unsigned int left, right; | ||
68 | |||
69 | #define CLAMP(x) if (x < 0) x = 0; if (x > 0xff) x = 0xff | ||
70 | |||
71 | switch (effect->type) { | ||
72 | case FF_CONSTANT: | ||
73 | x = effect->u.ramp.start_level + 0x7f; /* 0x7f is center */ | ||
74 | y = effect->u.ramp.end_level + 0x7f; | ||
75 | CLAMP(x); | ||
76 | CLAMP(y); | ||
77 | report->field[0]->value[0] = 0x51; | ||
78 | report->field[0]->value[1] = 0x08; | ||
79 | report->field[0]->value[2] = x; | ||
80 | report->field[0]->value[3] = y; | ||
81 | dbg("(x, y)=(%04x, %04x)", x, y); | ||
82 | usbhid_submit_report(hid, report, USB_DIR_OUT); | ||
83 | break; | ||
84 | |||
85 | case FF_RUMBLE: | ||
86 | right = effect->u.rumble.strong_magnitude; | ||
87 | left = effect->u.rumble.weak_magnitude; | ||
88 | right = right * 0xff / 0xffff; | ||
89 | left = left * 0xff / 0xffff; | ||
90 | CLAMP(left); | ||
91 | CLAMP(right); | ||
92 | report->field[0]->value[0] = 0x42; | ||
93 | report->field[0]->value[1] = 0x00; | ||
94 | report->field[0]->value[2] = left; | ||
95 | report->field[0]->value[3] = right; | ||
96 | dbg("(left, right)=(%04x, %04x)", left, right); | ||
97 | usbhid_submit_report(hid, report, USB_DIR_OUT); | ||
98 | break; | ||
99 | } | ||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | int hid_lgff_init(struct hid_device* hid) | ||
104 | { | ||
105 | struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); | ||
106 | struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; | ||
107 | struct input_dev *dev = hidinput->input; | ||
108 | struct hid_report *report; | ||
109 | struct hid_field *field; | ||
110 | const signed short *ff_bits = ff_joystick; | ||
111 | int error; | ||
112 | int i; | ||
113 | |||
114 | /* Find the report to use */ | ||
115 | if (list_empty(report_list)) { | ||
116 | err("No output report found"); | ||
117 | return -1; | ||
118 | } | ||
119 | |||
120 | /* Check that the report looks ok */ | ||
121 | report = list_entry(report_list->next, struct hid_report, list); | ||
122 | if (!report) { | ||
123 | err("NULL output report"); | ||
124 | return -1; | ||
125 | } | ||
126 | |||
127 | field = report->field[0]; | ||
128 | if (!field) { | ||
129 | err("NULL field"); | ||
130 | return -1; | ||
131 | } | ||
132 | |||
133 | for (i = 0; i < ARRAY_SIZE(devices); i++) { | ||
134 | if (dev->id.vendor == devices[i].idVendor && | ||
135 | dev->id.product == devices[i].idProduct) { | ||
136 | ff_bits = devices[i].ff; | ||
137 | break; | ||
138 | } | ||
139 | } | ||
140 | |||
141 | for (i = 0; ff_bits[i] >= 0; i++) | ||
142 | set_bit(ff_bits[i], dev->ffbit); | ||
143 | |||
144 | error = input_ff_create_memless(dev, NULL, hid_lgff_play); | ||
145 | if (error) | ||
146 | return error; | ||
147 | |||
148 | printk(KERN_INFO "Force feedback for Logitech force feedback devices by Johann Deneux <johann.deneux@it.uu.se>\n"); | ||
149 | |||
150 | return 0; | ||
151 | } | ||
diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c new file mode 100644 index 000000000000..f5a90e950e6b --- /dev/null +++ b/drivers/hid/usbhid/hid-pidff.c | |||
@@ -0,0 +1,1331 @@ | |||
1 | /* | ||
2 | * Force feedback driver for USB HID PID compliant devices | ||
3 | * | ||
4 | * Copyright (c) 2005, 2006 Anssi Hannula <anssi.hannula@gmail.com> | ||
5 | */ | ||
6 | |||
7 | /* | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | */ | ||
22 | |||
23 | /* #define DEBUG */ | ||
24 | |||
25 | #define debug(format, arg...) pr_debug("hid-pidff: " format "\n" , ## arg) | ||
26 | |||
27 | #include <linux/input.h> | ||
28 | #include <linux/usb.h> | ||
29 | |||
30 | #include <linux/hid.h> | ||
31 | |||
32 | #include "usbhid.h" | ||
33 | |||
34 | #define PID_EFFECTS_MAX 64 | ||
35 | |||
36 | /* Report usage table used to put reports into an array */ | ||
37 | |||
38 | #define PID_SET_EFFECT 0 | ||
39 | #define PID_EFFECT_OPERATION 1 | ||
40 | #define PID_DEVICE_GAIN 2 | ||
41 | #define PID_POOL 3 | ||
42 | #define PID_BLOCK_LOAD 4 | ||
43 | #define PID_BLOCK_FREE 5 | ||
44 | #define PID_DEVICE_CONTROL 6 | ||
45 | #define PID_CREATE_NEW_EFFECT 7 | ||
46 | |||
47 | #define PID_REQUIRED_REPORTS 7 | ||
48 | |||
49 | #define PID_SET_ENVELOPE 8 | ||
50 | #define PID_SET_CONDITION 9 | ||
51 | #define PID_SET_PERIODIC 10 | ||
52 | #define PID_SET_CONSTANT 11 | ||
53 | #define PID_SET_RAMP 12 | ||
54 | static const u8 pidff_reports[] = { | ||
55 | 0x21, 0x77, 0x7d, 0x7f, 0x89, 0x90, 0x96, 0xab, | ||
56 | 0x5a, 0x5f, 0x6e, 0x73, 0x74 | ||
57 | }; | ||
58 | |||
59 | /* device_control is really 0x95, but 0x96 specified as it is the usage of | ||
60 | the only field in that report */ | ||
61 | |||
62 | /* Value usage tables used to put fields and values into arrays */ | ||
63 | |||
64 | #define PID_EFFECT_BLOCK_INDEX 0 | ||
65 | |||
66 | #define PID_DURATION 1 | ||
67 | #define PID_GAIN 2 | ||
68 | #define PID_TRIGGER_BUTTON 3 | ||
69 | #define PID_TRIGGER_REPEAT_INT 4 | ||
70 | #define PID_DIRECTION_ENABLE 5 | ||
71 | #define PID_START_DELAY 6 | ||
72 | static const u8 pidff_set_effect[] = { | ||
73 | 0x22, 0x50, 0x52, 0x53, 0x54, 0x56, 0xa7 | ||
74 | }; | ||
75 | |||
76 | #define PID_ATTACK_LEVEL 1 | ||
77 | #define PID_ATTACK_TIME 2 | ||
78 | #define PID_FADE_LEVEL 3 | ||
79 | #define PID_FADE_TIME 4 | ||
80 | static const u8 pidff_set_envelope[] = { 0x22, 0x5b, 0x5c, 0x5d, 0x5e }; | ||
81 | |||
82 | #define PID_PARAM_BLOCK_OFFSET 1 | ||
83 | #define PID_CP_OFFSET 2 | ||
84 | #define PID_POS_COEFFICIENT 3 | ||
85 | #define PID_NEG_COEFFICIENT 4 | ||
86 | #define PID_POS_SATURATION 5 | ||
87 | #define PID_NEG_SATURATION 6 | ||
88 | #define PID_DEAD_BAND 7 | ||
89 | static const u8 pidff_set_condition[] = { | ||
90 | 0x22, 0x23, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65 | ||
91 | }; | ||
92 | |||
93 | #define PID_MAGNITUDE 1 | ||
94 | #define PID_OFFSET 2 | ||
95 | #define PID_PHASE 3 | ||
96 | #define PID_PERIOD 4 | ||
97 | static const u8 pidff_set_periodic[] = { 0x22, 0x70, 0x6f, 0x71, 0x72 }; | ||
98 | static const u8 pidff_set_constant[] = { 0x22, 0x70 }; | ||
99 | |||
100 | #define PID_RAMP_START 1 | ||
101 | #define PID_RAMP_END 2 | ||
102 | static const u8 pidff_set_ramp[] = { 0x22, 0x75, 0x76 }; | ||
103 | |||
104 | #define PID_RAM_POOL_AVAILABLE 1 | ||
105 | static const u8 pidff_block_load[] = { 0x22, 0xac }; | ||
106 | |||
107 | #define PID_LOOP_COUNT 1 | ||
108 | static const u8 pidff_effect_operation[] = { 0x22, 0x7c }; | ||
109 | |||
110 | static const u8 pidff_block_free[] = { 0x22 }; | ||
111 | |||
112 | #define PID_DEVICE_GAIN_FIELD 0 | ||
113 | static const u8 pidff_device_gain[] = { 0x7e }; | ||
114 | |||
115 | #define PID_RAM_POOL_SIZE 0 | ||
116 | #define PID_SIMULTANEOUS_MAX 1 | ||
117 | #define PID_DEVICE_MANAGED_POOL 2 | ||
118 | static const u8 pidff_pool[] = { 0x80, 0x83, 0xa9 }; | ||
119 | |||
120 | /* Special field key tables used to put special field keys into arrays */ | ||
121 | |||
122 | #define PID_ENABLE_ACTUATORS 0 | ||
123 | #define PID_RESET 1 | ||
124 | static const u8 pidff_device_control[] = { 0x97, 0x9a }; | ||
125 | |||
126 | #define PID_CONSTANT 0 | ||
127 | #define PID_RAMP 1 | ||
128 | #define PID_SQUARE 2 | ||
129 | #define PID_SINE 3 | ||
130 | #define PID_TRIANGLE 4 | ||
131 | #define PID_SAW_UP 5 | ||
132 | #define PID_SAW_DOWN 6 | ||
133 | #define PID_SPRING 7 | ||
134 | #define PID_DAMPER 8 | ||
135 | #define PID_INERTIA 9 | ||
136 | #define PID_FRICTION 10 | ||
137 | static const u8 pidff_effect_types[] = { | ||
138 | 0x26, 0x27, 0x30, 0x31, 0x32, 0x33, 0x34, | ||
139 | 0x40, 0x41, 0x42, 0x43 | ||
140 | }; | ||
141 | |||
142 | #define PID_BLOCK_LOAD_SUCCESS 0 | ||
143 | #define PID_BLOCK_LOAD_FULL 1 | ||
144 | static const u8 pidff_block_load_status[] = { 0x8c, 0x8d }; | ||
145 | |||
146 | #define PID_EFFECT_START 0 | ||
147 | #define PID_EFFECT_STOP 1 | ||
148 | static const u8 pidff_effect_operation_status[] = { 0x79, 0x7b }; | ||
149 | |||
150 | struct pidff_usage { | ||
151 | struct hid_field *field; | ||
152 | s32 *value; | ||
153 | }; | ||
154 | |||
155 | struct pidff_device { | ||
156 | struct hid_device *hid; | ||
157 | |||
158 | struct hid_report *reports[sizeof(pidff_reports)]; | ||
159 | |||
160 | struct pidff_usage set_effect[sizeof(pidff_set_effect)]; | ||
161 | struct pidff_usage set_envelope[sizeof(pidff_set_envelope)]; | ||
162 | struct pidff_usage set_condition[sizeof(pidff_set_condition)]; | ||
163 | struct pidff_usage set_periodic[sizeof(pidff_set_periodic)]; | ||
164 | struct pidff_usage set_constant[sizeof(pidff_set_constant)]; | ||
165 | struct pidff_usage set_ramp[sizeof(pidff_set_ramp)]; | ||
166 | |||
167 | struct pidff_usage device_gain[sizeof(pidff_device_gain)]; | ||
168 | struct pidff_usage block_load[sizeof(pidff_block_load)]; | ||
169 | struct pidff_usage pool[sizeof(pidff_pool)]; | ||
170 | struct pidff_usage effect_operation[sizeof(pidff_effect_operation)]; | ||
171 | struct pidff_usage block_free[sizeof(pidff_block_free)]; | ||
172 | |||
173 | /* Special field is a field that is not composed of | ||
174 | usage<->value pairs that pidff_usage values are */ | ||
175 | |||
176 | /* Special field in create_new_effect */ | ||
177 | struct hid_field *create_new_effect_type; | ||
178 | |||
179 | /* Special fields in set_effect */ | ||
180 | struct hid_field *set_effect_type; | ||
181 | struct hid_field *effect_direction; | ||
182 | |||
183 | /* Special field in device_control */ | ||
184 | struct hid_field *device_control; | ||
185 | |||
186 | /* Special field in block_load */ | ||
187 | struct hid_field *block_load_status; | ||
188 | |||
189 | /* Special field in effect_operation */ | ||
190 | struct hid_field *effect_operation_status; | ||
191 | |||
192 | int control_id[sizeof(pidff_device_control)]; | ||
193 | int type_id[sizeof(pidff_effect_types)]; | ||
194 | int status_id[sizeof(pidff_block_load_status)]; | ||
195 | int operation_id[sizeof(pidff_effect_operation_status)]; | ||
196 | |||
197 | int pid_id[PID_EFFECTS_MAX]; | ||
198 | }; | ||
199 | |||
200 | /* | ||
201 | * Scale an unsigned value with range 0..max for the given field | ||
202 | */ | ||
203 | static int pidff_rescale(int i, int max, struct hid_field *field) | ||
204 | { | ||
205 | return i * (field->logical_maximum - field->logical_minimum) / max + | ||
206 | field->logical_minimum; | ||
207 | } | ||
208 | |||
209 | /* | ||
210 | * Scale a signed value in range -0x8000..0x7fff for the given field | ||
211 | */ | ||
212 | static int pidff_rescale_signed(int i, struct hid_field *field) | ||
213 | { | ||
214 | return i == 0 ? 0 : i > | ||
215 | 0 ? i * field->logical_maximum / 0x7fff : i * | ||
216 | field->logical_minimum / -0x8000; | ||
217 | } | ||
218 | |||
219 | static void pidff_set(struct pidff_usage *usage, u16 value) | ||
220 | { | ||
221 | usage->value[0] = pidff_rescale(value, 0xffff, usage->field); | ||
222 | debug("calculated from %d to %d", value, usage->value[0]); | ||
223 | } | ||
224 | |||
225 | static void pidff_set_signed(struct pidff_usage *usage, s16 value) | ||
226 | { | ||
227 | if (usage->field->logical_minimum < 0) | ||
228 | usage->value[0] = pidff_rescale_signed(value, usage->field); | ||
229 | else { | ||
230 | if (value < 0) | ||
231 | usage->value[0] = | ||
232 | pidff_rescale(-value, 0x8000, usage->field); | ||
233 | else | ||
234 | usage->value[0] = | ||
235 | pidff_rescale(value, 0x7fff, usage->field); | ||
236 | } | ||
237 | debug("calculated from %d to %d", value, usage->value[0]); | ||
238 | } | ||
239 | |||
240 | /* | ||
241 | * Send envelope report to the device | ||
242 | */ | ||
243 | static void pidff_set_envelope_report(struct pidff_device *pidff, | ||
244 | struct ff_envelope *envelope) | ||
245 | { | ||
246 | pidff->set_envelope[PID_EFFECT_BLOCK_INDEX].value[0] = | ||
247 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; | ||
248 | |||
249 | pidff->set_envelope[PID_ATTACK_LEVEL].value[0] = | ||
250 | pidff_rescale(envelope->attack_level > | ||
251 | 0x7fff ? 0x7fff : envelope->attack_level, 0x7fff, | ||
252 | pidff->set_envelope[PID_ATTACK_LEVEL].field); | ||
253 | pidff->set_envelope[PID_FADE_LEVEL].value[0] = | ||
254 | pidff_rescale(envelope->fade_level > | ||
255 | 0x7fff ? 0x7fff : envelope->fade_level, 0x7fff, | ||
256 | pidff->set_envelope[PID_FADE_LEVEL].field); | ||
257 | |||
258 | pidff->set_envelope[PID_ATTACK_TIME].value[0] = envelope->attack_length; | ||
259 | pidff->set_envelope[PID_FADE_TIME].value[0] = envelope->fade_length; | ||
260 | |||
261 | debug("attack %u => %d", envelope->attack_level, | ||
262 | pidff->set_envelope[PID_ATTACK_LEVEL].value[0]); | ||
263 | |||
264 | usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_ENVELOPE], | ||
265 | USB_DIR_OUT); | ||
266 | } | ||
267 | |||
268 | /* | ||
269 | * Test if the new envelope differs from old one | ||
270 | */ | ||
271 | static int pidff_needs_set_envelope(struct ff_envelope *envelope, | ||
272 | struct ff_envelope *old) | ||
273 | { | ||
274 | return envelope->attack_level != old->attack_level || | ||
275 | envelope->fade_level != old->fade_level || | ||
276 | envelope->attack_length != old->attack_length || | ||
277 | envelope->fade_length != old->fade_length; | ||
278 | } | ||
279 | |||
280 | /* | ||
281 | * Send constant force report to the device | ||
282 | */ | ||
283 | static void pidff_set_constant_force_report(struct pidff_device *pidff, | ||
284 | struct ff_effect *effect) | ||
285 | { | ||
286 | pidff->set_constant[PID_EFFECT_BLOCK_INDEX].value[0] = | ||
287 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; | ||
288 | pidff_set_signed(&pidff->set_constant[PID_MAGNITUDE], | ||
289 | effect->u.constant.level); | ||
290 | |||
291 | usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_CONSTANT], | ||
292 | USB_DIR_OUT); | ||
293 | } | ||
294 | |||
295 | /* | ||
296 | * Test if the constant parameters have changed between effects | ||
297 | */ | ||
298 | static int pidff_needs_set_constant(struct ff_effect *effect, | ||
299 | struct ff_effect *old) | ||
300 | { | ||
301 | return effect->u.constant.level != old->u.constant.level; | ||
302 | } | ||
303 | |||
304 | /* | ||
305 | * Send set effect report to the device | ||
306 | */ | ||
307 | static void pidff_set_effect_report(struct pidff_device *pidff, | ||
308 | struct ff_effect *effect) | ||
309 | { | ||
310 | pidff->set_effect[PID_EFFECT_BLOCK_INDEX].value[0] = | ||
311 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; | ||
312 | pidff->set_effect_type->value[0] = | ||
313 | pidff->create_new_effect_type->value[0]; | ||
314 | pidff->set_effect[PID_DURATION].value[0] = effect->replay.length; | ||
315 | pidff->set_effect[PID_TRIGGER_BUTTON].value[0] = effect->trigger.button; | ||
316 | pidff->set_effect[PID_TRIGGER_REPEAT_INT].value[0] = | ||
317 | effect->trigger.interval; | ||
318 | pidff->set_effect[PID_GAIN].value[0] = | ||
319 | pidff->set_effect[PID_GAIN].field->logical_maximum; | ||
320 | pidff->set_effect[PID_DIRECTION_ENABLE].value[0] = 1; | ||
321 | pidff->effect_direction->value[0] = | ||
322 | pidff_rescale(effect->direction, 0xffff, | ||
323 | pidff->effect_direction); | ||
324 | pidff->set_effect[PID_START_DELAY].value[0] = effect->replay.delay; | ||
325 | |||
326 | usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT], | ||
327 | USB_DIR_OUT); | ||
328 | } | ||
329 | |||
330 | /* | ||
331 | * Test if the values used in set_effect have changed | ||
332 | */ | ||
333 | static int pidff_needs_set_effect(struct ff_effect *effect, | ||
334 | struct ff_effect *old) | ||
335 | { | ||
336 | return effect->replay.length != old->replay.length || | ||
337 | effect->trigger.interval != old->trigger.interval || | ||
338 | effect->trigger.button != old->trigger.button || | ||
339 | effect->direction != old->direction || | ||
340 | effect->replay.delay != old->replay.delay; | ||
341 | } | ||
342 | |||
343 | /* | ||
344 | * Send periodic effect report to the device | ||
345 | */ | ||
346 | static void pidff_set_periodic_report(struct pidff_device *pidff, | ||
347 | struct ff_effect *effect) | ||
348 | { | ||
349 | pidff->set_periodic[PID_EFFECT_BLOCK_INDEX].value[0] = | ||
350 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; | ||
351 | pidff_set_signed(&pidff->set_periodic[PID_MAGNITUDE], | ||
352 | effect->u.periodic.magnitude); | ||
353 | pidff_set_signed(&pidff->set_periodic[PID_OFFSET], | ||
354 | effect->u.periodic.offset); | ||
355 | pidff_set(&pidff->set_periodic[PID_PHASE], effect->u.periodic.phase); | ||
356 | pidff->set_periodic[PID_PERIOD].value[0] = effect->u.periodic.period; | ||
357 | |||
358 | usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_PERIODIC], | ||
359 | USB_DIR_OUT); | ||
360 | |||
361 | } | ||
362 | |||
363 | /* | ||
364 | * Test if periodic effect parameters have changed | ||
365 | */ | ||
366 | static int pidff_needs_set_periodic(struct ff_effect *effect, | ||
367 | struct ff_effect *old) | ||
368 | { | ||
369 | return effect->u.periodic.magnitude != old->u.periodic.magnitude || | ||
370 | effect->u.periodic.offset != old->u.periodic.offset || | ||
371 | effect->u.periodic.phase != old->u.periodic.phase || | ||
372 | effect->u.periodic.period != old->u.periodic.period; | ||
373 | } | ||
374 | |||
375 | /* | ||
376 | * Send condition effect reports to the device | ||
377 | */ | ||
378 | static void pidff_set_condition_report(struct pidff_device *pidff, | ||
379 | struct ff_effect *effect) | ||
380 | { | ||
381 | int i; | ||
382 | |||
383 | pidff->set_condition[PID_EFFECT_BLOCK_INDEX].value[0] = | ||
384 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; | ||
385 | |||
386 | for (i = 0; i < 2; i++) { | ||
387 | pidff->set_condition[PID_PARAM_BLOCK_OFFSET].value[0] = i; | ||
388 | pidff_set_signed(&pidff->set_condition[PID_CP_OFFSET], | ||
389 | effect->u.condition[i].center); | ||
390 | pidff_set_signed(&pidff->set_condition[PID_POS_COEFFICIENT], | ||
391 | effect->u.condition[i].right_coeff); | ||
392 | pidff_set_signed(&pidff->set_condition[PID_NEG_COEFFICIENT], | ||
393 | effect->u.condition[i].left_coeff); | ||
394 | pidff_set(&pidff->set_condition[PID_POS_SATURATION], | ||
395 | effect->u.condition[i].right_saturation); | ||
396 | pidff_set(&pidff->set_condition[PID_NEG_SATURATION], | ||
397 | effect->u.condition[i].left_saturation); | ||
398 | pidff_set(&pidff->set_condition[PID_DEAD_BAND], | ||
399 | effect->u.condition[i].deadband); | ||
400 | usbhid_wait_io(pidff->hid); | ||
401 | usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_CONDITION], | ||
402 | USB_DIR_OUT); | ||
403 | } | ||
404 | } | ||
405 | |||
406 | /* | ||
407 | * Test if condition effect parameters have changed | ||
408 | */ | ||
409 | static int pidff_needs_set_condition(struct ff_effect *effect, | ||
410 | struct ff_effect *old) | ||
411 | { | ||
412 | int i; | ||
413 | int ret = 0; | ||
414 | |||
415 | for (i = 0; i < 2; i++) { | ||
416 | struct ff_condition_effect *cond = &effect->u.condition[i]; | ||
417 | struct ff_condition_effect *old_cond = &old->u.condition[i]; | ||
418 | |||
419 | ret |= cond->center != old_cond->center || | ||
420 | cond->right_coeff != old_cond->right_coeff || | ||
421 | cond->left_coeff != old_cond->left_coeff || | ||
422 | cond->right_saturation != old_cond->right_saturation || | ||
423 | cond->left_saturation != old_cond->left_saturation || | ||
424 | cond->deadband != old_cond->deadband; | ||
425 | } | ||
426 | |||
427 | return ret; | ||
428 | } | ||
429 | |||
430 | /* | ||
431 | * Send ramp force report to the device | ||
432 | */ | ||
433 | static void pidff_set_ramp_force_report(struct pidff_device *pidff, | ||
434 | struct ff_effect *effect) | ||
435 | { | ||
436 | pidff->set_ramp[PID_EFFECT_BLOCK_INDEX].value[0] = | ||
437 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; | ||
438 | pidff_set_signed(&pidff->set_ramp[PID_RAMP_START], | ||
439 | effect->u.ramp.start_level); | ||
440 | pidff_set_signed(&pidff->set_ramp[PID_RAMP_END], | ||
441 | effect->u.ramp.end_level); | ||
442 | usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_RAMP], | ||
443 | USB_DIR_OUT); | ||
444 | } | ||
445 | |||
446 | /* | ||
447 | * Test if ramp force parameters have changed | ||
448 | */ | ||
449 | static int pidff_needs_set_ramp(struct ff_effect *effect, struct ff_effect *old) | ||
450 | { | ||
451 | return effect->u.ramp.start_level != old->u.ramp.start_level || | ||
452 | effect->u.ramp.end_level != old->u.ramp.end_level; | ||
453 | } | ||
454 | |||
455 | /* | ||
456 | * Send a request for effect upload to the device | ||
457 | * | ||
458 | * Returns 0 if device reported success, -ENOSPC if the device reported memory | ||
459 | * is full. Upon unknown response the function will retry for 60 times, if | ||
460 | * still unsuccessful -EIO is returned. | ||
461 | */ | ||
462 | static int pidff_request_effect_upload(struct pidff_device *pidff, int efnum) | ||
463 | { | ||
464 | int j; | ||
465 | |||
466 | pidff->create_new_effect_type->value[0] = efnum; | ||
467 | usbhid_submit_report(pidff->hid, pidff->reports[PID_CREATE_NEW_EFFECT], | ||
468 | USB_DIR_OUT); | ||
469 | debug("create_new_effect sent, type: %d", efnum); | ||
470 | |||
471 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0] = 0; | ||
472 | pidff->block_load_status->value[0] = 0; | ||
473 | usbhid_wait_io(pidff->hid); | ||
474 | |||
475 | for (j = 0; j < 60; j++) { | ||
476 | debug("pid_block_load requested"); | ||
477 | usbhid_submit_report(pidff->hid, pidff->reports[PID_BLOCK_LOAD], | ||
478 | USB_DIR_IN); | ||
479 | usbhid_wait_io(pidff->hid); | ||
480 | if (pidff->block_load_status->value[0] == | ||
481 | pidff->status_id[PID_BLOCK_LOAD_SUCCESS]) { | ||
482 | debug("device reported free memory: %d bytes", | ||
483 | pidff->block_load[PID_RAM_POOL_AVAILABLE].value ? | ||
484 | pidff->block_load[PID_RAM_POOL_AVAILABLE].value[0] : -1); | ||
485 | return 0; | ||
486 | } | ||
487 | if (pidff->block_load_status->value[0] == | ||
488 | pidff->status_id[PID_BLOCK_LOAD_FULL]) { | ||
489 | debug("not enough memory free: %d bytes", | ||
490 | pidff->block_load[PID_RAM_POOL_AVAILABLE].value ? | ||
491 | pidff->block_load[PID_RAM_POOL_AVAILABLE].value[0] : -1); | ||
492 | return -ENOSPC; | ||
493 | } | ||
494 | } | ||
495 | printk(KERN_ERR "hid-pidff: pid_block_load failed 60 times\n"); | ||
496 | return -EIO; | ||
497 | } | ||
498 | |||
499 | /* | ||
500 | * Play the effect with PID id n times | ||
501 | */ | ||
502 | static void pidff_playback_pid(struct pidff_device *pidff, int pid_id, int n) | ||
503 | { | ||
504 | pidff->effect_operation[PID_EFFECT_BLOCK_INDEX].value[0] = pid_id; | ||
505 | |||
506 | if (n == 0) { | ||
507 | pidff->effect_operation_status->value[0] = | ||
508 | pidff->operation_id[PID_EFFECT_STOP]; | ||
509 | } else { | ||
510 | pidff->effect_operation_status->value[0] = | ||
511 | pidff->operation_id[PID_EFFECT_START]; | ||
512 | pidff->effect_operation[PID_LOOP_COUNT].value[0] = n; | ||
513 | } | ||
514 | |||
515 | usbhid_wait_io(pidff->hid); | ||
516 | usbhid_submit_report(pidff->hid, pidff->reports[PID_EFFECT_OPERATION], | ||
517 | USB_DIR_OUT); | ||
518 | } | ||
519 | |||
520 | /** | ||
521 | * Play the effect with effect id @effect_id for @value times | ||
522 | */ | ||
523 | static int pidff_playback(struct input_dev *dev, int effect_id, int value) | ||
524 | { | ||
525 | struct pidff_device *pidff = dev->ff->private; | ||
526 | |||
527 | pidff_playback_pid(pidff, pidff->pid_id[effect_id], value); | ||
528 | |||
529 | return 0; | ||
530 | } | ||
531 | |||
532 | /* | ||
533 | * Erase effect with PID id | ||
534 | */ | ||
535 | static void pidff_erase_pid(struct pidff_device *pidff, int pid_id) | ||
536 | { | ||
537 | pidff->block_free[PID_EFFECT_BLOCK_INDEX].value[0] = pid_id; | ||
538 | usbhid_submit_report(pidff->hid, pidff->reports[PID_BLOCK_FREE], | ||
539 | USB_DIR_OUT); | ||
540 | } | ||
541 | |||
542 | /* | ||
543 | * Stop and erase effect with effect_id | ||
544 | */ | ||
545 | static int pidff_erase_effect(struct input_dev *dev, int effect_id) | ||
546 | { | ||
547 | struct pidff_device *pidff = dev->ff->private; | ||
548 | int pid_id = pidff->pid_id[effect_id]; | ||
549 | |||
550 | debug("starting to erase %d/%d", effect_id, pidff->pid_id[effect_id]); | ||
551 | pidff_playback_pid(pidff, pid_id, 0); | ||
552 | pidff_erase_pid(pidff, pid_id); | ||
553 | |||
554 | return 0; | ||
555 | } | ||
556 | |||
557 | /* | ||
558 | * Effect upload handler | ||
559 | */ | ||
560 | static int pidff_upload_effect(struct input_dev *dev, struct ff_effect *effect, | ||
561 | struct ff_effect *old) | ||
562 | { | ||
563 | struct pidff_device *pidff = dev->ff->private; | ||
564 | int type_id; | ||
565 | int error; | ||
566 | |||
567 | switch (effect->type) { | ||
568 | case FF_CONSTANT: | ||
569 | if (!old) { | ||
570 | error = pidff_request_effect_upload(pidff, | ||
571 | pidff->type_id[PID_CONSTANT]); | ||
572 | if (error) | ||
573 | return error; | ||
574 | } | ||
575 | if (!old || pidff_needs_set_effect(effect, old)) | ||
576 | pidff_set_effect_report(pidff, effect); | ||
577 | if (!old || pidff_needs_set_constant(effect, old)) | ||
578 | pidff_set_constant_force_report(pidff, effect); | ||
579 | if (!old || | ||
580 | pidff_needs_set_envelope(&effect->u.constant.envelope, | ||
581 | &old->u.constant.envelope)) | ||
582 | pidff_set_envelope_report(pidff, | ||
583 | &effect->u.constant.envelope); | ||
584 | break; | ||
585 | |||
586 | case FF_PERIODIC: | ||
587 | if (!old) { | ||
588 | switch (effect->u.periodic.waveform) { | ||
589 | case FF_SQUARE: | ||
590 | type_id = PID_SQUARE; | ||
591 | break; | ||
592 | case FF_TRIANGLE: | ||
593 | type_id = PID_TRIANGLE; | ||
594 | break; | ||
595 | case FF_SINE: | ||
596 | type_id = PID_SINE; | ||
597 | break; | ||
598 | case FF_SAW_UP: | ||
599 | type_id = PID_SAW_UP; | ||
600 | break; | ||
601 | case FF_SAW_DOWN: | ||
602 | type_id = PID_SAW_DOWN; | ||
603 | break; | ||
604 | default: | ||
605 | printk(KERN_ERR | ||
606 | "hid-pidff: invalid waveform\n"); | ||
607 | return -EINVAL; | ||
608 | } | ||
609 | |||
610 | error = pidff_request_effect_upload(pidff, | ||
611 | pidff->type_id[type_id]); | ||
612 | if (error) | ||
613 | return error; | ||
614 | } | ||
615 | if (!old || pidff_needs_set_effect(effect, old)) | ||
616 | pidff_set_effect_report(pidff, effect); | ||
617 | if (!old || pidff_needs_set_periodic(effect, old)) | ||
618 | pidff_set_periodic_report(pidff, effect); | ||
619 | if (!old || | ||
620 | pidff_needs_set_envelope(&effect->u.periodic.envelope, | ||
621 | &old->u.periodic.envelope)) | ||
622 | pidff_set_envelope_report(pidff, | ||
623 | &effect->u.periodic.envelope); | ||
624 | break; | ||
625 | |||
626 | case FF_RAMP: | ||
627 | if (!old) { | ||
628 | error = pidff_request_effect_upload(pidff, | ||
629 | pidff->type_id[PID_RAMP]); | ||
630 | if (error) | ||
631 | return error; | ||
632 | } | ||
633 | if (!old || pidff_needs_set_effect(effect, old)) | ||
634 | pidff_set_effect_report(pidff, effect); | ||
635 | if (!old || pidff_needs_set_ramp(effect, old)) | ||
636 | pidff_set_ramp_force_report(pidff, effect); | ||
637 | if (!old || | ||
638 | pidff_needs_set_envelope(&effect->u.ramp.envelope, | ||
639 | &old->u.ramp.envelope)) | ||
640 | pidff_set_envelope_report(pidff, | ||
641 | &effect->u.ramp.envelope); | ||
642 | break; | ||
643 | |||
644 | case FF_SPRING: | ||
645 | if (!old) { | ||
646 | error = pidff_request_effect_upload(pidff, | ||
647 | pidff->type_id[PID_SPRING]); | ||
648 | if (error) | ||
649 | return error; | ||
650 | } | ||
651 | if (!old || pidff_needs_set_effect(effect, old)) | ||
652 | pidff_set_effect_report(pidff, effect); | ||
653 | if (!old || pidff_needs_set_condition(effect, old)) | ||
654 | pidff_set_condition_report(pidff, effect); | ||
655 | break; | ||
656 | |||
657 | case FF_FRICTION: | ||
658 | if (!old) { | ||
659 | error = pidff_request_effect_upload(pidff, | ||
660 | pidff->type_id[PID_FRICTION]); | ||
661 | if (error) | ||
662 | return error; | ||
663 | } | ||
664 | if (!old || pidff_needs_set_effect(effect, old)) | ||
665 | pidff_set_effect_report(pidff, effect); | ||
666 | if (!old || pidff_needs_set_condition(effect, old)) | ||
667 | pidff_set_condition_report(pidff, effect); | ||
668 | break; | ||
669 | |||
670 | case FF_DAMPER: | ||
671 | if (!old) { | ||
672 | error = pidff_request_effect_upload(pidff, | ||
673 | pidff->type_id[PID_DAMPER]); | ||
674 | if (error) | ||
675 | return error; | ||
676 | } | ||
677 | if (!old || pidff_needs_set_effect(effect, old)) | ||
678 | pidff_set_effect_report(pidff, effect); | ||
679 | if (!old || pidff_needs_set_condition(effect, old)) | ||
680 | pidff_set_condition_report(pidff, effect); | ||
681 | break; | ||
682 | |||
683 | case FF_INERTIA: | ||
684 | if (!old) { | ||
685 | error = pidff_request_effect_upload(pidff, | ||
686 | pidff->type_id[PID_INERTIA]); | ||
687 | if (error) | ||
688 | return error; | ||
689 | } | ||
690 | if (!old || pidff_needs_set_effect(effect, old)) | ||
691 | pidff_set_effect_report(pidff, effect); | ||
692 | if (!old || pidff_needs_set_condition(effect, old)) | ||
693 | pidff_set_condition_report(pidff, effect); | ||
694 | break; | ||
695 | |||
696 | default: | ||
697 | printk(KERN_ERR "hid-pidff: invalid type\n"); | ||
698 | return -EINVAL; | ||
699 | } | ||
700 | |||
701 | if (!old) | ||
702 | pidff->pid_id[effect->id] = | ||
703 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; | ||
704 | |||
705 | debug("uploaded"); | ||
706 | |||
707 | return 0; | ||
708 | } | ||
709 | |||
710 | /* | ||
711 | * set_gain() handler | ||
712 | */ | ||
713 | static void pidff_set_gain(struct input_dev *dev, u16 gain) | ||
714 | { | ||
715 | struct pidff_device *pidff = dev->ff->private; | ||
716 | |||
717 | pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], gain); | ||
718 | usbhid_submit_report(pidff->hid, pidff->reports[PID_DEVICE_GAIN], | ||
719 | USB_DIR_OUT); | ||
720 | } | ||
721 | |||
722 | static void pidff_autocenter(struct pidff_device *pidff, u16 magnitude) | ||
723 | { | ||
724 | struct hid_field *field = | ||
725 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].field; | ||
726 | |||
727 | if (!magnitude) { | ||
728 | pidff_playback_pid(pidff, field->logical_minimum, 0); | ||
729 | return; | ||
730 | } | ||
731 | |||
732 | pidff_playback_pid(pidff, field->logical_minimum, 1); | ||
733 | |||
734 | pidff->set_effect[PID_EFFECT_BLOCK_INDEX].value[0] = | ||
735 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].field->logical_minimum; | ||
736 | pidff->set_effect_type->value[0] = pidff->type_id[PID_SPRING]; | ||
737 | pidff->set_effect[PID_DURATION].value[0] = 0; | ||
738 | pidff->set_effect[PID_TRIGGER_BUTTON].value[0] = 0; | ||
739 | pidff->set_effect[PID_TRIGGER_REPEAT_INT].value[0] = 0; | ||
740 | pidff_set(&pidff->set_effect[PID_GAIN], magnitude); | ||
741 | pidff->set_effect[PID_START_DELAY].value[0] = 0; | ||
742 | |||
743 | usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT], | ||
744 | USB_DIR_OUT); | ||
745 | } | ||
746 | |||
747 | /* | ||
748 | * pidff_set_autocenter() handler | ||
749 | */ | ||
750 | static void pidff_set_autocenter(struct input_dev *dev, u16 magnitude) | ||
751 | { | ||
752 | struct pidff_device *pidff = dev->ff->private; | ||
753 | |||
754 | pidff_autocenter(pidff, magnitude); | ||
755 | } | ||
756 | |||
757 | /* | ||
758 | * Find fields from a report and fill a pidff_usage | ||
759 | */ | ||
760 | static int pidff_find_fields(struct pidff_usage *usage, const u8 *table, | ||
761 | struct hid_report *report, int count, int strict) | ||
762 | { | ||
763 | int i, j, k, found; | ||
764 | |||
765 | for (k = 0; k < count; k++) { | ||
766 | found = 0; | ||
767 | for (i = 0; i < report->maxfield; i++) { | ||
768 | if (report->field[i]->maxusage != | ||
769 | report->field[i]->report_count) { | ||
770 | debug("maxusage and report_count do not match, " | ||
771 | "skipping"); | ||
772 | continue; | ||
773 | } | ||
774 | for (j = 0; j < report->field[i]->maxusage; j++) { | ||
775 | if (report->field[i]->usage[j].hid == | ||
776 | (HID_UP_PID | table[k])) { | ||
777 | debug("found %d at %d->%d", k, i, j); | ||
778 | usage[k].field = report->field[i]; | ||
779 | usage[k].value = | ||
780 | &report->field[i]->value[j]; | ||
781 | found = 1; | ||
782 | break; | ||
783 | } | ||
784 | } | ||
785 | if (found) | ||
786 | break; | ||
787 | } | ||
788 | if (!found && strict) { | ||
789 | debug("failed to locate %d", k); | ||
790 | return -1; | ||
791 | } | ||
792 | } | ||
793 | return 0; | ||
794 | } | ||
795 | |||
796 | /* | ||
797 | * Return index into pidff_reports for the given usage | ||
798 | */ | ||
799 | static int pidff_check_usage(int usage) | ||
800 | { | ||
801 | int i; | ||
802 | |||
803 | for (i = 0; i < sizeof(pidff_reports); i++) | ||
804 | if (usage == (HID_UP_PID | pidff_reports[i])) | ||
805 | return i; | ||
806 | |||
807 | return -1; | ||
808 | } | ||
809 | |||
810 | /* | ||
811 | * Find the reports and fill pidff->reports[] | ||
812 | * report_type specifies either OUTPUT or FEATURE reports | ||
813 | */ | ||
814 | static void pidff_find_reports(struct hid_device *hid, int report_type, | ||
815 | struct pidff_device *pidff) | ||
816 | { | ||
817 | struct hid_report *report; | ||
818 | int i, ret; | ||
819 | |||
820 | list_for_each_entry(report, | ||
821 | &hid->report_enum[report_type].report_list, list) { | ||
822 | if (report->maxfield < 1) | ||
823 | continue; | ||
824 | ret = pidff_check_usage(report->field[0]->logical); | ||
825 | if (ret != -1) { | ||
826 | debug("found usage 0x%02x from field->logical", | ||
827 | pidff_reports[ret]); | ||
828 | pidff->reports[ret] = report; | ||
829 | continue; | ||
830 | } | ||
831 | |||
832 | /* | ||
833 | * Sometimes logical collections are stacked to indicate | ||
834 | * different usages for the report and the field, in which | ||
835 | * case we want the usage of the parent. However, Linux HID | ||
836 | * implementation hides this fact, so we have to dig it up | ||
837 | * ourselves | ||
838 | */ | ||
839 | i = report->field[0]->usage[0].collection_index; | ||
840 | if (i <= 0 || | ||
841 | hid->collection[i - 1].type != HID_COLLECTION_LOGICAL) | ||
842 | continue; | ||
843 | ret = pidff_check_usage(hid->collection[i - 1].usage); | ||
844 | if (ret != -1 && !pidff->reports[ret]) { | ||
845 | debug("found usage 0x%02x from collection array", | ||
846 | pidff_reports[ret]); | ||
847 | pidff->reports[ret] = report; | ||
848 | } | ||
849 | } | ||
850 | } | ||
851 | |||
852 | /* | ||
853 | * Test if the required reports have been found | ||
854 | */ | ||
855 | static int pidff_reports_ok(struct pidff_device *pidff) | ||
856 | { | ||
857 | int i; | ||
858 | |||
859 | for (i = 0; i <= PID_REQUIRED_REPORTS; i++) { | ||
860 | if (!pidff->reports[i]) { | ||
861 | debug("%d missing", i); | ||
862 | return 0; | ||
863 | } | ||
864 | } | ||
865 | |||
866 | return 1; | ||
867 | } | ||
868 | |||
869 | /* | ||
870 | * Find a field with a specific usage within a report | ||
871 | */ | ||
872 | static struct hid_field *pidff_find_special_field(struct hid_report *report, | ||
873 | int usage, int enforce_min) | ||
874 | { | ||
875 | int i; | ||
876 | |||
877 | for (i = 0; i < report->maxfield; i++) { | ||
878 | if (report->field[i]->logical == (HID_UP_PID | usage) && | ||
879 | report->field[i]->report_count > 0) { | ||
880 | if (!enforce_min || | ||
881 | report->field[i]->logical_minimum == 1) | ||
882 | return report->field[i]; | ||
883 | else { | ||
884 | printk(KERN_ERR "hid-pidff: logical_minimum " | ||
885 | "is not 1 as it should be\n"); | ||
886 | return NULL; | ||
887 | } | ||
888 | } | ||
889 | } | ||
890 | return NULL; | ||
891 | } | ||
892 | |||
893 | /* | ||
894 | * Fill a pidff->*_id struct table | ||
895 | */ | ||
896 | static int pidff_find_special_keys(int *keys, struct hid_field *fld, | ||
897 | const u8 *usagetable, int count) | ||
898 | { | ||
899 | |||
900 | int i, j; | ||
901 | int found = 0; | ||
902 | |||
903 | for (i = 0; i < count; i++) { | ||
904 | for (j = 0; j < fld->maxusage; j++) { | ||
905 | if (fld->usage[j].hid == (HID_UP_PID | usagetable[i])) { | ||
906 | keys[i] = j + 1; | ||
907 | found++; | ||
908 | break; | ||
909 | } | ||
910 | } | ||
911 | } | ||
912 | return found; | ||
913 | } | ||
914 | |||
915 | #define PIDFF_FIND_SPECIAL_KEYS(keys, field, name) \ | ||
916 | pidff_find_special_keys(pidff->keys, pidff->field, pidff_ ## name, \ | ||
917 | sizeof(pidff_ ## name)) | ||
918 | |||
919 | /* | ||
920 | * Find and check the special fields | ||
921 | */ | ||
922 | static int pidff_find_special_fields(struct pidff_device *pidff) | ||
923 | { | ||
924 | debug("finding special fields"); | ||
925 | |||
926 | pidff->create_new_effect_type = | ||
927 | pidff_find_special_field(pidff->reports[PID_CREATE_NEW_EFFECT], | ||
928 | 0x25, 1); | ||
929 | pidff->set_effect_type = | ||
930 | pidff_find_special_field(pidff->reports[PID_SET_EFFECT], | ||
931 | 0x25, 1); | ||
932 | pidff->effect_direction = | ||
933 | pidff_find_special_field(pidff->reports[PID_SET_EFFECT], | ||
934 | 0x57, 0); | ||
935 | pidff->device_control = | ||
936 | pidff_find_special_field(pidff->reports[PID_DEVICE_CONTROL], | ||
937 | 0x96, 1); | ||
938 | pidff->block_load_status = | ||
939 | pidff_find_special_field(pidff->reports[PID_BLOCK_LOAD], | ||
940 | 0x8b, 1); | ||
941 | pidff->effect_operation_status = | ||
942 | pidff_find_special_field(pidff->reports[PID_EFFECT_OPERATION], | ||
943 | 0x78, 1); | ||
944 | |||
945 | debug("search done"); | ||
946 | |||
947 | if (!pidff->create_new_effect_type || !pidff->set_effect_type) { | ||
948 | printk(KERN_ERR "hid-pidff: effect lists not found\n"); | ||
949 | return -1; | ||
950 | } | ||
951 | |||
952 | if (!pidff->effect_direction) { | ||
953 | printk(KERN_ERR "hid-pidff: direction field not found\n"); | ||
954 | return -1; | ||
955 | } | ||
956 | |||
957 | if (!pidff->device_control) { | ||
958 | printk(KERN_ERR "hid-pidff: device control field not found\n"); | ||
959 | return -1; | ||
960 | } | ||
961 | |||
962 | if (!pidff->block_load_status) { | ||
963 | printk(KERN_ERR | ||
964 | "hid-pidff: block load status field not found\n"); | ||
965 | return -1; | ||
966 | } | ||
967 | |||
968 | if (!pidff->effect_operation_status) { | ||
969 | printk(KERN_ERR | ||
970 | "hid-pidff: effect operation field not found\n"); | ||
971 | return -1; | ||
972 | } | ||
973 | |||
974 | pidff_find_special_keys(pidff->control_id, pidff->device_control, | ||
975 | pidff_device_control, | ||
976 | sizeof(pidff_device_control)); | ||
977 | |||
978 | PIDFF_FIND_SPECIAL_KEYS(control_id, device_control, device_control); | ||
979 | |||
980 | if (!PIDFF_FIND_SPECIAL_KEYS(type_id, create_new_effect_type, | ||
981 | effect_types)) { | ||
982 | printk(KERN_ERR "hid-pidff: no effect types found\n"); | ||
983 | return -1; | ||
984 | } | ||
985 | |||
986 | if (PIDFF_FIND_SPECIAL_KEYS(status_id, block_load_status, | ||
987 | block_load_status) != | ||
988 | sizeof(pidff_block_load_status)) { | ||
989 | printk(KERN_ERR | ||
990 | "hidpidff: block load status identifiers not found\n"); | ||
991 | return -1; | ||
992 | } | ||
993 | |||
994 | if (PIDFF_FIND_SPECIAL_KEYS(operation_id, effect_operation_status, | ||
995 | effect_operation_status) != | ||
996 | sizeof(pidff_effect_operation_status)) { | ||
997 | printk(KERN_ERR | ||
998 | "hidpidff: effect operation identifiers not found\n"); | ||
999 | return -1; | ||
1000 | } | ||
1001 | |||
1002 | return 0; | ||
1003 | } | ||
1004 | |||
1005 | /** | ||
1006 | * Find the implemented effect types | ||
1007 | */ | ||
1008 | static int pidff_find_effects(struct pidff_device *pidff, | ||
1009 | struct input_dev *dev) | ||
1010 | { | ||
1011 | int i; | ||
1012 | |||
1013 | for (i = 0; i < sizeof(pidff_effect_types); i++) { | ||
1014 | int pidff_type = pidff->type_id[i]; | ||
1015 | if (pidff->set_effect_type->usage[pidff_type].hid != | ||
1016 | pidff->create_new_effect_type->usage[pidff_type].hid) { | ||
1017 | printk(KERN_ERR "hid-pidff: " | ||
1018 | "effect type number %d is invalid\n", i); | ||
1019 | return -1; | ||
1020 | } | ||
1021 | } | ||
1022 | |||
1023 | if (pidff->type_id[PID_CONSTANT]) | ||
1024 | set_bit(FF_CONSTANT, dev->ffbit); | ||
1025 | if (pidff->type_id[PID_RAMP]) | ||
1026 | set_bit(FF_RAMP, dev->ffbit); | ||
1027 | if (pidff->type_id[PID_SQUARE]) { | ||
1028 | set_bit(FF_SQUARE, dev->ffbit); | ||
1029 | set_bit(FF_PERIODIC, dev->ffbit); | ||
1030 | } | ||
1031 | if (pidff->type_id[PID_SINE]) { | ||
1032 | set_bit(FF_SINE, dev->ffbit); | ||
1033 | set_bit(FF_PERIODIC, dev->ffbit); | ||
1034 | } | ||
1035 | if (pidff->type_id[PID_TRIANGLE]) { | ||
1036 | set_bit(FF_TRIANGLE, dev->ffbit); | ||
1037 | set_bit(FF_PERIODIC, dev->ffbit); | ||
1038 | } | ||
1039 | if (pidff->type_id[PID_SAW_UP]) { | ||
1040 | set_bit(FF_SAW_UP, dev->ffbit); | ||
1041 | set_bit(FF_PERIODIC, dev->ffbit); | ||
1042 | } | ||
1043 | if (pidff->type_id[PID_SAW_DOWN]) { | ||
1044 | set_bit(FF_SAW_DOWN, dev->ffbit); | ||
1045 | set_bit(FF_PERIODIC, dev->ffbit); | ||
1046 | } | ||
1047 | if (pidff->type_id[PID_SPRING]) | ||
1048 | set_bit(FF_SPRING, dev->ffbit); | ||
1049 | if (pidff->type_id[PID_DAMPER]) | ||
1050 | set_bit(FF_DAMPER, dev->ffbit); | ||
1051 | if (pidff->type_id[PID_INERTIA]) | ||
1052 | set_bit(FF_INERTIA, dev->ffbit); | ||
1053 | if (pidff->type_id[PID_FRICTION]) | ||
1054 | set_bit(FF_FRICTION, dev->ffbit); | ||
1055 | |||
1056 | return 0; | ||
1057 | |||
1058 | } | ||
1059 | |||
1060 | #define PIDFF_FIND_FIELDS(name, report, strict) \ | ||
1061 | pidff_find_fields(pidff->name, pidff_ ## name, \ | ||
1062 | pidff->reports[report], \ | ||
1063 | sizeof(pidff_ ## name), strict) | ||
1064 | |||
1065 | /* | ||
1066 | * Fill and check the pidff_usages | ||
1067 | */ | ||
1068 | static int pidff_init_fields(struct pidff_device *pidff, struct input_dev *dev) | ||
1069 | { | ||
1070 | int envelope_ok = 0; | ||
1071 | |||
1072 | if (PIDFF_FIND_FIELDS(set_effect, PID_SET_EFFECT, 1)) { | ||
1073 | printk(KERN_ERR | ||
1074 | "hid-pidff: unknown set_effect report layout\n"); | ||
1075 | return -ENODEV; | ||
1076 | } | ||
1077 | |||
1078 | PIDFF_FIND_FIELDS(block_load, PID_BLOCK_LOAD, 0); | ||
1079 | if (!pidff->block_load[PID_EFFECT_BLOCK_INDEX].value) { | ||
1080 | printk(KERN_ERR | ||
1081 | "hid-pidff: unknown pid_block_load report layout\n"); | ||
1082 | return -ENODEV; | ||
1083 | } | ||
1084 | |||
1085 | if (PIDFF_FIND_FIELDS(effect_operation, PID_EFFECT_OPERATION, 1)) { | ||
1086 | printk(KERN_ERR | ||
1087 | "hid-pidff: unknown effect_operation report layout\n"); | ||
1088 | return -ENODEV; | ||
1089 | } | ||
1090 | |||
1091 | if (PIDFF_FIND_FIELDS(block_free, PID_BLOCK_FREE, 1)) { | ||
1092 | printk(KERN_ERR | ||
1093 | "hid-pidff: unknown pid_block_free report layout\n"); | ||
1094 | return -ENODEV; | ||
1095 | } | ||
1096 | |||
1097 | if (!PIDFF_FIND_FIELDS(set_envelope, PID_SET_ENVELOPE, 1)) | ||
1098 | envelope_ok = 1; | ||
1099 | |||
1100 | if (pidff_find_special_fields(pidff) || pidff_find_effects(pidff, dev)) | ||
1101 | return -ENODEV; | ||
1102 | |||
1103 | if (!envelope_ok) { | ||
1104 | if (test_and_clear_bit(FF_CONSTANT, dev->ffbit)) | ||
1105 | printk(KERN_WARNING "hid-pidff: " | ||
1106 | "has constant effect but no envelope\n"); | ||
1107 | if (test_and_clear_bit(FF_RAMP, dev->ffbit)) | ||
1108 | printk(KERN_WARNING "hid-pidff: " | ||
1109 | "has ramp effect but no envelope\n"); | ||
1110 | |||
1111 | if (test_and_clear_bit(FF_PERIODIC, dev->ffbit)) | ||
1112 | printk(KERN_WARNING "hid-pidff: " | ||
1113 | "has periodic effect but no envelope\n"); | ||
1114 | } | ||
1115 | |||
1116 | if (test_bit(FF_CONSTANT, dev->ffbit) && | ||
1117 | PIDFF_FIND_FIELDS(set_constant, PID_SET_CONSTANT, 1)) { | ||
1118 | printk(KERN_WARNING | ||
1119 | "hid-pidff: unknown constant effect layout\n"); | ||
1120 | clear_bit(FF_CONSTANT, dev->ffbit); | ||
1121 | } | ||
1122 | |||
1123 | if (test_bit(FF_RAMP, dev->ffbit) && | ||
1124 | PIDFF_FIND_FIELDS(set_ramp, PID_SET_RAMP, 1)) { | ||
1125 | printk(KERN_WARNING "hid-pidff: unknown ramp effect layout\n"); | ||
1126 | clear_bit(FF_RAMP, dev->ffbit); | ||
1127 | } | ||
1128 | |||
1129 | if ((test_bit(FF_SPRING, dev->ffbit) || | ||
1130 | test_bit(FF_DAMPER, dev->ffbit) || | ||
1131 | test_bit(FF_FRICTION, dev->ffbit) || | ||
1132 | test_bit(FF_INERTIA, dev->ffbit)) && | ||
1133 | PIDFF_FIND_FIELDS(set_condition, PID_SET_CONDITION, 1)) { | ||
1134 | printk(KERN_WARNING | ||
1135 | "hid-pidff: unknown condition effect layout\n"); | ||
1136 | clear_bit(FF_SPRING, dev->ffbit); | ||
1137 | clear_bit(FF_DAMPER, dev->ffbit); | ||
1138 | clear_bit(FF_FRICTION, dev->ffbit); | ||
1139 | clear_bit(FF_INERTIA, dev->ffbit); | ||
1140 | } | ||
1141 | |||
1142 | if (test_bit(FF_PERIODIC, dev->ffbit) && | ||
1143 | PIDFF_FIND_FIELDS(set_periodic, PID_SET_PERIODIC, 1)) { | ||
1144 | printk(KERN_WARNING | ||
1145 | "hid-pidff: unknown periodic effect layout\n"); | ||
1146 | clear_bit(FF_PERIODIC, dev->ffbit); | ||
1147 | } | ||
1148 | |||
1149 | PIDFF_FIND_FIELDS(pool, PID_POOL, 0); | ||
1150 | |||
1151 | if (!PIDFF_FIND_FIELDS(device_gain, PID_DEVICE_GAIN, 1)) | ||
1152 | set_bit(FF_GAIN, dev->ffbit); | ||
1153 | |||
1154 | return 0; | ||
1155 | } | ||
1156 | |||
1157 | /* | ||
1158 | * Reset the device | ||
1159 | */ | ||
1160 | static void pidff_reset(struct pidff_device *pidff) | ||
1161 | { | ||
1162 | struct hid_device *hid = pidff->hid; | ||
1163 | int i = 0; | ||
1164 | |||
1165 | pidff->device_control->value[0] = pidff->control_id[PID_RESET]; | ||
1166 | /* We reset twice as sometimes hid_wait_io isn't waiting long enough */ | ||
1167 | usbhid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT); | ||
1168 | usbhid_wait_io(hid); | ||
1169 | usbhid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT); | ||
1170 | usbhid_wait_io(hid); | ||
1171 | |||
1172 | pidff->device_control->value[0] = | ||
1173 | pidff->control_id[PID_ENABLE_ACTUATORS]; | ||
1174 | usbhid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT); | ||
1175 | usbhid_wait_io(hid); | ||
1176 | |||
1177 | /* pool report is sometimes messed up, refetch it */ | ||
1178 | usbhid_submit_report(hid, pidff->reports[PID_POOL], USB_DIR_IN); | ||
1179 | usbhid_wait_io(hid); | ||
1180 | |||
1181 | if (pidff->pool[PID_SIMULTANEOUS_MAX].value) { | ||
1182 | int sim_effects = pidff->pool[PID_SIMULTANEOUS_MAX].value[0]; | ||
1183 | while (sim_effects < 2) { | ||
1184 | if (i++ > 20) { | ||
1185 | printk(KERN_WARNING "hid-pidff: device reports " | ||
1186 | "%d simultaneous effects\n", | ||
1187 | sim_effects); | ||
1188 | break; | ||
1189 | } | ||
1190 | debug("pid_pool requested again"); | ||
1191 | usbhid_submit_report(hid, pidff->reports[PID_POOL], | ||
1192 | USB_DIR_IN); | ||
1193 | usbhid_wait_io(hid); | ||
1194 | } | ||
1195 | } | ||
1196 | } | ||
1197 | |||
1198 | /* | ||
1199 | * Test if autocenter modification is using the supported method | ||
1200 | */ | ||
1201 | static int pidff_check_autocenter(struct pidff_device *pidff, | ||
1202 | struct input_dev *dev) | ||
1203 | { | ||
1204 | int error; | ||
1205 | |||
1206 | /* | ||
1207 | * Let's find out if autocenter modification is supported | ||
1208 | * Specification doesn't specify anything, so we request an | ||
1209 | * effect upload and cancel it immediately. If the approved | ||
1210 | * effect id was one above the minimum, then we assume the first | ||
1211 | * effect id is a built-in spring type effect used for autocenter | ||
1212 | */ | ||
1213 | |||
1214 | error = pidff_request_effect_upload(pidff, 1); | ||
1215 | if (error) { | ||
1216 | printk(KERN_ERR "hid-pidff: upload request failed\n"); | ||
1217 | return error; | ||
1218 | } | ||
1219 | |||
1220 | if (pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0] == | ||
1221 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].field->logical_minimum + 1) { | ||
1222 | pidff_autocenter(pidff, 0xffff); | ||
1223 | set_bit(FF_AUTOCENTER, dev->ffbit); | ||
1224 | } else { | ||
1225 | printk(KERN_NOTICE "hid-pidff: " | ||
1226 | "device has unknown autocenter control method\n"); | ||
1227 | } | ||
1228 | |||
1229 | pidff_erase_pid(pidff, | ||
1230 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]); | ||
1231 | |||
1232 | return 0; | ||
1233 | |||
1234 | } | ||
1235 | |||
1236 | /* | ||
1237 | * Check if the device is PID and initialize it | ||
1238 | */ | ||
1239 | int hid_pidff_init(struct hid_device *hid) | ||
1240 | { | ||
1241 | struct pidff_device *pidff; | ||
1242 | struct hid_input *hidinput = list_entry(hid->inputs.next, | ||
1243 | struct hid_input, list); | ||
1244 | struct input_dev *dev = hidinput->input; | ||
1245 | struct ff_device *ff; | ||
1246 | int max_effects; | ||
1247 | int error; | ||
1248 | |||
1249 | debug("starting pid init"); | ||
1250 | |||
1251 | if (list_empty(&hid->report_enum[HID_OUTPUT_REPORT].report_list)) { | ||
1252 | debug("not a PID device, no output report"); | ||
1253 | return -ENODEV; | ||
1254 | } | ||
1255 | |||
1256 | pidff = kzalloc(sizeof(*pidff), GFP_KERNEL); | ||
1257 | if (!pidff) | ||
1258 | return -ENOMEM; | ||
1259 | |||
1260 | pidff->hid = hid; | ||
1261 | |||
1262 | pidff_find_reports(hid, HID_OUTPUT_REPORT, pidff); | ||
1263 | pidff_find_reports(hid, HID_FEATURE_REPORT, pidff); | ||
1264 | |||
1265 | if (!pidff_reports_ok(pidff)) { | ||
1266 | debug("reports not ok, aborting"); | ||
1267 | error = -ENODEV; | ||
1268 | goto fail; | ||
1269 | } | ||
1270 | |||
1271 | error = pidff_init_fields(pidff, dev); | ||
1272 | if (error) | ||
1273 | goto fail; | ||
1274 | |||
1275 | pidff_reset(pidff); | ||
1276 | |||
1277 | if (test_bit(FF_GAIN, dev->ffbit)) { | ||
1278 | pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], 0xffff); | ||
1279 | usbhid_submit_report(pidff->hid, pidff->reports[PID_DEVICE_GAIN], | ||
1280 | USB_DIR_OUT); | ||
1281 | } | ||
1282 | |||
1283 | error = pidff_check_autocenter(pidff, dev); | ||
1284 | if (error) | ||
1285 | goto fail; | ||
1286 | |||
1287 | max_effects = | ||
1288 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].field->logical_maximum - | ||
1289 | pidff->block_load[PID_EFFECT_BLOCK_INDEX].field->logical_minimum + | ||
1290 | 1; | ||
1291 | debug("max effects is %d", max_effects); | ||
1292 | |||
1293 | if (max_effects > PID_EFFECTS_MAX) | ||
1294 | max_effects = PID_EFFECTS_MAX; | ||
1295 | |||
1296 | if (pidff->pool[PID_SIMULTANEOUS_MAX].value) | ||
1297 | debug("max simultaneous effects is %d", | ||
1298 | pidff->pool[PID_SIMULTANEOUS_MAX].value[0]); | ||
1299 | |||
1300 | if (pidff->pool[PID_RAM_POOL_SIZE].value) | ||
1301 | debug("device memory size is %d bytes", | ||
1302 | pidff->pool[PID_RAM_POOL_SIZE].value[0]); | ||
1303 | |||
1304 | if (pidff->pool[PID_DEVICE_MANAGED_POOL].value && | ||
1305 | pidff->pool[PID_DEVICE_MANAGED_POOL].value[0] == 0) { | ||
1306 | printk(KERN_NOTICE "hid-pidff: " | ||
1307 | "device does not support device managed pool\n"); | ||
1308 | goto fail; | ||
1309 | } | ||
1310 | |||
1311 | error = input_ff_create(dev, max_effects); | ||
1312 | if (error) | ||
1313 | goto fail; | ||
1314 | |||
1315 | ff = dev->ff; | ||
1316 | ff->private = pidff; | ||
1317 | ff->upload = pidff_upload_effect; | ||
1318 | ff->erase = pidff_erase_effect; | ||
1319 | ff->set_gain = pidff_set_gain; | ||
1320 | ff->set_autocenter = pidff_set_autocenter; | ||
1321 | ff->playback = pidff_playback; | ||
1322 | |||
1323 | printk(KERN_INFO "Force feedback for USB HID PID devices by " | ||
1324 | "Anssi Hannula <anssi.hannula@gmail.com>\n"); | ||
1325 | |||
1326 | return 0; | ||
1327 | |||
1328 | fail: | ||
1329 | kfree(pidff); | ||
1330 | return error; | ||
1331 | } | ||
diff --git a/drivers/hid/usbhid/hid-plff.c b/drivers/hid/usbhid/hid-plff.c new file mode 100644 index 000000000000..76d2e6e14db4 --- /dev/null +++ b/drivers/hid/usbhid/hid-plff.c | |||
@@ -0,0 +1,129 @@ | |||
1 | /* | ||
2 | * Force feedback support for PantherLord USB/PS2 2in1 Adapter devices | ||
3 | * | ||
4 | * Copyright (c) 2007 Anssi Hannula <anssi.hannula@gmail.com> | ||
5 | */ | ||
6 | |||
7 | /* | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | */ | ||
22 | |||
23 | |||
24 | /* #define DEBUG */ | ||
25 | |||
26 | #define debug(format, arg...) pr_debug("hid-plff: " format "\n" , ## arg) | ||
27 | |||
28 | #include <linux/input.h> | ||
29 | #include <linux/usb.h> | ||
30 | #include <linux/hid.h> | ||
31 | #include "usbhid.h" | ||
32 | |||
33 | struct plff_device { | ||
34 | struct hid_report *report; | ||
35 | }; | ||
36 | |||
37 | static int hid_plff_play(struct input_dev *dev, void *data, | ||
38 | struct ff_effect *effect) | ||
39 | { | ||
40 | struct hid_device *hid = dev->private; | ||
41 | struct plff_device *plff = data; | ||
42 | int left, right; | ||
43 | |||
44 | left = effect->u.rumble.strong_magnitude; | ||
45 | right = effect->u.rumble.weak_magnitude; | ||
46 | debug("called with 0x%04x 0x%04x", left, right); | ||
47 | |||
48 | left = left * 0x7f / 0xffff; | ||
49 | right = right * 0x7f / 0xffff; | ||
50 | |||
51 | plff->report->field[0]->value[2] = left; | ||
52 | plff->report->field[0]->value[3] = right; | ||
53 | debug("running with 0x%02x 0x%02x", left, right); | ||
54 | usbhid_submit_report(hid, plff->report, USB_DIR_OUT); | ||
55 | |||
56 | return 0; | ||
57 | } | ||
58 | |||
59 | int hid_plff_init(struct hid_device *hid) | ||
60 | { | ||
61 | struct plff_device *plff; | ||
62 | struct hid_report *report; | ||
63 | struct hid_input *hidinput; | ||
64 | struct list_head *report_list = | ||
65 | &hid->report_enum[HID_OUTPUT_REPORT].report_list; | ||
66 | struct list_head *report_ptr = report_list; | ||
67 | struct input_dev *dev; | ||
68 | int error; | ||
69 | |||
70 | /* The device contains 2 output reports (one for each | ||
71 | HID_QUIRK_MULTI_INPUT device), both containing 1 field, which | ||
72 | contains 4 ff00.0002 usages and 4 16bit absolute values. | ||
73 | |||
74 | The 2 input reports also contain a field which contains | ||
75 | 8 ff00.0001 usages and 8 boolean values. Their meaning is | ||
76 | currently unknown. */ | ||
77 | |||
78 | if (list_empty(report_list)) { | ||
79 | printk(KERN_ERR "hid-plff: no output reports found\n"); | ||
80 | return -ENODEV; | ||
81 | } | ||
82 | |||
83 | list_for_each_entry(hidinput, &hid->inputs, list) { | ||
84 | |||
85 | report_ptr = report_ptr->next; | ||
86 | |||
87 | if (report_ptr == report_list) { | ||
88 | printk(KERN_ERR "hid-plff: required output report is missing\n"); | ||
89 | return -ENODEV; | ||
90 | } | ||
91 | |||
92 | report = list_entry(report_ptr, struct hid_report, list); | ||
93 | if (report->maxfield < 1) { | ||
94 | printk(KERN_ERR "hid-plff: no fields in the report\n"); | ||
95 | return -ENODEV; | ||
96 | } | ||
97 | |||
98 | if (report->field[0]->report_count < 4) { | ||
99 | printk(KERN_ERR "hid-plff: not enough values in the field\n"); | ||
100 | return -ENODEV; | ||
101 | } | ||
102 | |||
103 | plff = kzalloc(sizeof(struct plff_device), GFP_KERNEL); | ||
104 | if (!plff) | ||
105 | return -ENOMEM; | ||
106 | |||
107 | dev = hidinput->input; | ||
108 | |||
109 | set_bit(FF_RUMBLE, dev->ffbit); | ||
110 | |||
111 | error = input_ff_create_memless(dev, plff, hid_plff_play); | ||
112 | if (error) { | ||
113 | kfree(plff); | ||
114 | return error; | ||
115 | } | ||
116 | |||
117 | plff->report = report; | ||
118 | plff->report->field[0]->value[0] = 0x00; | ||
119 | plff->report->field[0]->value[1] = 0x00; | ||
120 | plff->report->field[0]->value[2] = 0x00; | ||
121 | plff->report->field[0]->value[3] = 0x00; | ||
122 | usbhid_submit_report(hid, plff->report, USB_DIR_OUT); | ||
123 | } | ||
124 | |||
125 | printk(KERN_INFO "hid-plff: Force feedback for PantherLord USB/PS2 " | ||
126 | "2in1 Adapters by Anssi Hannula <anssi.hannula@gmail.com>\n"); | ||
127 | |||
128 | return 0; | ||
129 | } | ||
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c new file mode 100644 index 000000000000..17a87555e32f --- /dev/null +++ b/drivers/hid/usbhid/hid-quirks.c | |||
@@ -0,0 +1,681 @@ | |||
1 | /* | ||
2 | * USB HID quirks support for Linux | ||
3 | * | ||
4 | * Copyright (c) 1999 Andreas Gal | ||
5 | * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> | ||
6 | * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc | ||
7 | * Copyright (c) 2006-2007 Jiri Kosina | ||
8 | * Copyright (c) 2007 Paul Walmsley | ||
9 | */ | ||
10 | |||
11 | /* | ||
12 | * This program is free software; you can redistribute it and/or modify it | ||
13 | * under the terms of the GNU General Public License as published by the Free | ||
14 | * Software Foundation; either version 2 of the License, or (at your option) | ||
15 | * any later version. | ||
16 | */ | ||
17 | |||
18 | #include <linux/hid.h> | ||
19 | |||
20 | #define USB_VENDOR_ID_A4TECH 0x09da | ||
21 | #define USB_DEVICE_ID_A4TECH_WCP32PU 0x0006 | ||
22 | |||
23 | #define USB_VENDOR_ID_AASHIMA 0x06d6 | ||
24 | #define USB_DEVICE_ID_AASHIMA_GAMEPAD 0x0025 | ||
25 | #define USB_DEVICE_ID_AASHIMA_PREDATOR 0x0026 | ||
26 | |||
27 | #define USB_VENDOR_ID_ACECAD 0x0460 | ||
28 | #define USB_DEVICE_ID_ACECAD_FLAIR 0x0004 | ||
29 | #define USB_DEVICE_ID_ACECAD_302 0x0008 | ||
30 | |||
31 | #define USB_VENDOR_ID_AIPTEK 0x08ca | ||
32 | #define USB_DEVICE_ID_AIPTEK_01 0x0001 | ||
33 | #define USB_DEVICE_ID_AIPTEK_10 0x0010 | ||
34 | #define USB_DEVICE_ID_AIPTEK_20 0x0020 | ||
35 | #define USB_DEVICE_ID_AIPTEK_21 0x0021 | ||
36 | #define USB_DEVICE_ID_AIPTEK_22 0x0022 | ||
37 | #define USB_DEVICE_ID_AIPTEK_23 0x0023 | ||
38 | #define USB_DEVICE_ID_AIPTEK_24 0x0024 | ||
39 | |||
40 | #define USB_VENDOR_ID_AIRCABLE 0x16CA | ||
41 | #define USB_DEVICE_ID_AIRCABLE1 0x1502 | ||
42 | |||
43 | #define USB_VENDOR_ID_ALCOR 0x058f | ||
44 | #define USB_DEVICE_ID_ALCOR_USBRS232 0x9720 | ||
45 | |||
46 | #define USB_VENDOR_ID_ALPS 0x0433 | ||
47 | #define USB_DEVICE_ID_IBM_GAMEPAD 0x1101 | ||
48 | |||
49 | #define USB_VENDOR_ID_APPLE 0x05ac | ||
50 | #define USB_DEVICE_ID_APPLE_MIGHTYMOUSE 0x0304 | ||
51 | #define USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI 0x020e | ||
52 | #define USB_DEVICE_ID_APPLE_FOUNTAIN_ISO 0x020f | ||
53 | #define USB_DEVICE_ID_APPLE_GEYSER_ANSI 0x0214 | ||
54 | #define USB_DEVICE_ID_APPLE_GEYSER_ISO 0x0215 | ||
55 | #define USB_DEVICE_ID_APPLE_GEYSER_JIS 0x0216 | ||
56 | #define USB_DEVICE_ID_APPLE_GEYSER3_ANSI 0x0217 | ||
57 | #define USB_DEVICE_ID_APPLE_GEYSER3_ISO 0x0218 | ||
58 | #define USB_DEVICE_ID_APPLE_GEYSER3_JIS 0x0219 | ||
59 | #define USB_DEVICE_ID_APPLE_GEYSER4_ANSI 0x021a | ||
60 | #define USB_DEVICE_ID_APPLE_GEYSER4_ISO 0x021b | ||
61 | #define USB_DEVICE_ID_APPLE_GEYSER4_JIS 0x021c | ||
62 | #define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a | ||
63 | #define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b | ||
64 | #define USB_DEVICE_ID_APPLE_IR 0x8240 | ||
65 | |||
66 | #define USB_VENDOR_ID_ATEN 0x0557 | ||
67 | #define USB_DEVICE_ID_ATEN_UC100KM 0x2004 | ||
68 | #define USB_DEVICE_ID_ATEN_CS124U 0x2202 | ||
69 | #define USB_DEVICE_ID_ATEN_2PORTKVM 0x2204 | ||
70 | #define USB_DEVICE_ID_ATEN_4PORTKVM 0x2205 | ||
71 | #define USB_DEVICE_ID_ATEN_4PORTKVMC 0x2208 | ||
72 | |||
73 | #define USB_VENDOR_ID_BELKIN 0x050d | ||
74 | #define USB_DEVICE_ID_FLIP_KVM 0x3201 | ||
75 | |||
76 | #define USB_VENDOR_ID_BERKSHIRE 0x0c98 | ||
77 | #define USB_DEVICE_ID_BERKSHIRE_PCWD 0x1140 | ||
78 | |||
79 | #define USB_VENDOR_ID_CHERRY 0x046a | ||
80 | #define USB_DEVICE_ID_CHERRY_CYMOTION 0x0023 | ||
81 | |||
82 | #define USB_VENDOR_ID_CHIC 0x05fe | ||
83 | #define USB_DEVICE_ID_CHIC_GAMEPAD 0x0014 | ||
84 | |||
85 | #define USB_VENDOR_ID_CIDC 0x1677 | ||
86 | |||
87 | #define USB_VENDOR_ID_CODEMERCS 0x07c0 | ||
88 | #define USB_DEVICE_ID_CODEMERCS_IOW_FIRST 0x1500 | ||
89 | #define USB_DEVICE_ID_CODEMERCS_IOW_LAST 0x15ff | ||
90 | |||
91 | #define USB_VENDOR_ID_CYPRESS 0x04b4 | ||
92 | #define USB_DEVICE_ID_CYPRESS_MOUSE 0x0001 | ||
93 | #define USB_DEVICE_ID_CYPRESS_HIDCOM 0x5500 | ||
94 | #define USB_DEVICE_ID_CYPRESS_ULTRAMOUSE 0x7417 | ||
95 | |||
96 | #define USB_VENDOR_ID_DELL 0x413c | ||
97 | #define USB_DEVICE_ID_DELL_W7658 0x2005 | ||
98 | |||
99 | #define USB_VENDOR_ID_DELORME 0x1163 | ||
100 | #define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100 | ||
101 | #define USB_DEVICE_ID_DELORME_EM_LT20 0x0200 | ||
102 | |||
103 | #define USB_VENDOR_ID_ESSENTIAL_REALITY 0x0d7f | ||
104 | #define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100 | ||
105 | |||
106 | #define USB_VENDOR_ID_GLAB 0x06c2 | ||
107 | #define USB_DEVICE_ID_4_PHIDGETSERVO_30 0x0038 | ||
108 | #define USB_DEVICE_ID_1_PHIDGETSERVO_30 0x0039 | ||
109 | #define USB_DEVICE_ID_0_0_4_IF_KIT 0x0040 | ||
110 | #define USB_DEVICE_ID_0_16_16_IF_KIT 0x0044 | ||
111 | #define USB_DEVICE_ID_8_8_8_IF_KIT 0x0045 | ||
112 | #define USB_DEVICE_ID_0_8_7_IF_KIT 0x0051 | ||
113 | #define USB_DEVICE_ID_0_8_8_IF_KIT 0x0053 | ||
114 | #define USB_DEVICE_ID_PHIDGET_MOTORCONTROL 0x0058 | ||
115 | |||
116 | #define USB_VENDOR_ID_GRIFFIN 0x077d | ||
117 | #define USB_DEVICE_ID_POWERMATE 0x0410 | ||
118 | #define USB_DEVICE_ID_SOUNDKNOB 0x04AA | ||
119 | |||
120 | #define USB_VENDOR_ID_GTCO 0x078c | ||
121 | #define USB_DEVICE_ID_GTCO_90 0x0090 | ||
122 | #define USB_DEVICE_ID_GTCO_100 0x0100 | ||
123 | #define USB_DEVICE_ID_GTCO_101 0x0101 | ||
124 | #define USB_DEVICE_ID_GTCO_103 0x0103 | ||
125 | #define USB_DEVICE_ID_GTCO_104 0x0104 | ||
126 | #define USB_DEVICE_ID_GTCO_105 0x0105 | ||
127 | #define USB_DEVICE_ID_GTCO_106 0x0106 | ||
128 | #define USB_DEVICE_ID_GTCO_107 0x0107 | ||
129 | #define USB_DEVICE_ID_GTCO_108 0x0108 | ||
130 | #define USB_DEVICE_ID_GTCO_200 0x0200 | ||
131 | #define USB_DEVICE_ID_GTCO_201 0x0201 | ||
132 | #define USB_DEVICE_ID_GTCO_202 0x0202 | ||
133 | #define USB_DEVICE_ID_GTCO_203 0x0203 | ||
134 | #define USB_DEVICE_ID_GTCO_204 0x0204 | ||
135 | #define USB_DEVICE_ID_GTCO_205 0x0205 | ||
136 | #define USB_DEVICE_ID_GTCO_206 0x0206 | ||
137 | #define USB_DEVICE_ID_GTCO_207 0x0207 | ||
138 | #define USB_DEVICE_ID_GTCO_300 0x0300 | ||
139 | #define USB_DEVICE_ID_GTCO_301 0x0301 | ||
140 | #define USB_DEVICE_ID_GTCO_302 0x0302 | ||
141 | #define USB_DEVICE_ID_GTCO_303 0x0303 | ||
142 | #define USB_DEVICE_ID_GTCO_304 0x0304 | ||
143 | #define USB_DEVICE_ID_GTCO_305 0x0305 | ||
144 | #define USB_DEVICE_ID_GTCO_306 0x0306 | ||
145 | #define USB_DEVICE_ID_GTCO_307 0x0307 | ||
146 | #define USB_DEVICE_ID_GTCO_308 0x0308 | ||
147 | #define USB_DEVICE_ID_GTCO_309 0x0309 | ||
148 | #define USB_DEVICE_ID_GTCO_400 0x0400 | ||
149 | #define USB_DEVICE_ID_GTCO_401 0x0401 | ||
150 | #define USB_DEVICE_ID_GTCO_402 0x0402 | ||
151 | #define USB_DEVICE_ID_GTCO_403 0x0403 | ||
152 | #define USB_DEVICE_ID_GTCO_404 0x0404 | ||
153 | #define USB_DEVICE_ID_GTCO_405 0x0405 | ||
154 | #define USB_DEVICE_ID_GTCO_500 0x0500 | ||
155 | #define USB_DEVICE_ID_GTCO_501 0x0501 | ||
156 | #define USB_DEVICE_ID_GTCO_502 0x0502 | ||
157 | #define USB_DEVICE_ID_GTCO_503 0x0503 | ||
158 | #define USB_DEVICE_ID_GTCO_504 0x0504 | ||
159 | #define USB_DEVICE_ID_GTCO_1000 0x1000 | ||
160 | #define USB_DEVICE_ID_GTCO_1001 0x1001 | ||
161 | #define USB_DEVICE_ID_GTCO_1002 0x1002 | ||
162 | #define USB_DEVICE_ID_GTCO_1003 0x1003 | ||
163 | #define USB_DEVICE_ID_GTCO_1004 0x1004 | ||
164 | #define USB_DEVICE_ID_GTCO_1005 0x1005 | ||
165 | #define USB_DEVICE_ID_GTCO_1006 0x1006 | ||
166 | |||
167 | #define USB_VENDOR_ID_HAPP 0x078b | ||
168 | #define USB_DEVICE_ID_UGCI_DRIVING 0x0010 | ||
169 | #define USB_DEVICE_ID_UGCI_FLYING 0x0020 | ||
170 | #define USB_DEVICE_ID_UGCI_FIGHTING 0x0030 | ||
171 | |||
172 | #define USB_VENDOR_ID_IMATION 0x0718 | ||
173 | #define USB_DEVICE_ID_DISC_STAKKA 0xd000 | ||
174 | |||
175 | #define USB_VENDOR_ID_KBGEAR 0x084e | ||
176 | #define USB_DEVICE_ID_KBGEAR_JAMSTUDIO 0x1001 | ||
177 | |||
178 | #define USB_VENDOR_ID_LD 0x0f11 | ||
179 | #define USB_DEVICE_ID_LD_CASSY 0x1000 | ||
180 | #define USB_DEVICE_ID_LD_POCKETCASSY 0x1010 | ||
181 | #define USB_DEVICE_ID_LD_MOBILECASSY 0x1020 | ||
182 | #define USB_DEVICE_ID_LD_JWM 0x1080 | ||
183 | #define USB_DEVICE_ID_LD_DMMP 0x1081 | ||
184 | #define USB_DEVICE_ID_LD_UMIP 0x1090 | ||
185 | #define USB_DEVICE_ID_LD_XRAY1 0x1100 | ||
186 | #define USB_DEVICE_ID_LD_XRAY2 0x1101 | ||
187 | #define USB_DEVICE_ID_LD_VIDEOCOM 0x1200 | ||
188 | #define USB_DEVICE_ID_LD_COM3LAB 0x2000 | ||
189 | #define USB_DEVICE_ID_LD_TELEPORT 0x2010 | ||
190 | #define USB_DEVICE_ID_LD_NETWORKANALYSER 0x2020 | ||
191 | #define USB_DEVICE_ID_LD_POWERCONTROL 0x2030 | ||
192 | #define USB_DEVICE_ID_LD_MACHINETEST 0x2040 | ||
193 | |||
194 | #define USB_VENDOR_ID_LOGITECH 0x046d | ||
195 | #define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101 | ||
196 | #define USB_DEVICE_ID_S510_RECEIVER 0xc50c | ||
197 | #define USB_DEVICE_ID_S510_RECEIVER_2 0xc517 | ||
198 | #define USB_DEVICE_ID_MX3000_RECEIVER 0xc513 | ||
199 | #define USB_DEVICE_ID_DINOVO_EDGE 0xc714 | ||
200 | |||
201 | #define USB_VENDOR_ID_MCC 0x09db | ||
202 | #define USB_DEVICE_ID_MCC_PMD1024LS 0x0076 | ||
203 | #define USB_DEVICE_ID_MCC_PMD1208LS 0x007a | ||
204 | |||
205 | #define USB_VENDOR_ID_MGE 0x0463 | ||
206 | #define USB_DEVICE_ID_MGE_UPS 0xffff | ||
207 | #define USB_DEVICE_ID_MGE_UPS1 0x0001 | ||
208 | |||
209 | #define USB_VENDOR_ID_NEC 0x073e | ||
210 | #define USB_DEVICE_ID_NEC_USB_GAME_PAD 0x0301 | ||
211 | |||
212 | #define USB_VENDOR_ID_ONTRAK 0x0a07 | ||
213 | #define USB_DEVICE_ID_ONTRAK_ADU100 0x0064 | ||
214 | |||
215 | #define USB_VENDOR_ID_PANJIT 0x134c | ||
216 | |||
217 | #define USB_VENDOR_ID_PANTHERLORD 0x0810 | ||
218 | #define USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK 0x0001 | ||
219 | |||
220 | #define USB_VENDOR_ID_PLAYDOTCOM 0x0b43 | ||
221 | #define USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII 0x0003 | ||
222 | |||
223 | #define USB_VENDOR_ID_SAITEK 0x06a3 | ||
224 | #define USB_DEVICE_ID_SAITEK_RUMBLEPAD 0xff17 | ||
225 | |||
226 | #define USB_VENDOR_ID_SONY 0x054c | ||
227 | #define USB_DEVICE_ID_SONY_PS3_CONTROLLER 0x0268 | ||
228 | |||
229 | #define USB_VENDOR_ID_SUN 0x0430 | ||
230 | #define USB_DEVICE_ID_RARITAN_KVM_DONGLE 0xcdab | ||
231 | |||
232 | #define USB_VENDOR_ID_TOPMAX 0x0663 | ||
233 | #define USB_DEVICE_ID_TOPMAX_COBRAPAD 0x0103 | ||
234 | |||
235 | #define USB_VENDOR_ID_TURBOX 0x062a | ||
236 | #define USB_DEVICE_ID_TURBOX_KEYBOARD 0x0201 | ||
237 | |||
238 | #define USB_VENDOR_ID_VERNIER 0x08f7 | ||
239 | #define USB_DEVICE_ID_VERNIER_LABPRO 0x0001 | ||
240 | #define USB_DEVICE_ID_VERNIER_GOTEMP 0x0002 | ||
241 | #define USB_DEVICE_ID_VERNIER_SKIP 0x0003 | ||
242 | #define USB_DEVICE_ID_VERNIER_CYCLOPS 0x0004 | ||
243 | |||
244 | #define USB_VENDOR_ID_WACOM 0x056a | ||
245 | |||
246 | #define USB_VENDOR_ID_WISEGROUP 0x0925 | ||
247 | #define USB_DEVICE_ID_1_PHIDGETSERVO_20 0x8101 | ||
248 | #define USB_DEVICE_ID_4_PHIDGETSERVO_20 0x8104 | ||
249 | #define USB_DEVICE_ID_8_8_4_IF_KIT 0x8201 | ||
250 | #define USB_DEVICE_ID_QUAD_USB_JOYPAD 0x8800 | ||
251 | #define USB_DEVICE_ID_DUAL_USB_JOYPAD 0x8866 | ||
252 | |||
253 | #define USB_VENDOR_ID_WISEGROUP_LTD 0x6677 | ||
254 | #define USB_DEVICE_ID_SMARTJOY_DUAL_PLUS 0x8802 | ||
255 | |||
256 | #define USB_VENDOR_ID_YEALINK 0x6993 | ||
257 | #define USB_DEVICE_ID_YEALINK_P1K_P4K_B2K 0xb001 | ||
258 | |||
259 | /* | ||
260 | * Alphabetically sorted blacklist by quirk type. | ||
261 | */ | ||
262 | |||
263 | static const struct hid_blacklist { | ||
264 | __u16 idVendor; | ||
265 | __u16 idProduct; | ||
266 | __u32 quirks; | ||
267 | } hid_blacklist[] = { | ||
268 | |||
269 | { USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, HID_QUIRK_2WHEEL_MOUSE_HACK_7 }, | ||
270 | { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE, HID_QUIRK_2WHEEL_MOUSE_HACK_5 }, | ||
271 | |||
272 | { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RECEIVER, HID_QUIRK_BAD_RELATIVE_KEYS }, | ||
273 | |||
274 | { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_GAMEPAD, HID_QUIRK_BADPAD }, | ||
275 | { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_PREDATOR, HID_QUIRK_BADPAD }, | ||
276 | { USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD }, | ||
277 | { USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD }, | ||
278 | { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, | ||
279 | { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, | ||
280 | { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, | ||
281 | { USB_VENDOR_ID_NEC, USB_DEVICE_ID_NEC_USB_GAME_PAD, HID_QUIRK_BADPAD }, | ||
282 | { USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD }, | ||
283 | { USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD }, | ||
284 | |||
285 | { USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_CYMOTION }, | ||
286 | |||
287 | { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE, HID_QUIRK_DUPLICATE_USAGES }, | ||
288 | |||
289 | { USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM, HID_QUIRK_HIDDEV }, | ||
290 | |||
291 | { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_01, HID_QUIRK_IGNORE }, | ||
292 | { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_10, HID_QUIRK_IGNORE }, | ||
293 | { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_20, HID_QUIRK_IGNORE }, | ||
294 | { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_21, HID_QUIRK_IGNORE }, | ||
295 | { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_22, HID_QUIRK_IGNORE }, | ||
296 | { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_23, HID_QUIRK_IGNORE }, | ||
297 | { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_24, HID_QUIRK_IGNORE }, | ||
298 | { USB_VENDOR_ID_AIRCABLE, USB_DEVICE_ID_AIRCABLE1, HID_QUIRK_IGNORE }, | ||
299 | { USB_VENDOR_ID_ALCOR, USB_DEVICE_ID_ALCOR_USBRS232, HID_QUIRK_IGNORE }, | ||
300 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IR, HID_QUIRK_IGNORE }, | ||
301 | { USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD, HID_QUIRK_IGNORE }, | ||
302 | { USB_VENDOR_ID_CIDC, 0x0103, HID_QUIRK_IGNORE }, | ||
303 | { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_HIDCOM, HID_QUIRK_IGNORE }, | ||
304 | { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_ULTRAMOUSE, HID_QUIRK_IGNORE }, | ||
305 | { USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE, HID_QUIRK_IGNORE }, | ||
306 | { USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20, HID_QUIRK_IGNORE }, | ||
307 | { USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5, HID_QUIRK_IGNORE }, | ||
308 | { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_4_PHIDGETSERVO_30, HID_QUIRK_IGNORE }, | ||
309 | { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_1_PHIDGETSERVO_30, HID_QUIRK_IGNORE }, | ||
310 | { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_0_4_IF_KIT, HID_QUIRK_IGNORE }, | ||
311 | { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_16_16_IF_KIT, HID_QUIRK_IGNORE }, | ||
312 | { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_8_8_8_IF_KIT, HID_QUIRK_IGNORE }, | ||
313 | { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_7_IF_KIT, HID_QUIRK_IGNORE }, | ||
314 | { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_8_IF_KIT, HID_QUIRK_IGNORE }, | ||
315 | { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_PHIDGET_MOTORCONTROL, HID_QUIRK_IGNORE }, | ||
316 | { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE, HID_QUIRK_IGNORE }, | ||
317 | { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB, HID_QUIRK_IGNORE }, | ||
318 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_90, HID_QUIRK_IGNORE }, | ||
319 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_100, HID_QUIRK_IGNORE }, | ||
320 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_101, HID_QUIRK_IGNORE }, | ||
321 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_103, HID_QUIRK_IGNORE }, | ||
322 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_104, HID_QUIRK_IGNORE }, | ||
323 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_105, HID_QUIRK_IGNORE }, | ||
324 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_106, HID_QUIRK_IGNORE }, | ||
325 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_107, HID_QUIRK_IGNORE }, | ||
326 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_108, HID_QUIRK_IGNORE }, | ||
327 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_200, HID_QUIRK_IGNORE }, | ||
328 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_201, HID_QUIRK_IGNORE }, | ||
329 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_202, HID_QUIRK_IGNORE }, | ||
330 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_203, HID_QUIRK_IGNORE }, | ||
331 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_204, HID_QUIRK_IGNORE }, | ||
332 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_205, HID_QUIRK_IGNORE }, | ||
333 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_206, HID_QUIRK_IGNORE }, | ||
334 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_207, HID_QUIRK_IGNORE }, | ||
335 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_300, HID_QUIRK_IGNORE }, | ||
336 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_301, HID_QUIRK_IGNORE }, | ||
337 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_302, HID_QUIRK_IGNORE }, | ||
338 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_303, HID_QUIRK_IGNORE }, | ||
339 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_304, HID_QUIRK_IGNORE }, | ||
340 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_305, HID_QUIRK_IGNORE }, | ||
341 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_306, HID_QUIRK_IGNORE }, | ||
342 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_307, HID_QUIRK_IGNORE }, | ||
343 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_308, HID_QUIRK_IGNORE }, | ||
344 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_309, HID_QUIRK_IGNORE }, | ||
345 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_400, HID_QUIRK_IGNORE }, | ||
346 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_401, HID_QUIRK_IGNORE }, | ||
347 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_402, HID_QUIRK_IGNORE }, | ||
348 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_403, HID_QUIRK_IGNORE }, | ||
349 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_404, HID_QUIRK_IGNORE }, | ||
350 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_405, HID_QUIRK_IGNORE }, | ||
351 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_500, HID_QUIRK_IGNORE }, | ||
352 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_501, HID_QUIRK_IGNORE }, | ||
353 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_502, HID_QUIRK_IGNORE }, | ||
354 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_503, HID_QUIRK_IGNORE }, | ||
355 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_504, HID_QUIRK_IGNORE }, | ||
356 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1000, HID_QUIRK_IGNORE }, | ||
357 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1001, HID_QUIRK_IGNORE }, | ||
358 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1002, HID_QUIRK_IGNORE }, | ||
359 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1003, HID_QUIRK_IGNORE }, | ||
360 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1004, HID_QUIRK_IGNORE }, | ||
361 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1005, HID_QUIRK_IGNORE }, | ||
362 | { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1006, HID_QUIRK_IGNORE }, | ||
363 | { USB_VENDOR_ID_IMATION, USB_DEVICE_ID_DISC_STAKKA, HID_QUIRK_IGNORE }, | ||
364 | { USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO, HID_QUIRK_IGNORE }, | ||
365 | { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY, HID_QUIRK_IGNORE }, | ||
366 | { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POCKETCASSY, HID_QUIRK_IGNORE }, | ||
367 | { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOBILECASSY, HID_QUIRK_IGNORE }, | ||
368 | { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_JWM, HID_QUIRK_IGNORE }, | ||
369 | { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_DMMP, HID_QUIRK_IGNORE }, | ||
370 | { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_UMIP, HID_QUIRK_IGNORE }, | ||
371 | { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY1, HID_QUIRK_IGNORE }, | ||
372 | { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY2, HID_QUIRK_IGNORE }, | ||
373 | { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_VIDEOCOM, HID_QUIRK_IGNORE }, | ||
374 | { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_COM3LAB, HID_QUIRK_IGNORE }, | ||
375 | { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_TELEPORT, HID_QUIRK_IGNORE }, | ||
376 | { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_NETWORKANALYSER, HID_QUIRK_IGNORE }, | ||
377 | { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POWERCONTROL, HID_QUIRK_IGNORE }, | ||
378 | { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MACHINETEST, HID_QUIRK_IGNORE }, | ||
379 | { USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1024LS, HID_QUIRK_IGNORE }, | ||
380 | { USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1208LS, HID_QUIRK_IGNORE }, | ||
381 | { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_IGNORE }, | ||
382 | { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS1, HID_QUIRK_IGNORE }, | ||
383 | { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100, HID_QUIRK_IGNORE }, | ||
384 | { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 20, HID_QUIRK_IGNORE }, | ||
385 | { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 30, HID_QUIRK_IGNORE }, | ||
386 | { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 100, HID_QUIRK_IGNORE }, | ||
387 | { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 108, HID_QUIRK_IGNORE }, | ||
388 | { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 118, HID_QUIRK_IGNORE }, | ||
389 | { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 200, HID_QUIRK_IGNORE }, | ||
390 | { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 300, HID_QUIRK_IGNORE }, | ||
391 | { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 400, HID_QUIRK_IGNORE }, | ||
392 | { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 500, HID_QUIRK_IGNORE }, | ||
393 | { USB_VENDOR_ID_PANJIT, 0x0001, HID_QUIRK_IGNORE }, | ||
394 | { USB_VENDOR_ID_PANJIT, 0x0002, HID_QUIRK_IGNORE }, | ||
395 | { USB_VENDOR_ID_PANJIT, 0x0003, HID_QUIRK_IGNORE }, | ||
396 | { USB_VENDOR_ID_PANJIT, 0x0004, HID_QUIRK_IGNORE }, | ||
397 | { USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LABPRO, HID_QUIRK_IGNORE }, | ||
398 | { USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_GOTEMP, HID_QUIRK_IGNORE }, | ||
399 | { USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_SKIP, HID_QUIRK_IGNORE }, | ||
400 | { USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_CYCLOPS, HID_QUIRK_IGNORE }, | ||
401 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20, HID_QUIRK_IGNORE }, | ||
402 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20, HID_QUIRK_IGNORE }, | ||
403 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_8_8_4_IF_KIT, HID_QUIRK_IGNORE }, | ||
404 | { USB_VENDOR_ID_YEALINK, USB_DEVICE_ID_YEALINK_P1K_P4K_B2K, HID_QUIRK_IGNORE }, | ||
405 | |||
406 | { USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_FLAIR, HID_QUIRK_IGNORE }, | ||
407 | { USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_302, HID_QUIRK_IGNORE }, | ||
408 | |||
409 | { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER, HID_QUIRK_LOGITECH_DESCRIPTOR }, | ||
410 | { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER, HID_QUIRK_LOGITECH_DESCRIPTOR }, | ||
411 | { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2, HID_QUIRK_LOGITECH_DESCRIPTOR }, | ||
412 | |||
413 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE, HID_QUIRK_MIGHTYMOUSE | HID_QUIRK_INVERT_HWHEEL }, | ||
414 | |||
415 | { USB_VENDOR_ID_PANTHERLORD, USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK, HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS }, | ||
416 | { USB_VENDOR_ID_PLAYDOTCOM, USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII, HID_QUIRK_MULTI_INPUT }, | ||
417 | |||
418 | { USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER, HID_QUIRK_SONY_PS3_CONTROLLER }, | ||
419 | |||
420 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET }, | ||
421 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET }, | ||
422 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET }, | ||
423 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET }, | ||
424 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET }, | ||
425 | { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET }, | ||
426 | { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET }, | ||
427 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, | ||
428 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, | ||
429 | |||
430 | { USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, | ||
431 | |||
432 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, | ||
433 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, | ||
434 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, | ||
435 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_POWERBOOK_ISO_KEYBOARD}, | ||
436 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, | ||
437 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, | ||
438 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_POWERBOOK_ISO_KEYBOARD}, | ||
439 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, | ||
440 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, | ||
441 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_POWERBOOK_ISO_KEYBOARD}, | ||
442 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, | ||
443 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, | ||
444 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, | ||
445 | |||
446 | { USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658, HID_QUIRK_RESET_LEDS }, | ||
447 | |||
448 | { 0, 0 } | ||
449 | }; | ||
450 | |||
451 | /* Dynamic HID quirks list - specified at runtime */ | ||
452 | struct quirks_list_struct { | ||
453 | struct hid_blacklist hid_bl_item; | ||
454 | struct list_head node; | ||
455 | }; | ||
456 | |||
457 | static LIST_HEAD(dquirks_list); | ||
458 | static DECLARE_RWSEM(dquirks_rwsem); | ||
459 | |||
460 | /* Runtime ("dynamic") quirks manipulation functions */ | ||
461 | |||
462 | /** | ||
463 | * usbhid_exists_dquirk: find any dynamic quirks for a USB HID device | ||
464 | * @idVendor: the 16-bit USB vendor ID, in native byteorder | ||
465 | * @idProduct: the 16-bit USB product ID, in native byteorder | ||
466 | * | ||
467 | * Description: | ||
468 | * Scans dquirks_list for a matching dynamic quirk and returns | ||
469 | * the pointer to the relevant struct hid_blacklist if found. | ||
470 | * Must be called with a read lock held on dquirks_rwsem. | ||
471 | * | ||
472 | * Returns: NULL if no quirk found, struct hid_blacklist * if found. | ||
473 | */ | ||
474 | static struct hid_blacklist *usbhid_exists_dquirk(const u16 idVendor, | ||
475 | const u16 idProduct) | ||
476 | { | ||
477 | struct quirks_list_struct *q; | ||
478 | struct hid_blacklist *bl_entry = NULL; | ||
479 | |||
480 | list_for_each_entry(q, &dquirks_list, node) { | ||
481 | if (q->hid_bl_item.idVendor == idVendor && | ||
482 | q->hid_bl_item.idProduct == idProduct) { | ||
483 | bl_entry = &q->hid_bl_item; | ||
484 | break; | ||
485 | } | ||
486 | } | ||
487 | |||
488 | if (bl_entry != NULL) | ||
489 | dbg("Found dynamic quirk 0x%x for USB HID vendor 0x%hx prod 0x%hx\n", | ||
490 | bl_entry->quirks, bl_entry->idVendor, | ||
491 | bl_entry->idProduct); | ||
492 | |||
493 | return bl_entry; | ||
494 | } | ||
495 | |||
496 | |||
497 | /** | ||
498 | * usbhid_modify_dquirk: add/replace a HID quirk | ||
499 | * @idVendor: the 16-bit USB vendor ID, in native byteorder | ||
500 | * @idProduct: the 16-bit USB product ID, in native byteorder | ||
501 | * @quirks: the u32 quirks value to add/replace | ||
502 | * | ||
503 | * Description: | ||
504 | * If an dynamic quirk exists in memory for this (idVendor, | ||
505 | * idProduct) pair, replace its quirks value with what was | ||
506 | * provided. Otherwise, add the quirk to the dynamic quirks list. | ||
507 | * | ||
508 | * Returns: 0 OK, -error on failure. | ||
509 | */ | ||
510 | int usbhid_modify_dquirk(const u16 idVendor, const u16 idProduct, | ||
511 | const u32 quirks) | ||
512 | { | ||
513 | struct quirks_list_struct *q_new, *q; | ||
514 | int list_edited = 0; | ||
515 | |||
516 | if (!idVendor) { | ||
517 | dbg("Cannot add a quirk with idVendor = 0"); | ||
518 | return -EINVAL; | ||
519 | } | ||
520 | |||
521 | q_new = kmalloc(sizeof(struct quirks_list_struct), GFP_KERNEL); | ||
522 | if (!q_new) { | ||
523 | dbg("Could not allocate quirks_list_struct"); | ||
524 | return -ENOMEM; | ||
525 | } | ||
526 | |||
527 | q_new->hid_bl_item.idVendor = idVendor; | ||
528 | q_new->hid_bl_item.idProduct = idProduct; | ||
529 | q_new->hid_bl_item.quirks = quirks; | ||
530 | |||
531 | down_write(&dquirks_rwsem); | ||
532 | |||
533 | list_for_each_entry(q, &dquirks_list, node) { | ||
534 | |||
535 | if (q->hid_bl_item.idVendor == idVendor && | ||
536 | q->hid_bl_item.idProduct == idProduct) { | ||
537 | |||
538 | list_replace(&q->node, &q_new->node); | ||
539 | kfree(q); | ||
540 | list_edited = 1; | ||
541 | break; | ||
542 | |||
543 | } | ||
544 | |||
545 | } | ||
546 | |||
547 | if (!list_edited) | ||
548 | list_add_tail(&q_new->node, &dquirks_list); | ||
549 | |||
550 | up_write(&dquirks_rwsem); | ||
551 | |||
552 | return 0; | ||
553 | } | ||
554 | |||
555 | |||
556 | /** | ||
557 | * usbhid_remove_all_dquirks: remove all runtime HID quirks from memory | ||
558 | * | ||
559 | * Description: | ||
560 | * Free all memory associated with dynamic quirks - called before | ||
561 | * module unload. | ||
562 | * | ||
563 | */ | ||
564 | static void usbhid_remove_all_dquirks(void) | ||
565 | { | ||
566 | struct quirks_list_struct *q, *temp; | ||
567 | |||
568 | down_write(&dquirks_rwsem); | ||
569 | list_for_each_entry_safe(q, temp, &dquirks_list, node) { | ||
570 | list_del(&q->node); | ||
571 | kfree(q); | ||
572 | } | ||
573 | up_write(&dquirks_rwsem); | ||
574 | |||
575 | } | ||
576 | |||
577 | /** | ||
578 | * usbhid_quirks_init: apply USB HID quirks specified at module load time | ||
579 | */ | ||
580 | int usbhid_quirks_init(char **quirks_param) | ||
581 | { | ||
582 | u16 idVendor, idProduct; | ||
583 | u32 quirks; | ||
584 | int n = 0, m; | ||
585 | |||
586 | for (; quirks_param[n] && n < MAX_USBHID_BOOT_QUIRKS; n++) { | ||
587 | |||
588 | m = sscanf(quirks_param[n], "0x%hx:0x%hx:0x%x", | ||
589 | &idVendor, &idProduct, &quirks); | ||
590 | |||
591 | if (m != 3 || | ||
592 | usbhid_modify_dquirk(idVendor, idProduct, quirks) != 0) { | ||
593 | printk(KERN_WARNING | ||
594 | "Could not parse HID quirk module param %s\n", | ||
595 | quirks_param[n]); | ||
596 | } | ||
597 | } | ||
598 | |||
599 | return 0; | ||
600 | } | ||
601 | |||
602 | /** | ||
603 | * usbhid_quirks_exit: release memory associated with dynamic_quirks | ||
604 | * | ||
605 | * Description: | ||
606 | * Release all memory associated with dynamic quirks. Called upon | ||
607 | * module unload. | ||
608 | * | ||
609 | * Returns: nothing | ||
610 | */ | ||
611 | void usbhid_quirks_exit(void) | ||
612 | { | ||
613 | usbhid_remove_all_dquirks(); | ||
614 | } | ||
615 | |||
616 | /** | ||
617 | * usbhid_exists_squirk: return any static quirks for a USB HID device | ||
618 | * @idVendor: the 16-bit USB vendor ID, in native byteorder | ||
619 | * @idProduct: the 16-bit USB product ID, in native byteorder | ||
620 | * | ||
621 | * Description: | ||
622 | * Given a USB vendor ID and product ID, return a pointer to | ||
623 | * the hid_blacklist entry associated with that device. | ||
624 | * | ||
625 | * Returns: pointer if quirk found, or NULL if no quirks found. | ||
626 | */ | ||
627 | static const struct hid_blacklist *usbhid_exists_squirk(const u16 idVendor, | ||
628 | const u16 idProduct) | ||
629 | { | ||
630 | const struct hid_blacklist *bl_entry = NULL; | ||
631 | int n = 0; | ||
632 | |||
633 | for (; hid_blacklist[n].idVendor; n++) | ||
634 | if (hid_blacklist[n].idVendor == idVendor && | ||
635 | hid_blacklist[n].idProduct == idProduct) | ||
636 | bl_entry = &hid_blacklist[n]; | ||
637 | |||
638 | if (bl_entry != NULL) | ||
639 | dbg("Found squirk 0x%x for USB HID vendor 0x%hx prod 0x%hx\n", | ||
640 | bl_entry->quirks, bl_entry->idVendor, | ||
641 | bl_entry->idProduct); | ||
642 | return bl_entry; | ||
643 | } | ||
644 | |||
645 | /** | ||
646 | * usbhid_lookup_quirk: return any quirks associated with a USB HID device | ||
647 | * @idVendor: the 16-bit USB vendor ID, in native byteorder | ||
648 | * @idProduct: the 16-bit USB product ID, in native byteorder | ||
649 | * | ||
650 | * Description: | ||
651 | * Given a USB vendor ID and product ID, return any quirks associated | ||
652 | * with that device. | ||
653 | * | ||
654 | * Returns: a u32 quirks value. | ||
655 | */ | ||
656 | u32 usbhid_lookup_quirk(const u16 idVendor, const u16 idProduct) | ||
657 | { | ||
658 | u32 quirks = 0; | ||
659 | const struct hid_blacklist *bl_entry = NULL; | ||
660 | |||
661 | /* Ignore all Wacom devices */ | ||
662 | if (idVendor == USB_VENDOR_ID_WACOM) | ||
663 | return HID_QUIRK_IGNORE; | ||
664 | |||
665 | /* ignore all Code Mercenaries IOWarrior devices */ | ||
666 | if (idVendor == USB_VENDOR_ID_CODEMERCS) | ||
667 | if (idProduct >= USB_DEVICE_ID_CODEMERCS_IOW_FIRST && | ||
668 | idProduct <= USB_DEVICE_ID_CODEMERCS_IOW_LAST) | ||
669 | return HID_QUIRK_IGNORE; | ||
670 | |||
671 | down_read(&dquirks_rwsem); | ||
672 | bl_entry = usbhid_exists_dquirk(idVendor, idProduct); | ||
673 | if (!bl_entry) | ||
674 | bl_entry = usbhid_exists_squirk(idVendor, idProduct); | ||
675 | if (bl_entry) | ||
676 | quirks = bl_entry->quirks; | ||
677 | up_read(&dquirks_rwsem); | ||
678 | |||
679 | return quirks; | ||
680 | } | ||
681 | |||
diff --git a/drivers/hid/usbhid/hid-tmff.c b/drivers/hid/usbhid/hid-tmff.c new file mode 100644 index 000000000000..ab67331620d0 --- /dev/null +++ b/drivers/hid/usbhid/hid-tmff.c | |||
@@ -0,0 +1,147 @@ | |||
1 | /* | ||
2 | * Force feedback support for various HID compliant devices by ThrustMaster: | ||
3 | * ThrustMaster FireStorm Dual Power 2 | ||
4 | * and possibly others whose device ids haven't been added. | ||
5 | * | ||
6 | * Modified to support ThrustMaster devices by Zinx Verituse | ||
7 | * on 2003-01-25 from the Logitech force feedback driver, | ||
8 | * which is by Johann Deneux. | ||
9 | * | ||
10 | * Copyright (c) 2003 Zinx Verituse <zinx@epicsol.org> | ||
11 | * Copyright (c) 2002 Johann Deneux | ||
12 | */ | ||
13 | |||
14 | /* | ||
15 | * This program is free software; you can redistribute it and/or modify | ||
16 | * it under the terms of the GNU General Public License as published by | ||
17 | * the Free Software Foundation; either version 2 of the License, or | ||
18 | * (at your option) any later version. | ||
19 | * | ||
20 | * This program is distributed in the hope that it will be useful, | ||
21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
23 | * GNU General Public License for more details. | ||
24 | * | ||
25 | * You should have received a copy of the GNU General Public License | ||
26 | * along with this program; if not, write to the Free Software | ||
27 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
28 | */ | ||
29 | |||
30 | #include <linux/input.h> | ||
31 | |||
32 | #undef DEBUG | ||
33 | #include <linux/usb.h> | ||
34 | |||
35 | #include <linux/hid.h> | ||
36 | #include "usbhid.h" | ||
37 | |||
38 | /* Usages for thrustmaster devices I know about */ | ||
39 | #define THRUSTMASTER_USAGE_RUMBLE_LR (HID_UP_GENDESK | 0xbb) | ||
40 | |||
41 | |||
42 | struct tmff_device { | ||
43 | struct hid_report *report; | ||
44 | struct hid_field *rumble; | ||
45 | }; | ||
46 | |||
47 | /* Changes values from 0 to 0xffff into values from minimum to maximum */ | ||
48 | static inline int hid_tmff_scale(unsigned int in, int minimum, int maximum) | ||
49 | { | ||
50 | int ret; | ||
51 | |||
52 | ret = (in * (maximum - minimum) / 0xffff) + minimum; | ||
53 | if (ret < minimum) | ||
54 | return minimum; | ||
55 | if (ret > maximum) | ||
56 | return maximum; | ||
57 | return ret; | ||
58 | } | ||
59 | |||
60 | static int hid_tmff_play(struct input_dev *dev, void *data, struct ff_effect *effect) | ||
61 | { | ||
62 | struct hid_device *hid = dev->private; | ||
63 | struct tmff_device *tmff = data; | ||
64 | int left, right; /* Rumbling */ | ||
65 | |||
66 | left = hid_tmff_scale(effect->u.rumble.weak_magnitude, | ||
67 | tmff->rumble->logical_minimum, tmff->rumble->logical_maximum); | ||
68 | right = hid_tmff_scale(effect->u.rumble.strong_magnitude, | ||
69 | tmff->rumble->logical_minimum, tmff->rumble->logical_maximum); | ||
70 | |||
71 | tmff->rumble->value[0] = left; | ||
72 | tmff->rumble->value[1] = right; | ||
73 | dbg("(left,right)=(%08x, %08x)", left, right); | ||
74 | usbhid_submit_report(hid, tmff->report, USB_DIR_OUT); | ||
75 | |||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | int hid_tmff_init(struct hid_device *hid) | ||
80 | { | ||
81 | struct tmff_device *tmff; | ||
82 | struct list_head *pos; | ||
83 | struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); | ||
84 | struct input_dev *input_dev = hidinput->input; | ||
85 | int error; | ||
86 | |||
87 | tmff = kzalloc(sizeof(struct tmff_device), GFP_KERNEL); | ||
88 | if (!tmff) | ||
89 | return -ENOMEM; | ||
90 | |||
91 | /* Find the report to use */ | ||
92 | __list_for_each(pos, &hid->report_enum[HID_OUTPUT_REPORT].report_list) { | ||
93 | struct hid_report *report = (struct hid_report *)pos; | ||
94 | int fieldnum; | ||
95 | |||
96 | for (fieldnum = 0; fieldnum < report->maxfield; ++fieldnum) { | ||
97 | struct hid_field *field = report->field[fieldnum]; | ||
98 | |||
99 | if (field->maxusage <= 0) | ||
100 | continue; | ||
101 | |||
102 | switch (field->usage[0].hid) { | ||
103 | case THRUSTMASTER_USAGE_RUMBLE_LR: | ||
104 | if (field->report_count < 2) { | ||
105 | warn("ignoring THRUSTMASTER_USAGE_RUMBLE_LR with report_count < 2"); | ||
106 | continue; | ||
107 | } | ||
108 | |||
109 | if (field->logical_maximum == field->logical_minimum) { | ||
110 | warn("ignoring THRUSTMASTER_USAGE_RUMBLE_LR with logical_maximum == logical_minimum"); | ||
111 | continue; | ||
112 | } | ||
113 | |||
114 | if (tmff->report && tmff->report != report) { | ||
115 | warn("ignoring THRUSTMASTER_USAGE_RUMBLE_LR in other report"); | ||
116 | continue; | ||
117 | } | ||
118 | |||
119 | if (tmff->rumble && tmff->rumble != field) { | ||
120 | warn("ignoring duplicate THRUSTMASTER_USAGE_RUMBLE_LR"); | ||
121 | continue; | ||
122 | } | ||
123 | |||
124 | tmff->report = report; | ||
125 | tmff->rumble = field; | ||
126 | |||
127 | set_bit(FF_RUMBLE, input_dev->ffbit); | ||
128 | break; | ||
129 | |||
130 | default: | ||
131 | warn("ignoring unknown output usage %08x", field->usage[0].hid); | ||
132 | continue; | ||
133 | } | ||
134 | } | ||
135 | } | ||
136 | |||
137 | error = input_ff_create_memless(input_dev, tmff, hid_tmff_play); | ||
138 | if (error) { | ||
139 | kfree(tmff); | ||
140 | return error; | ||
141 | } | ||
142 | |||
143 | info("Force feedback for ThrustMaster rumble pad devices by Zinx Verituse <zinx@epicsol.org>"); | ||
144 | |||
145 | return 0; | ||
146 | } | ||
147 | |||
diff --git a/drivers/hid/usbhid/hid-zpff.c b/drivers/hid/usbhid/hid-zpff.c new file mode 100644 index 000000000000..7bd8238ca212 --- /dev/null +++ b/drivers/hid/usbhid/hid-zpff.c | |||
@@ -0,0 +1,111 @@ | |||
1 | /* | ||
2 | * Force feedback support for Zeroplus based devices | ||
3 | * | ||
4 | * Copyright (c) 2005, 2006 Anssi Hannula <anssi.hannula@gmail.com> | ||
5 | */ | ||
6 | |||
7 | /* | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | */ | ||
22 | |||
23 | |||
24 | /* #define DEBUG */ | ||
25 | |||
26 | #define debug(format, arg...) pr_debug("hid-zpff: " format "\n" , ## arg) | ||
27 | |||
28 | #include <linux/input.h> | ||
29 | #include <linux/usb.h> | ||
30 | #include <linux/hid.h> | ||
31 | #include "usbhid.h" | ||
32 | |||
33 | struct zpff_device { | ||
34 | struct hid_report *report; | ||
35 | }; | ||
36 | |||
37 | static int hid_zpff_play(struct input_dev *dev, void *data, | ||
38 | struct ff_effect *effect) | ||
39 | { | ||
40 | struct hid_device *hid = dev->private; | ||
41 | struct zpff_device *zpff = data; | ||
42 | int left, right; | ||
43 | |||
44 | /* | ||
45 | * The following is specified the other way around in the Zeroplus | ||
46 | * datasheet but the order below is correct for the XFX Executioner; | ||
47 | * however it is possible that the XFX Executioner is an exception | ||
48 | */ | ||
49 | |||
50 | left = effect->u.rumble.strong_magnitude; | ||
51 | right = effect->u.rumble.weak_magnitude; | ||
52 | debug("called with 0x%04x 0x%04x", left, right); | ||
53 | |||
54 | left = left * 0x7f / 0xffff; | ||
55 | right = right * 0x7f / 0xffff; | ||
56 | |||
57 | zpff->report->field[2]->value[0] = left; | ||
58 | zpff->report->field[3]->value[0] = right; | ||
59 | debug("running with 0x%02x 0x%02x", left, right); | ||
60 | usbhid_submit_report(hid, zpff->report, USB_DIR_OUT); | ||
61 | |||
62 | return 0; | ||
63 | } | ||
64 | |||
65 | int hid_zpff_init(struct hid_device *hid) | ||
66 | { | ||
67 | struct zpff_device *zpff; | ||
68 | struct hid_report *report; | ||
69 | struct hid_input *hidinput = list_entry(hid->inputs.next, | ||
70 | struct hid_input, list); | ||
71 | struct list_head *report_list = | ||
72 | &hid->report_enum[HID_OUTPUT_REPORT].report_list; | ||
73 | struct input_dev *dev = hidinput->input; | ||
74 | int error; | ||
75 | |||
76 | if (list_empty(report_list)) { | ||
77 | printk(KERN_ERR "hid-zpff: no output report found\n"); | ||
78 | return -ENODEV; | ||
79 | } | ||
80 | |||
81 | report = list_entry(report_list->next, struct hid_report, list); | ||
82 | |||
83 | if (report->maxfield < 4) { | ||
84 | printk(KERN_ERR "hid-zpff: not enough fields in report\n"); | ||
85 | return -ENODEV; | ||
86 | } | ||
87 | |||
88 | zpff = kzalloc(sizeof(struct zpff_device), GFP_KERNEL); | ||
89 | if (!zpff) | ||
90 | return -ENOMEM; | ||
91 | |||
92 | set_bit(FF_RUMBLE, dev->ffbit); | ||
93 | |||
94 | error = input_ff_create_memless(dev, zpff, hid_zpff_play); | ||
95 | if (error) { | ||
96 | kfree(zpff); | ||
97 | return error; | ||
98 | } | ||
99 | |||
100 | zpff->report = report; | ||
101 | zpff->report->field[0]->value[0] = 0x00; | ||
102 | zpff->report->field[1]->value[0] = 0x02; | ||
103 | zpff->report->field[2]->value[0] = 0x00; | ||
104 | zpff->report->field[3]->value[0] = 0x00; | ||
105 | usbhid_submit_report(hid, zpff->report, USB_DIR_OUT); | ||
106 | |||
107 | printk(KERN_INFO "Force feedback for Zeroplus based devices by " | ||
108 | "Anssi Hannula <anssi.hannula@gmail.com>\n"); | ||
109 | |||
110 | return 0; | ||
111 | } | ||
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c new file mode 100644 index 000000000000..a8b3d66cd498 --- /dev/null +++ b/drivers/hid/usbhid/hiddev.c | |||
@@ -0,0 +1,847 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2001 Paul Stewart | ||
3 | * Copyright (c) 2001 Vojtech Pavlik | ||
4 | * | ||
5 | * HID char devices, giving access to raw HID device events. | ||
6 | * | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
23 | * | ||
24 | * Should you need to contact me, the author, you can do so either by | ||
25 | * e-mail - mail your message to Paul Stewart <stewart@wetlogic.net> | ||
26 | */ | ||
27 | |||
28 | #include <linux/poll.h> | ||
29 | #include <linux/slab.h> | ||
30 | #include <linux/module.h> | ||
31 | #include <linux/init.h> | ||
32 | #include <linux/smp_lock.h> | ||
33 | #include <linux/input.h> | ||
34 | #include <linux/usb.h> | ||
35 | #include <linux/hid.h> | ||
36 | #include <linux/hiddev.h> | ||
37 | #include "usbhid.h" | ||
38 | |||
39 | #ifdef CONFIG_USB_DYNAMIC_MINORS | ||
40 | #define HIDDEV_MINOR_BASE 0 | ||
41 | #define HIDDEV_MINORS 256 | ||
42 | #else | ||
43 | #define HIDDEV_MINOR_BASE 96 | ||
44 | #define HIDDEV_MINORS 16 | ||
45 | #endif | ||
46 | #define HIDDEV_BUFFER_SIZE 64 | ||
47 | |||
48 | struct hiddev { | ||
49 | int exist; | ||
50 | int open; | ||
51 | wait_queue_head_t wait; | ||
52 | struct hid_device *hid; | ||
53 | struct list_head list; | ||
54 | }; | ||
55 | |||
56 | struct hiddev_list { | ||
57 | struct hiddev_usage_ref buffer[HIDDEV_BUFFER_SIZE]; | ||
58 | int head; | ||
59 | int tail; | ||
60 | unsigned flags; | ||
61 | struct fasync_struct *fasync; | ||
62 | struct hiddev *hiddev; | ||
63 | struct list_head node; | ||
64 | }; | ||
65 | |||
66 | static struct hiddev *hiddev_table[HIDDEV_MINORS]; | ||
67 | |||
68 | /* | ||
69 | * Find a report, given the report's type and ID. The ID can be specified | ||
70 | * indirectly by REPORT_ID_FIRST (which returns the first report of the given | ||
71 | * type) or by (REPORT_ID_NEXT | old_id), which returns the next report of the | ||
72 | * given type which follows old_id. | ||
73 | */ | ||
74 | static struct hid_report * | ||
75 | hiddev_lookup_report(struct hid_device *hid, struct hiddev_report_info *rinfo) | ||
76 | { | ||
77 | unsigned int flags = rinfo->report_id & ~HID_REPORT_ID_MASK; | ||
78 | unsigned int rid = rinfo->report_id & HID_REPORT_ID_MASK; | ||
79 | struct hid_report_enum *report_enum; | ||
80 | struct hid_report *report; | ||
81 | struct list_head *list; | ||
82 | |||
83 | if (rinfo->report_type < HID_REPORT_TYPE_MIN || | ||
84 | rinfo->report_type > HID_REPORT_TYPE_MAX) | ||
85 | return NULL; | ||
86 | |||
87 | report_enum = hid->report_enum + | ||
88 | (rinfo->report_type - HID_REPORT_TYPE_MIN); | ||
89 | |||
90 | switch (flags) { | ||
91 | case 0: /* Nothing to do -- report_id is already set correctly */ | ||
92 | break; | ||
93 | |||
94 | case HID_REPORT_ID_FIRST: | ||
95 | if (list_empty(&report_enum->report_list)) | ||
96 | return NULL; | ||
97 | |||
98 | list = report_enum->report_list.next; | ||
99 | report = list_entry(list, struct hid_report, list); | ||
100 | rinfo->report_id = report->id; | ||
101 | break; | ||
102 | |||
103 | case HID_REPORT_ID_NEXT: | ||
104 | report = report_enum->report_id_hash[rid]; | ||
105 | if (!report) | ||
106 | return NULL; | ||
107 | |||
108 | list = report->list.next; | ||
109 | if (list == &report_enum->report_list) | ||
110 | return NULL; | ||
111 | |||
112 | report = list_entry(list, struct hid_report, list); | ||
113 | rinfo->report_id = report->id; | ||
114 | break; | ||
115 | |||
116 | default: | ||
117 | return NULL; | ||
118 | } | ||
119 | |||
120 | return report_enum->report_id_hash[rinfo->report_id]; | ||
121 | } | ||
122 | |||
123 | /* | ||
124 | * Perform an exhaustive search of the report table for a usage, given its | ||
125 | * type and usage id. | ||
126 | */ | ||
127 | static struct hid_field * | ||
128 | hiddev_lookup_usage(struct hid_device *hid, struct hiddev_usage_ref *uref) | ||
129 | { | ||
130 | int i, j; | ||
131 | struct hid_report *report; | ||
132 | struct hid_report_enum *report_enum; | ||
133 | struct hid_field *field; | ||
134 | |||
135 | if (uref->report_type < HID_REPORT_TYPE_MIN || | ||
136 | uref->report_type > HID_REPORT_TYPE_MAX) | ||
137 | return NULL; | ||
138 | |||
139 | report_enum = hid->report_enum + | ||
140 | (uref->report_type - HID_REPORT_TYPE_MIN); | ||
141 | |||
142 | list_for_each_entry(report, &report_enum->report_list, list) { | ||
143 | for (i = 0; i < report->maxfield; i++) { | ||
144 | field = report->field[i]; | ||
145 | for (j = 0; j < field->maxusage; j++) { | ||
146 | if (field->usage[j].hid == uref->usage_code) { | ||
147 | uref->report_id = report->id; | ||
148 | uref->field_index = i; | ||
149 | uref->usage_index = j; | ||
150 | return field; | ||
151 | } | ||
152 | } | ||
153 | } | ||
154 | } | ||
155 | |||
156 | return NULL; | ||
157 | } | ||
158 | |||
159 | static void hiddev_send_event(struct hid_device *hid, | ||
160 | struct hiddev_usage_ref *uref) | ||
161 | { | ||
162 | struct hiddev *hiddev = hid->hiddev; | ||
163 | struct hiddev_list *list; | ||
164 | |||
165 | list_for_each_entry(list, &hiddev->list, node) { | ||
166 | if (uref->field_index != HID_FIELD_INDEX_NONE || | ||
167 | (list->flags & HIDDEV_FLAG_REPORT) != 0) { | ||
168 | list->buffer[list->head] = *uref; | ||
169 | list->head = (list->head + 1) & | ||
170 | (HIDDEV_BUFFER_SIZE - 1); | ||
171 | kill_fasync(&list->fasync, SIGIO, POLL_IN); | ||
172 | } | ||
173 | } | ||
174 | |||
175 | wake_up_interruptible(&hiddev->wait); | ||
176 | } | ||
177 | |||
178 | /* | ||
179 | * This is where hid.c calls into hiddev to pass an event that occurred over | ||
180 | * the interrupt pipe | ||
181 | */ | ||
182 | void hiddev_hid_event(struct hid_device *hid, struct hid_field *field, | ||
183 | struct hid_usage *usage, __s32 value) | ||
184 | { | ||
185 | unsigned type = field->report_type; | ||
186 | struct hiddev_usage_ref uref; | ||
187 | |||
188 | uref.report_type = | ||
189 | (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT : | ||
190 | ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT : | ||
191 | ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE : 0)); | ||
192 | uref.report_id = field->report->id; | ||
193 | uref.field_index = field->index; | ||
194 | uref.usage_index = (usage - field->usage); | ||
195 | uref.usage_code = usage->hid; | ||
196 | uref.value = value; | ||
197 | |||
198 | hiddev_send_event(hid, &uref); | ||
199 | } | ||
200 | EXPORT_SYMBOL_GPL(hiddev_hid_event); | ||
201 | |||
202 | void hiddev_report_event(struct hid_device *hid, struct hid_report *report) | ||
203 | { | ||
204 | unsigned type = report->type; | ||
205 | struct hiddev_usage_ref uref; | ||
206 | |||
207 | memset(&uref, 0, sizeof(uref)); | ||
208 | uref.report_type = | ||
209 | (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT : | ||
210 | ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT : | ||
211 | ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE : 0)); | ||
212 | uref.report_id = report->id; | ||
213 | uref.field_index = HID_FIELD_INDEX_NONE; | ||
214 | |||
215 | hiddev_send_event(hid, &uref); | ||
216 | } | ||
217 | |||
218 | /* | ||
219 | * fasync file op | ||
220 | */ | ||
221 | static int hiddev_fasync(int fd, struct file *file, int on) | ||
222 | { | ||
223 | int retval; | ||
224 | struct hiddev_list *list = file->private_data; | ||
225 | |||
226 | retval = fasync_helper(fd, file, on, &list->fasync); | ||
227 | |||
228 | return retval < 0 ? retval : 0; | ||
229 | } | ||
230 | |||
231 | |||
232 | /* | ||
233 | * release file op | ||
234 | */ | ||
235 | static int hiddev_release(struct inode * inode, struct file * file) | ||
236 | { | ||
237 | struct hiddev_list *list = file->private_data; | ||
238 | |||
239 | hiddev_fasync(-1, file, 0); | ||
240 | list_del(&list->node); | ||
241 | |||
242 | if (!--list->hiddev->open) { | ||
243 | if (list->hiddev->exist) | ||
244 | usbhid_close(list->hiddev->hid); | ||
245 | else | ||
246 | kfree(list->hiddev); | ||
247 | } | ||
248 | |||
249 | kfree(list); | ||
250 | |||
251 | return 0; | ||
252 | } | ||
253 | |||
254 | /* | ||
255 | * open file op | ||
256 | */ | ||
257 | static int hiddev_open(struct inode *inode, struct file *file) | ||
258 | { | ||
259 | struct hiddev_list *list; | ||
260 | |||
261 | int i = iminor(inode) - HIDDEV_MINOR_BASE; | ||
262 | |||
263 | if (i >= HIDDEV_MINORS || !hiddev_table[i]) | ||
264 | return -ENODEV; | ||
265 | |||
266 | if (!(list = kzalloc(sizeof(struct hiddev_list), GFP_KERNEL))) | ||
267 | return -ENOMEM; | ||
268 | |||
269 | list->hiddev = hiddev_table[i]; | ||
270 | list_add_tail(&list->node, &hiddev_table[i]->list); | ||
271 | file->private_data = list; | ||
272 | |||
273 | if (!list->hiddev->open++) | ||
274 | if (list->hiddev->exist) | ||
275 | usbhid_open(hiddev_table[i]->hid); | ||
276 | |||
277 | return 0; | ||
278 | } | ||
279 | |||
280 | /* | ||
281 | * "write" file op | ||
282 | */ | ||
283 | static ssize_t hiddev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos) | ||
284 | { | ||
285 | return -EINVAL; | ||
286 | } | ||
287 | |||
288 | /* | ||
289 | * "read" file op | ||
290 | */ | ||
291 | static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t count, loff_t *ppos) | ||
292 | { | ||
293 | DECLARE_WAITQUEUE(wait, current); | ||
294 | struct hiddev_list *list = file->private_data; | ||
295 | int event_size; | ||
296 | int retval = 0; | ||
297 | |||
298 | event_size = ((list->flags & HIDDEV_FLAG_UREF) != 0) ? | ||
299 | sizeof(struct hiddev_usage_ref) : sizeof(struct hiddev_event); | ||
300 | |||
301 | if (count < event_size) | ||
302 | return 0; | ||
303 | |||
304 | while (retval == 0) { | ||
305 | if (list->head == list->tail) { | ||
306 | add_wait_queue(&list->hiddev->wait, &wait); | ||
307 | set_current_state(TASK_INTERRUPTIBLE); | ||
308 | |||
309 | while (list->head == list->tail) { | ||
310 | if (file->f_flags & O_NONBLOCK) { | ||
311 | retval = -EAGAIN; | ||
312 | break; | ||
313 | } | ||
314 | if (signal_pending(current)) { | ||
315 | retval = -ERESTARTSYS; | ||
316 | break; | ||
317 | } | ||
318 | if (!list->hiddev->exist) { | ||
319 | retval = -EIO; | ||
320 | break; | ||
321 | } | ||
322 | |||
323 | schedule(); | ||
324 | set_current_state(TASK_INTERRUPTIBLE); | ||
325 | } | ||
326 | |||
327 | set_current_state(TASK_RUNNING); | ||
328 | remove_wait_queue(&list->hiddev->wait, &wait); | ||
329 | } | ||
330 | |||
331 | if (retval) | ||
332 | return retval; | ||
333 | |||
334 | |||
335 | while (list->head != list->tail && | ||
336 | retval + event_size <= count) { | ||
337 | if ((list->flags & HIDDEV_FLAG_UREF) == 0) { | ||
338 | if (list->buffer[list->tail].field_index != | ||
339 | HID_FIELD_INDEX_NONE) { | ||
340 | struct hiddev_event event; | ||
341 | event.hid = list->buffer[list->tail].usage_code; | ||
342 | event.value = list->buffer[list->tail].value; | ||
343 | if (copy_to_user(buffer + retval, &event, sizeof(struct hiddev_event))) | ||
344 | return -EFAULT; | ||
345 | retval += sizeof(struct hiddev_event); | ||
346 | } | ||
347 | } else { | ||
348 | if (list->buffer[list->tail].field_index != HID_FIELD_INDEX_NONE || | ||
349 | (list->flags & HIDDEV_FLAG_REPORT) != 0) { | ||
350 | if (copy_to_user(buffer + retval, list->buffer + list->tail, sizeof(struct hiddev_usage_ref))) | ||
351 | return -EFAULT; | ||
352 | retval += sizeof(struct hiddev_usage_ref); | ||
353 | } | ||
354 | } | ||
355 | list->tail = (list->tail + 1) & (HIDDEV_BUFFER_SIZE - 1); | ||
356 | } | ||
357 | |||
358 | } | ||
359 | |||
360 | return retval; | ||
361 | } | ||
362 | |||
363 | /* | ||
364 | * "poll" file op | ||
365 | * No kernel lock - fine | ||
366 | */ | ||
367 | static unsigned int hiddev_poll(struct file *file, poll_table *wait) | ||
368 | { | ||
369 | struct hiddev_list *list = file->private_data; | ||
370 | |||
371 | poll_wait(file, &list->hiddev->wait, wait); | ||
372 | if (list->head != list->tail) | ||
373 | return POLLIN | POLLRDNORM; | ||
374 | if (!list->hiddev->exist) | ||
375 | return POLLERR | POLLHUP; | ||
376 | return 0; | ||
377 | } | ||
378 | |||
379 | /* | ||
380 | * "ioctl" file op | ||
381 | */ | ||
382 | static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) | ||
383 | { | ||
384 | struct hiddev_list *list = file->private_data; | ||
385 | struct hiddev *hiddev = list->hiddev; | ||
386 | struct hid_device *hid = hiddev->hid; | ||
387 | struct usb_device *dev = hid_to_usb_dev(hid); | ||
388 | struct hiddev_collection_info cinfo; | ||
389 | struct hiddev_report_info rinfo; | ||
390 | struct hiddev_field_info finfo; | ||
391 | struct hiddev_usage_ref_multi *uref_multi = NULL; | ||
392 | struct hiddev_usage_ref *uref; | ||
393 | struct hiddev_devinfo dinfo; | ||
394 | struct hid_report *report; | ||
395 | struct hid_field *field; | ||
396 | struct usbhid_device *usbhid = hid->driver_data; | ||
397 | void __user *user_arg = (void __user *)arg; | ||
398 | int i; | ||
399 | |||
400 | if (!hiddev->exist) | ||
401 | return -EIO; | ||
402 | |||
403 | switch (cmd) { | ||
404 | |||
405 | case HIDIOCGVERSION: | ||
406 | return put_user(HID_VERSION, (int __user *)arg); | ||
407 | |||
408 | case HIDIOCAPPLICATION: | ||
409 | if (arg < 0 || arg >= hid->maxapplication) | ||
410 | return -EINVAL; | ||
411 | |||
412 | for (i = 0; i < hid->maxcollection; i++) | ||
413 | if (hid->collection[i].type == | ||
414 | HID_COLLECTION_APPLICATION && arg-- == 0) | ||
415 | break; | ||
416 | |||
417 | if (i == hid->maxcollection) | ||
418 | return -EINVAL; | ||
419 | |||
420 | return hid->collection[i].usage; | ||
421 | |||
422 | case HIDIOCGDEVINFO: | ||
423 | dinfo.bustype = BUS_USB; | ||
424 | dinfo.busnum = dev->bus->busnum; | ||
425 | dinfo.devnum = dev->devnum; | ||
426 | dinfo.ifnum = usbhid->ifnum; | ||
427 | dinfo.vendor = le16_to_cpu(dev->descriptor.idVendor); | ||
428 | dinfo.product = le16_to_cpu(dev->descriptor.idProduct); | ||
429 | dinfo.version = le16_to_cpu(dev->descriptor.bcdDevice); | ||
430 | dinfo.num_applications = hid->maxapplication; | ||
431 | if (copy_to_user(user_arg, &dinfo, sizeof(dinfo))) | ||
432 | return -EFAULT; | ||
433 | |||
434 | return 0; | ||
435 | |||
436 | case HIDIOCGFLAG: | ||
437 | if (put_user(list->flags, (int __user *)arg)) | ||
438 | return -EFAULT; | ||
439 | |||
440 | return 0; | ||
441 | |||
442 | case HIDIOCSFLAG: | ||
443 | { | ||
444 | int newflags; | ||
445 | if (get_user(newflags, (int __user *)arg)) | ||
446 | return -EFAULT; | ||
447 | |||
448 | if ((newflags & ~HIDDEV_FLAGS) != 0 || | ||
449 | ((newflags & HIDDEV_FLAG_REPORT) != 0 && | ||
450 | (newflags & HIDDEV_FLAG_UREF) == 0)) | ||
451 | return -EINVAL; | ||
452 | |||
453 | list->flags = newflags; | ||
454 | |||
455 | return 0; | ||
456 | } | ||
457 | |||
458 | case HIDIOCGSTRING: | ||
459 | { | ||
460 | int idx, len; | ||
461 | char *buf; | ||
462 | |||
463 | if (get_user(idx, (int __user *)arg)) | ||
464 | return -EFAULT; | ||
465 | |||
466 | if ((buf = kmalloc(HID_STRING_SIZE, GFP_KERNEL)) == NULL) | ||
467 | return -ENOMEM; | ||
468 | |||
469 | if ((len = usb_string(dev, idx, buf, HID_STRING_SIZE-1)) < 0) { | ||
470 | kfree(buf); | ||
471 | return -EINVAL; | ||
472 | } | ||
473 | |||
474 | if (copy_to_user(user_arg+sizeof(int), buf, len+1)) { | ||
475 | kfree(buf); | ||
476 | return -EFAULT; | ||
477 | } | ||
478 | |||
479 | kfree(buf); | ||
480 | |||
481 | return len; | ||
482 | } | ||
483 | |||
484 | case HIDIOCINITREPORT: | ||
485 | usbhid_init_reports(hid); | ||
486 | |||
487 | return 0; | ||
488 | |||
489 | case HIDIOCGREPORT: | ||
490 | if (copy_from_user(&rinfo, user_arg, sizeof(rinfo))) | ||
491 | return -EFAULT; | ||
492 | |||
493 | if (rinfo.report_type == HID_REPORT_TYPE_OUTPUT) | ||
494 | return -EINVAL; | ||
495 | |||
496 | if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) | ||
497 | return -EINVAL; | ||
498 | |||
499 | usbhid_submit_report(hid, report, USB_DIR_IN); | ||
500 | usbhid_wait_io(hid); | ||
501 | |||
502 | return 0; | ||
503 | |||
504 | case HIDIOCSREPORT: | ||
505 | if (copy_from_user(&rinfo, user_arg, sizeof(rinfo))) | ||
506 | return -EFAULT; | ||
507 | |||
508 | if (rinfo.report_type == HID_REPORT_TYPE_INPUT) | ||
509 | return -EINVAL; | ||
510 | |||
511 | if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) | ||
512 | return -EINVAL; | ||
513 | |||
514 | usbhid_submit_report(hid, report, USB_DIR_OUT); | ||
515 | usbhid_wait_io(hid); | ||
516 | |||
517 | return 0; | ||
518 | |||
519 | case HIDIOCGREPORTINFO: | ||
520 | if (copy_from_user(&rinfo, user_arg, sizeof(rinfo))) | ||
521 | return -EFAULT; | ||
522 | |||
523 | if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) | ||
524 | return -EINVAL; | ||
525 | |||
526 | rinfo.num_fields = report->maxfield; | ||
527 | |||
528 | if (copy_to_user(user_arg, &rinfo, sizeof(rinfo))) | ||
529 | return -EFAULT; | ||
530 | |||
531 | return 0; | ||
532 | |||
533 | case HIDIOCGFIELDINFO: | ||
534 | if (copy_from_user(&finfo, user_arg, sizeof(finfo))) | ||
535 | return -EFAULT; | ||
536 | rinfo.report_type = finfo.report_type; | ||
537 | rinfo.report_id = finfo.report_id; | ||
538 | if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) | ||
539 | return -EINVAL; | ||
540 | |||
541 | if (finfo.field_index >= report->maxfield) | ||
542 | return -EINVAL; | ||
543 | |||
544 | field = report->field[finfo.field_index]; | ||
545 | memset(&finfo, 0, sizeof(finfo)); | ||
546 | finfo.report_type = rinfo.report_type; | ||
547 | finfo.report_id = rinfo.report_id; | ||
548 | finfo.field_index = field->report_count - 1; | ||
549 | finfo.maxusage = field->maxusage; | ||
550 | finfo.flags = field->flags; | ||
551 | finfo.physical = field->physical; | ||
552 | finfo.logical = field->logical; | ||
553 | finfo.application = field->application; | ||
554 | finfo.logical_minimum = field->logical_minimum; | ||
555 | finfo.logical_maximum = field->logical_maximum; | ||
556 | finfo.physical_minimum = field->physical_minimum; | ||
557 | finfo.physical_maximum = field->physical_maximum; | ||
558 | finfo.unit_exponent = field->unit_exponent; | ||
559 | finfo.unit = field->unit; | ||
560 | |||
561 | if (copy_to_user(user_arg, &finfo, sizeof(finfo))) | ||
562 | return -EFAULT; | ||
563 | |||
564 | return 0; | ||
565 | |||
566 | case HIDIOCGUCODE: | ||
567 | uref_multi = kmalloc(sizeof(struct hiddev_usage_ref_multi), GFP_KERNEL); | ||
568 | if (!uref_multi) | ||
569 | return -ENOMEM; | ||
570 | uref = &uref_multi->uref; | ||
571 | if (copy_from_user(uref, user_arg, sizeof(*uref))) | ||
572 | goto fault; | ||
573 | |||
574 | rinfo.report_type = uref->report_type; | ||
575 | rinfo.report_id = uref->report_id; | ||
576 | if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) | ||
577 | goto inval; | ||
578 | |||
579 | if (uref->field_index >= report->maxfield) | ||
580 | goto inval; | ||
581 | |||
582 | field = report->field[uref->field_index]; | ||
583 | if (uref->usage_index >= field->maxusage) | ||
584 | goto inval; | ||
585 | |||
586 | uref->usage_code = field->usage[uref->usage_index].hid; | ||
587 | |||
588 | if (copy_to_user(user_arg, uref, sizeof(*uref))) | ||
589 | goto fault; | ||
590 | |||
591 | kfree(uref_multi); | ||
592 | return 0; | ||
593 | |||
594 | case HIDIOCGUSAGE: | ||
595 | case HIDIOCSUSAGE: | ||
596 | case HIDIOCGUSAGES: | ||
597 | case HIDIOCSUSAGES: | ||
598 | case HIDIOCGCOLLECTIONINDEX: | ||
599 | uref_multi = kmalloc(sizeof(struct hiddev_usage_ref_multi), GFP_KERNEL); | ||
600 | if (!uref_multi) | ||
601 | return -ENOMEM; | ||
602 | uref = &uref_multi->uref; | ||
603 | if (cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) { | ||
604 | if (copy_from_user(uref_multi, user_arg, | ||
605 | sizeof(*uref_multi))) | ||
606 | goto fault; | ||
607 | } else { | ||
608 | if (copy_from_user(uref, user_arg, sizeof(*uref))) | ||
609 | goto fault; | ||
610 | } | ||
611 | |||
612 | if (cmd != HIDIOCGUSAGE && | ||
613 | cmd != HIDIOCGUSAGES && | ||
614 | uref->report_type == HID_REPORT_TYPE_INPUT) | ||
615 | goto inval; | ||
616 | |||
617 | if (uref->report_id == HID_REPORT_ID_UNKNOWN) { | ||
618 | field = hiddev_lookup_usage(hid, uref); | ||
619 | if (field == NULL) | ||
620 | goto inval; | ||
621 | } else { | ||
622 | rinfo.report_type = uref->report_type; | ||
623 | rinfo.report_id = uref->report_id; | ||
624 | if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) | ||
625 | goto inval; | ||
626 | |||
627 | if (uref->field_index >= report->maxfield) | ||
628 | goto inval; | ||
629 | |||
630 | field = report->field[uref->field_index]; | ||
631 | |||
632 | if (cmd == HIDIOCGCOLLECTIONINDEX) { | ||
633 | if (uref->usage_index >= field->maxusage) | ||
634 | goto inval; | ||
635 | } else if (uref->usage_index >= field->report_count) | ||
636 | goto inval; | ||
637 | |||
638 | else if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) && | ||
639 | (uref_multi->num_values > HID_MAX_MULTI_USAGES || | ||
640 | uref->usage_index + uref_multi->num_values > field->report_count)) | ||
641 | goto inval; | ||
642 | } | ||
643 | |||
644 | switch (cmd) { | ||
645 | case HIDIOCGUSAGE: | ||
646 | uref->value = field->value[uref->usage_index]; | ||
647 | if (copy_to_user(user_arg, uref, sizeof(*uref))) | ||
648 | goto fault; | ||
649 | goto goodreturn; | ||
650 | |||
651 | case HIDIOCSUSAGE: | ||
652 | field->value[uref->usage_index] = uref->value; | ||
653 | goto goodreturn; | ||
654 | |||
655 | case HIDIOCGCOLLECTIONINDEX: | ||
656 | kfree(uref_multi); | ||
657 | return field->usage[uref->usage_index].collection_index; | ||
658 | case HIDIOCGUSAGES: | ||
659 | for (i = 0; i < uref_multi->num_values; i++) | ||
660 | uref_multi->values[i] = | ||
661 | field->value[uref->usage_index + i]; | ||
662 | if (copy_to_user(user_arg, uref_multi, | ||
663 | sizeof(*uref_multi))) | ||
664 | goto fault; | ||
665 | goto goodreturn; | ||
666 | case HIDIOCSUSAGES: | ||
667 | for (i = 0; i < uref_multi->num_values; i++) | ||
668 | field->value[uref->usage_index + i] = | ||
669 | uref_multi->values[i]; | ||
670 | goto goodreturn; | ||
671 | } | ||
672 | |||
673 | goodreturn: | ||
674 | kfree(uref_multi); | ||
675 | return 0; | ||
676 | fault: | ||
677 | kfree(uref_multi); | ||
678 | return -EFAULT; | ||
679 | inval: | ||
680 | kfree(uref_multi); | ||
681 | return -EINVAL; | ||
682 | |||
683 | case HIDIOCGCOLLECTIONINFO: | ||
684 | if (copy_from_user(&cinfo, user_arg, sizeof(cinfo))) | ||
685 | return -EFAULT; | ||
686 | |||
687 | if (cinfo.index >= hid->maxcollection) | ||
688 | return -EINVAL; | ||
689 | |||
690 | cinfo.type = hid->collection[cinfo.index].type; | ||
691 | cinfo.usage = hid->collection[cinfo.index].usage; | ||
692 | cinfo.level = hid->collection[cinfo.index].level; | ||
693 | |||
694 | if (copy_to_user(user_arg, &cinfo, sizeof(cinfo))) | ||
695 | return -EFAULT; | ||
696 | return 0; | ||
697 | |||
698 | default: | ||
699 | |||
700 | if (_IOC_TYPE(cmd) != 'H' || _IOC_DIR(cmd) != _IOC_READ) | ||
701 | return -EINVAL; | ||
702 | |||
703 | if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGNAME(0))) { | ||
704 | int len; | ||
705 | if (!hid->name) | ||
706 | return 0; | ||
707 | len = strlen(hid->name) + 1; | ||
708 | if (len > _IOC_SIZE(cmd)) | ||
709 | len = _IOC_SIZE(cmd); | ||
710 | return copy_to_user(user_arg, hid->name, len) ? | ||
711 | -EFAULT : len; | ||
712 | } | ||
713 | |||
714 | if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGPHYS(0))) { | ||
715 | int len; | ||
716 | if (!hid->phys) | ||
717 | return 0; | ||
718 | len = strlen(hid->phys) + 1; | ||
719 | if (len > _IOC_SIZE(cmd)) | ||
720 | len = _IOC_SIZE(cmd); | ||
721 | return copy_to_user(user_arg, hid->phys, len) ? | ||
722 | -EFAULT : len; | ||
723 | } | ||
724 | } | ||
725 | return -EINVAL; | ||
726 | } | ||
727 | |||
728 | static const struct file_operations hiddev_fops = { | ||
729 | .owner = THIS_MODULE, | ||
730 | .read = hiddev_read, | ||
731 | .write = hiddev_write, | ||
732 | .poll = hiddev_poll, | ||
733 | .open = hiddev_open, | ||
734 | .release = hiddev_release, | ||
735 | .ioctl = hiddev_ioctl, | ||
736 | .fasync = hiddev_fasync, | ||
737 | }; | ||
738 | |||
739 | static struct usb_class_driver hiddev_class = { | ||
740 | .name = "hiddev%d", | ||
741 | .fops = &hiddev_fops, | ||
742 | .minor_base = HIDDEV_MINOR_BASE, | ||
743 | }; | ||
744 | |||
745 | /* | ||
746 | * This is where hid.c calls us to connect a hid device to the hiddev driver | ||
747 | */ | ||
748 | int hiddev_connect(struct hid_device *hid) | ||
749 | { | ||
750 | struct hiddev *hiddev; | ||
751 | struct usbhid_device *usbhid = hid->driver_data; | ||
752 | int i; | ||
753 | int retval; | ||
754 | |||
755 | for (i = 0; i < hid->maxcollection; i++) | ||
756 | if (hid->collection[i].type == | ||
757 | HID_COLLECTION_APPLICATION && | ||
758 | !IS_INPUT_APPLICATION(hid->collection[i].usage)) | ||
759 | break; | ||
760 | |||
761 | if (i == hid->maxcollection && (hid->quirks & HID_QUIRK_HIDDEV) == 0) | ||
762 | return -1; | ||
763 | |||
764 | if (!(hiddev = kzalloc(sizeof(struct hiddev), GFP_KERNEL))) | ||
765 | return -1; | ||
766 | |||
767 | retval = usb_register_dev(usbhid->intf, &hiddev_class); | ||
768 | if (retval) { | ||
769 | err("Not able to get a minor for this device."); | ||
770 | kfree(hiddev); | ||
771 | return -1; | ||
772 | } | ||
773 | |||
774 | init_waitqueue_head(&hiddev->wait); | ||
775 | INIT_LIST_HEAD(&hiddev->list); | ||
776 | hiddev->hid = hid; | ||
777 | hiddev->exist = 1; | ||
778 | |||
779 | hid->minor = usbhid->intf->minor; | ||
780 | hid->hiddev = hiddev; | ||
781 | |||
782 | hiddev_table[usbhid->intf->minor - HIDDEV_MINOR_BASE] = hiddev; | ||
783 | |||
784 | return 0; | ||
785 | } | ||
786 | |||
787 | /* | ||
788 | * This is where hid.c calls us to disconnect a hiddev device from the | ||
789 | * corresponding hid device (usually because the usb device has disconnected) | ||
790 | */ | ||
791 | static struct usb_class_driver hiddev_class; | ||
792 | void hiddev_disconnect(struct hid_device *hid) | ||
793 | { | ||
794 | struct hiddev *hiddev = hid->hiddev; | ||
795 | struct usbhid_device *usbhid = hid->driver_data; | ||
796 | |||
797 | hiddev->exist = 0; | ||
798 | |||
799 | hiddev_table[hiddev->hid->minor - HIDDEV_MINOR_BASE] = NULL; | ||
800 | usb_deregister_dev(usbhid->intf, &hiddev_class); | ||
801 | |||
802 | if (hiddev->open) { | ||
803 | usbhid_close(hiddev->hid); | ||
804 | wake_up_interruptible(&hiddev->wait); | ||
805 | } else { | ||
806 | kfree(hiddev); | ||
807 | } | ||
808 | } | ||
809 | |||
810 | /* Currently this driver is a USB driver. It's not a conventional one in | ||
811 | * the sense that it doesn't probe at the USB level. Instead it waits to | ||
812 | * be connected by HID through the hiddev_connect / hiddev_disconnect | ||
813 | * routines. The reason to register as a USB device is to gain part of the | ||
814 | * minor number space from the USB major. | ||
815 | * | ||
816 | * In theory, should the HID code be generalized to more than one physical | ||
817 | * medium (say, IEEE 1384), this driver will probably need to register its | ||
818 | * own major number, and in doing so, no longer need to register with USB. | ||
819 | * At that point the probe routine and hiddev_driver struct below will no | ||
820 | * longer be useful. | ||
821 | */ | ||
822 | |||
823 | |||
824 | /* We never attach in this manner, and rely on HID to connect us. This | ||
825 | * is why there is no disconnect routine defined in the usb_driver either. | ||
826 | */ | ||
827 | static int hiddev_usbd_probe(struct usb_interface *intf, | ||
828 | const struct usb_device_id *hiddev_info) | ||
829 | { | ||
830 | return -ENODEV; | ||
831 | } | ||
832 | |||
833 | |||
834 | static /* const */ struct usb_driver hiddev_driver = { | ||
835 | .name = "hiddev", | ||
836 | .probe = hiddev_usbd_probe, | ||
837 | }; | ||
838 | |||
839 | int __init hiddev_init(void) | ||
840 | { | ||
841 | return usb_register(&hiddev_driver); | ||
842 | } | ||
843 | |||
844 | void hiddev_exit(void) | ||
845 | { | ||
846 | usb_deregister(&hiddev_driver); | ||
847 | } | ||
diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h new file mode 100644 index 000000000000..0023f96d4294 --- /dev/null +++ b/drivers/hid/usbhid/usbhid.h | |||
@@ -0,0 +1,87 @@ | |||
1 | #ifndef __USBHID_H | ||
2 | #define __USBHID_H | ||
3 | |||
4 | /* | ||
5 | * Copyright (c) 1999 Andreas Gal | ||
6 | * Copyright (c) 2000-2001 Vojtech Pavlik | ||
7 | * Copyright (c) 2006 Jiri Kosina | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License | ||
22 | * along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
24 | * | ||
25 | */ | ||
26 | |||
27 | #include <linux/types.h> | ||
28 | #include <linux/slab.h> | ||
29 | #include <linux/list.h> | ||
30 | #include <linux/timer.h> | ||
31 | #include <linux/workqueue.h> | ||
32 | #include <linux/input.h> | ||
33 | |||
34 | /* API provided by hid-core.c for USB HID drivers */ | ||
35 | int usbhid_wait_io(struct hid_device* hid); | ||
36 | void usbhid_close(struct hid_device *hid); | ||
37 | int usbhid_open(struct hid_device *hid); | ||
38 | void usbhid_init_reports(struct hid_device *hid); | ||
39 | void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir); | ||
40 | |||
41 | /* | ||
42 | * USB-specific HID struct, to be pointed to | ||
43 | * from struct hid_device->driver_data | ||
44 | */ | ||
45 | |||
46 | struct usbhid_device { | ||
47 | struct hid_device *hid; /* pointer to corresponding HID dev */ | ||
48 | |||
49 | struct usb_interface *intf; /* USB interface */ | ||
50 | int ifnum; /* USB interface number */ | ||
51 | |||
52 | unsigned int bufsize; /* URB buffer size */ | ||
53 | |||
54 | struct urb *urbin; /* Input URB */ | ||
55 | char *inbuf; /* Input buffer */ | ||
56 | dma_addr_t inbuf_dma; /* Input buffer dma */ | ||
57 | spinlock_t inlock; /* Input fifo spinlock */ | ||
58 | |||
59 | struct urb *urbctrl; /* Control URB */ | ||
60 | struct usb_ctrlrequest *cr; /* Control request struct */ | ||
61 | dma_addr_t cr_dma; /* Control request struct dma */ | ||
62 | struct hid_control_fifo ctrl[HID_CONTROL_FIFO_SIZE]; /* Control fifo */ | ||
63 | unsigned char ctrlhead, ctrltail; /* Control fifo head & tail */ | ||
64 | char *ctrlbuf; /* Control buffer */ | ||
65 | dma_addr_t ctrlbuf_dma; /* Control buffer dma */ | ||
66 | spinlock_t ctrllock; /* Control fifo spinlock */ | ||
67 | |||
68 | struct urb *urbout; /* Output URB */ | ||
69 | struct hid_report *out[HID_CONTROL_FIFO_SIZE]; /* Output pipe fifo */ | ||
70 | unsigned char outhead, outtail; /* Output pipe fifo head & tail */ | ||
71 | char *outbuf; /* Output buffer */ | ||
72 | dma_addr_t outbuf_dma; /* Output buffer dma */ | ||
73 | spinlock_t outlock; /* Output fifo spinlock */ | ||
74 | |||
75 | unsigned long iofl; /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */ | ||
76 | struct timer_list io_retry; /* Retry timer */ | ||
77 | unsigned long stop_retry; /* Time to give up, in jiffies */ | ||
78 | unsigned int retry_delay; /* Delay length in ms */ | ||
79 | struct work_struct reset_work; /* Task context for resets */ | ||
80 | |||
81 | }; | ||
82 | |||
83 | #define hid_to_usb_dev(hid_dev) \ | ||
84 | container_of(hid_dev->dev->parent, struct usb_device, dev) | ||
85 | |||
86 | #endif | ||
87 | |||
diff --git a/drivers/hid/usbhid/usbkbd.c b/drivers/hid/usbhid/usbkbd.c new file mode 100644 index 000000000000..65aa12e8d7b3 --- /dev/null +++ b/drivers/hid/usbhid/usbkbd.c | |||
@@ -0,0 +1,367 @@ | |||
1 | /* | ||
2 | * $Id: usbkbd.c,v 1.27 2001/12/27 10:37:41 vojtech Exp $ | ||
3 | * | ||
4 | * Copyright (c) 1999-2001 Vojtech Pavlik | ||
5 | * | ||
6 | * USB HIDBP Keyboard support | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
23 | * | ||
24 | * Should you need to contact me, the author, you can do so either by | ||
25 | * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: | ||
26 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic | ||
27 | */ | ||
28 | |||
29 | #include <linux/kernel.h> | ||
30 | #include <linux/slab.h> | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/init.h> | ||
33 | #include <linux/usb/input.h> | ||
34 | #include <linux/hid.h> | ||
35 | |||
36 | /* | ||
37 | * Version Information | ||
38 | */ | ||
39 | #define DRIVER_VERSION "" | ||
40 | #define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>" | ||
41 | #define DRIVER_DESC "USB HID Boot Protocol keyboard driver" | ||
42 | #define DRIVER_LICENSE "GPL" | ||
43 | |||
44 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
45 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
46 | MODULE_LICENSE(DRIVER_LICENSE); | ||
47 | |||
48 | static unsigned char usb_kbd_keycode[256] = { | ||
49 | 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, | ||
50 | 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3, | ||
51 | 4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26, | ||
52 | 27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64, | ||
53 | 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106, | ||
54 | 105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71, | ||
55 | 72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190, | ||
56 | 191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113, | ||
57 | 115,114, 0, 0, 0,121, 0, 89, 93,124, 92, 94, 95, 0, 0, 0, | ||
58 | 122,123, 90, 91, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
59 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
60 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
61 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
62 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
63 | 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113, | ||
64 | 150,158,159,128,136,177,178,176,142,152,173,140 | ||
65 | }; | ||
66 | |||
67 | struct usb_kbd { | ||
68 | struct input_dev *dev; | ||
69 | struct usb_device *usbdev; | ||
70 | unsigned char old[8]; | ||
71 | struct urb *irq, *led; | ||
72 | unsigned char newleds; | ||
73 | char name[128]; | ||
74 | char phys[64]; | ||
75 | |||
76 | unsigned char *new; | ||
77 | struct usb_ctrlrequest *cr; | ||
78 | unsigned char *leds; | ||
79 | dma_addr_t cr_dma; | ||
80 | dma_addr_t new_dma; | ||
81 | dma_addr_t leds_dma; | ||
82 | }; | ||
83 | |||
84 | static void usb_kbd_irq(struct urb *urb) | ||
85 | { | ||
86 | struct usb_kbd *kbd = urb->context; | ||
87 | int i; | ||
88 | |||
89 | switch (urb->status) { | ||
90 | case 0: /* success */ | ||
91 | break; | ||
92 | case -ECONNRESET: /* unlink */ | ||
93 | case -ENOENT: | ||
94 | case -ESHUTDOWN: | ||
95 | return; | ||
96 | /* -EPIPE: should clear the halt */ | ||
97 | default: /* error */ | ||
98 | goto resubmit; | ||
99 | } | ||
100 | |||
101 | for (i = 0; i < 8; i++) | ||
102 | input_report_key(kbd->dev, usb_kbd_keycode[i + 224], (kbd->new[0] >> i) & 1); | ||
103 | |||
104 | for (i = 2; i < 8; i++) { | ||
105 | |||
106 | if (kbd->old[i] > 3 && memscan(kbd->new + 2, kbd->old[i], 6) == kbd->new + 8) { | ||
107 | if (usb_kbd_keycode[kbd->old[i]]) | ||
108 | input_report_key(kbd->dev, usb_kbd_keycode[kbd->old[i]], 0); | ||
109 | else | ||
110 | info("Unknown key (scancode %#x) released.", kbd->old[i]); | ||
111 | } | ||
112 | |||
113 | if (kbd->new[i] > 3 && memscan(kbd->old + 2, kbd->new[i], 6) == kbd->old + 8) { | ||
114 | if (usb_kbd_keycode[kbd->new[i]]) | ||
115 | input_report_key(kbd->dev, usb_kbd_keycode[kbd->new[i]], 1); | ||
116 | else | ||
117 | info("Unknown key (scancode %#x) pressed.", kbd->new[i]); | ||
118 | } | ||
119 | } | ||
120 | |||
121 | input_sync(kbd->dev); | ||
122 | |||
123 | memcpy(kbd->old, kbd->new, 8); | ||
124 | |||
125 | resubmit: | ||
126 | i = usb_submit_urb (urb, GFP_ATOMIC); | ||
127 | if (i) | ||
128 | err ("can't resubmit intr, %s-%s/input0, status %d", | ||
129 | kbd->usbdev->bus->bus_name, | ||
130 | kbd->usbdev->devpath, i); | ||
131 | } | ||
132 | |||
133 | static int usb_kbd_event(struct input_dev *dev, unsigned int type, | ||
134 | unsigned int code, int value) | ||
135 | { | ||
136 | struct usb_kbd *kbd = dev->private; | ||
137 | |||
138 | if (type != EV_LED) | ||
139 | return -1; | ||
140 | |||
141 | |||
142 | kbd->newleds = (!!test_bit(LED_KANA, dev->led) << 3) | (!!test_bit(LED_COMPOSE, dev->led) << 3) | | ||
143 | (!!test_bit(LED_SCROLLL, dev->led) << 2) | (!!test_bit(LED_CAPSL, dev->led) << 1) | | ||
144 | (!!test_bit(LED_NUML, dev->led)); | ||
145 | |||
146 | if (kbd->led->status == -EINPROGRESS) | ||
147 | return 0; | ||
148 | |||
149 | if (*(kbd->leds) == kbd->newleds) | ||
150 | return 0; | ||
151 | |||
152 | *(kbd->leds) = kbd->newleds; | ||
153 | kbd->led->dev = kbd->usbdev; | ||
154 | if (usb_submit_urb(kbd->led, GFP_ATOMIC)) | ||
155 | err("usb_submit_urb(leds) failed"); | ||
156 | |||
157 | return 0; | ||
158 | } | ||
159 | |||
160 | static void usb_kbd_led(struct urb *urb) | ||
161 | { | ||
162 | struct usb_kbd *kbd = urb->context; | ||
163 | |||
164 | if (urb->status) | ||
165 | warn("led urb status %d received", urb->status); | ||
166 | |||
167 | if (*(kbd->leds) == kbd->newleds) | ||
168 | return; | ||
169 | |||
170 | *(kbd->leds) = kbd->newleds; | ||
171 | kbd->led->dev = kbd->usbdev; | ||
172 | if (usb_submit_urb(kbd->led, GFP_ATOMIC)) | ||
173 | err("usb_submit_urb(leds) failed"); | ||
174 | } | ||
175 | |||
176 | static int usb_kbd_open(struct input_dev *dev) | ||
177 | { | ||
178 | struct usb_kbd *kbd = dev->private; | ||
179 | |||
180 | kbd->irq->dev = kbd->usbdev; | ||
181 | if (usb_submit_urb(kbd->irq, GFP_KERNEL)) | ||
182 | return -EIO; | ||
183 | |||
184 | return 0; | ||
185 | } | ||
186 | |||
187 | static void usb_kbd_close(struct input_dev *dev) | ||
188 | { | ||
189 | struct usb_kbd *kbd = dev->private; | ||
190 | |||
191 | usb_kill_urb(kbd->irq); | ||
192 | } | ||
193 | |||
194 | static int usb_kbd_alloc_mem(struct usb_device *dev, struct usb_kbd *kbd) | ||
195 | { | ||
196 | if (!(kbd->irq = usb_alloc_urb(0, GFP_KERNEL))) | ||
197 | return -1; | ||
198 | if (!(kbd->led = usb_alloc_urb(0, GFP_KERNEL))) | ||
199 | return -1; | ||
200 | if (!(kbd->new = usb_buffer_alloc(dev, 8, GFP_ATOMIC, &kbd->new_dma))) | ||
201 | return -1; | ||
202 | if (!(kbd->cr = usb_buffer_alloc(dev, sizeof(struct usb_ctrlrequest), GFP_ATOMIC, &kbd->cr_dma))) | ||
203 | return -1; | ||
204 | if (!(kbd->leds = usb_buffer_alloc(dev, 1, GFP_ATOMIC, &kbd->leds_dma))) | ||
205 | return -1; | ||
206 | |||
207 | return 0; | ||
208 | } | ||
209 | |||
210 | static void usb_kbd_free_mem(struct usb_device *dev, struct usb_kbd *kbd) | ||
211 | { | ||
212 | usb_free_urb(kbd->irq); | ||
213 | usb_free_urb(kbd->led); | ||
214 | if (kbd->new) | ||
215 | usb_buffer_free(dev, 8, kbd->new, kbd->new_dma); | ||
216 | if (kbd->cr) | ||
217 | usb_buffer_free(dev, sizeof(struct usb_ctrlrequest), kbd->cr, kbd->cr_dma); | ||
218 | if (kbd->leds) | ||
219 | usb_buffer_free(dev, 1, kbd->leds, kbd->leds_dma); | ||
220 | } | ||
221 | |||
222 | static int usb_kbd_probe(struct usb_interface *iface, | ||
223 | const struct usb_device_id *id) | ||
224 | { | ||
225 | struct usb_device *dev = interface_to_usbdev(iface); | ||
226 | struct usb_host_interface *interface; | ||
227 | struct usb_endpoint_descriptor *endpoint; | ||
228 | struct usb_kbd *kbd; | ||
229 | struct input_dev *input_dev; | ||
230 | int i, pipe, maxp; | ||
231 | int error = -ENOMEM; | ||
232 | |||
233 | interface = iface->cur_altsetting; | ||
234 | |||
235 | if (interface->desc.bNumEndpoints != 1) | ||
236 | return -ENODEV; | ||
237 | |||
238 | endpoint = &interface->endpoint[0].desc; | ||
239 | if (!usb_endpoint_is_int_in(endpoint)) | ||
240 | return -ENODEV; | ||
241 | |||
242 | pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); | ||
243 | maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); | ||
244 | |||
245 | kbd = kzalloc(sizeof(struct usb_kbd), GFP_KERNEL); | ||
246 | input_dev = input_allocate_device(); | ||
247 | if (!kbd || !input_dev) | ||
248 | goto fail1; | ||
249 | |||
250 | if (usb_kbd_alloc_mem(dev, kbd)) | ||
251 | goto fail2; | ||
252 | |||
253 | kbd->usbdev = dev; | ||
254 | kbd->dev = input_dev; | ||
255 | |||
256 | if (dev->manufacturer) | ||
257 | strlcpy(kbd->name, dev->manufacturer, sizeof(kbd->name)); | ||
258 | |||
259 | if (dev->product) { | ||
260 | if (dev->manufacturer) | ||
261 | strlcat(kbd->name, " ", sizeof(kbd->name)); | ||
262 | strlcat(kbd->name, dev->product, sizeof(kbd->name)); | ||
263 | } | ||
264 | |||
265 | if (!strlen(kbd->name)) | ||
266 | snprintf(kbd->name, sizeof(kbd->name), | ||
267 | "USB HIDBP Keyboard %04x:%04x", | ||
268 | le16_to_cpu(dev->descriptor.idVendor), | ||
269 | le16_to_cpu(dev->descriptor.idProduct)); | ||
270 | |||
271 | usb_make_path(dev, kbd->phys, sizeof(kbd->phys)); | ||
272 | strlcpy(kbd->phys, "/input0", sizeof(kbd->phys)); | ||
273 | |||
274 | input_dev->name = kbd->name; | ||
275 | input_dev->phys = kbd->phys; | ||
276 | usb_to_input_id(dev, &input_dev->id); | ||
277 | input_dev->cdev.dev = &iface->dev; | ||
278 | input_dev->private = kbd; | ||
279 | |||
280 | input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP); | ||
281 | input_dev->ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL) | BIT(LED_COMPOSE) | BIT(LED_KANA); | ||
282 | |||
283 | for (i = 0; i < 255; i++) | ||
284 | set_bit(usb_kbd_keycode[i], input_dev->keybit); | ||
285 | clear_bit(0, input_dev->keybit); | ||
286 | |||
287 | input_dev->event = usb_kbd_event; | ||
288 | input_dev->open = usb_kbd_open; | ||
289 | input_dev->close = usb_kbd_close; | ||
290 | |||
291 | usb_fill_int_urb(kbd->irq, dev, pipe, | ||
292 | kbd->new, (maxp > 8 ? 8 : maxp), | ||
293 | usb_kbd_irq, kbd, endpoint->bInterval); | ||
294 | kbd->irq->transfer_dma = kbd->new_dma; | ||
295 | kbd->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
296 | |||
297 | kbd->cr->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE; | ||
298 | kbd->cr->bRequest = 0x09; | ||
299 | kbd->cr->wValue = cpu_to_le16(0x200); | ||
300 | kbd->cr->wIndex = cpu_to_le16(interface->desc.bInterfaceNumber); | ||
301 | kbd->cr->wLength = cpu_to_le16(1); | ||
302 | |||
303 | usb_fill_control_urb(kbd->led, dev, usb_sndctrlpipe(dev, 0), | ||
304 | (void *) kbd->cr, kbd->leds, 1, | ||
305 | usb_kbd_led, kbd); | ||
306 | kbd->led->setup_dma = kbd->cr_dma; | ||
307 | kbd->led->transfer_dma = kbd->leds_dma; | ||
308 | kbd->led->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP); | ||
309 | |||
310 | error = input_register_device(kbd->dev); | ||
311 | if (error) | ||
312 | goto fail2; | ||
313 | |||
314 | usb_set_intfdata(iface, kbd); | ||
315 | return 0; | ||
316 | |||
317 | fail2: | ||
318 | usb_kbd_free_mem(dev, kbd); | ||
319 | fail1: | ||
320 | input_free_device(input_dev); | ||
321 | kfree(kbd); | ||
322 | return error; | ||
323 | } | ||
324 | |||
325 | static void usb_kbd_disconnect(struct usb_interface *intf) | ||
326 | { | ||
327 | struct usb_kbd *kbd = usb_get_intfdata (intf); | ||
328 | |||
329 | usb_set_intfdata(intf, NULL); | ||
330 | if (kbd) { | ||
331 | usb_kill_urb(kbd->irq); | ||
332 | input_unregister_device(kbd->dev); | ||
333 | usb_kbd_free_mem(interface_to_usbdev(intf), kbd); | ||
334 | kfree(kbd); | ||
335 | } | ||
336 | } | ||
337 | |||
338 | static struct usb_device_id usb_kbd_id_table [] = { | ||
339 | { USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT, | ||
340 | USB_INTERFACE_PROTOCOL_KEYBOARD) }, | ||
341 | { } /* Terminating entry */ | ||
342 | }; | ||
343 | |||
344 | MODULE_DEVICE_TABLE (usb, usb_kbd_id_table); | ||
345 | |||
346 | static struct usb_driver usb_kbd_driver = { | ||
347 | .name = "usbkbd", | ||
348 | .probe = usb_kbd_probe, | ||
349 | .disconnect = usb_kbd_disconnect, | ||
350 | .id_table = usb_kbd_id_table, | ||
351 | }; | ||
352 | |||
353 | static int __init usb_kbd_init(void) | ||
354 | { | ||
355 | int result = usb_register(&usb_kbd_driver); | ||
356 | if (result == 0) | ||
357 | info(DRIVER_VERSION ":" DRIVER_DESC); | ||
358 | return result; | ||
359 | } | ||
360 | |||
361 | static void __exit usb_kbd_exit(void) | ||
362 | { | ||
363 | usb_deregister(&usb_kbd_driver); | ||
364 | } | ||
365 | |||
366 | module_init(usb_kbd_init); | ||
367 | module_exit(usb_kbd_exit); | ||
diff --git a/drivers/hid/usbhid/usbmouse.c b/drivers/hid/usbhid/usbmouse.c new file mode 100644 index 000000000000..573776d865e1 --- /dev/null +++ b/drivers/hid/usbhid/usbmouse.c | |||
@@ -0,0 +1,252 @@ | |||
1 | /* | ||
2 | * $Id: usbmouse.c,v 1.15 2001/12/27 10:37:41 vojtech Exp $ | ||
3 | * | ||
4 | * Copyright (c) 1999-2001 Vojtech Pavlik | ||
5 | * | ||
6 | * USB HIDBP Mouse support | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
23 | * | ||
24 | * Should you need to contact me, the author, you can do so either by | ||
25 | * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: | ||
26 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic | ||
27 | */ | ||
28 | |||
29 | #include <linux/kernel.h> | ||
30 | #include <linux/slab.h> | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/init.h> | ||
33 | #include <linux/usb/input.h> | ||
34 | #include <linux/hid.h> | ||
35 | |||
36 | /* | ||
37 | * Version Information | ||
38 | */ | ||
39 | #define DRIVER_VERSION "v1.6" | ||
40 | #define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>" | ||
41 | #define DRIVER_DESC "USB HID Boot Protocol mouse driver" | ||
42 | #define DRIVER_LICENSE "GPL" | ||
43 | |||
44 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
45 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
46 | MODULE_LICENSE(DRIVER_LICENSE); | ||
47 | |||
48 | struct usb_mouse { | ||
49 | char name[128]; | ||
50 | char phys[64]; | ||
51 | struct usb_device *usbdev; | ||
52 | struct input_dev *dev; | ||
53 | struct urb *irq; | ||
54 | |||
55 | signed char *data; | ||
56 | dma_addr_t data_dma; | ||
57 | }; | ||
58 | |||
59 | static void usb_mouse_irq(struct urb *urb) | ||
60 | { | ||
61 | struct usb_mouse *mouse = urb->context; | ||
62 | signed char *data = mouse->data; | ||
63 | struct input_dev *dev = mouse->dev; | ||
64 | int status; | ||
65 | |||
66 | switch (urb->status) { | ||
67 | case 0: /* success */ | ||
68 | break; | ||
69 | case -ECONNRESET: /* unlink */ | ||
70 | case -ENOENT: | ||
71 | case -ESHUTDOWN: | ||
72 | return; | ||
73 | /* -EPIPE: should clear the halt */ | ||
74 | default: /* error */ | ||
75 | goto resubmit; | ||
76 | } | ||
77 | |||
78 | input_report_key(dev, BTN_LEFT, data[0] & 0x01); | ||
79 | input_report_key(dev, BTN_RIGHT, data[0] & 0x02); | ||
80 | input_report_key(dev, BTN_MIDDLE, data[0] & 0x04); | ||
81 | input_report_key(dev, BTN_SIDE, data[0] & 0x08); | ||
82 | input_report_key(dev, BTN_EXTRA, data[0] & 0x10); | ||
83 | |||
84 | input_report_rel(dev, REL_X, data[1]); | ||
85 | input_report_rel(dev, REL_Y, data[2]); | ||
86 | input_report_rel(dev, REL_WHEEL, data[3]); | ||
87 | |||
88 | input_sync(dev); | ||
89 | resubmit: | ||
90 | status = usb_submit_urb (urb, GFP_ATOMIC); | ||
91 | if (status) | ||
92 | err ("can't resubmit intr, %s-%s/input0, status %d", | ||
93 | mouse->usbdev->bus->bus_name, | ||
94 | mouse->usbdev->devpath, status); | ||
95 | } | ||
96 | |||
97 | static int usb_mouse_open(struct input_dev *dev) | ||
98 | { | ||
99 | struct usb_mouse *mouse = dev->private; | ||
100 | |||
101 | mouse->irq->dev = mouse->usbdev; | ||
102 | if (usb_submit_urb(mouse->irq, GFP_KERNEL)) | ||
103 | return -EIO; | ||
104 | |||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | static void usb_mouse_close(struct input_dev *dev) | ||
109 | { | ||
110 | struct usb_mouse *mouse = dev->private; | ||
111 | |||
112 | usb_kill_urb(mouse->irq); | ||
113 | } | ||
114 | |||
115 | static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_id *id) | ||
116 | { | ||
117 | struct usb_device *dev = interface_to_usbdev(intf); | ||
118 | struct usb_host_interface *interface; | ||
119 | struct usb_endpoint_descriptor *endpoint; | ||
120 | struct usb_mouse *mouse; | ||
121 | struct input_dev *input_dev; | ||
122 | int pipe, maxp; | ||
123 | int error = -ENOMEM; | ||
124 | |||
125 | interface = intf->cur_altsetting; | ||
126 | |||
127 | if (interface->desc.bNumEndpoints != 1) | ||
128 | return -ENODEV; | ||
129 | |||
130 | endpoint = &interface->endpoint[0].desc; | ||
131 | if (!usb_endpoint_is_int_in(endpoint)) | ||
132 | return -ENODEV; | ||
133 | |||
134 | pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); | ||
135 | maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); | ||
136 | |||
137 | mouse = kzalloc(sizeof(struct usb_mouse), GFP_KERNEL); | ||
138 | input_dev = input_allocate_device(); | ||
139 | if (!mouse || !input_dev) | ||
140 | goto fail1; | ||
141 | |||
142 | mouse->data = usb_buffer_alloc(dev, 8, GFP_ATOMIC, &mouse->data_dma); | ||
143 | if (!mouse->data) | ||
144 | goto fail1; | ||
145 | |||
146 | mouse->irq = usb_alloc_urb(0, GFP_KERNEL); | ||
147 | if (!mouse->irq) | ||
148 | goto fail2; | ||
149 | |||
150 | mouse->usbdev = dev; | ||
151 | mouse->dev = input_dev; | ||
152 | |||
153 | if (dev->manufacturer) | ||
154 | strlcpy(mouse->name, dev->manufacturer, sizeof(mouse->name)); | ||
155 | |||
156 | if (dev->product) { | ||
157 | if (dev->manufacturer) | ||
158 | strlcat(mouse->name, " ", sizeof(mouse->name)); | ||
159 | strlcat(mouse->name, dev->product, sizeof(mouse->name)); | ||
160 | } | ||
161 | |||
162 | if (!strlen(mouse->name)) | ||
163 | snprintf(mouse->name, sizeof(mouse->name), | ||
164 | "USB HIDBP Mouse %04x:%04x", | ||
165 | le16_to_cpu(dev->descriptor.idVendor), | ||
166 | le16_to_cpu(dev->descriptor.idProduct)); | ||
167 | |||
168 | usb_make_path(dev, mouse->phys, sizeof(mouse->phys)); | ||
169 | strlcat(mouse->phys, "/input0", sizeof(mouse->phys)); | ||
170 | |||
171 | input_dev->name = mouse->name; | ||
172 | input_dev->phys = mouse->phys; | ||
173 | usb_to_input_id(dev, &input_dev->id); | ||
174 | input_dev->cdev.dev = &intf->dev; | ||
175 | |||
176 | input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL); | ||
177 | input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); | ||
178 | input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y); | ||
179 | input_dev->keybit[LONG(BTN_MOUSE)] |= BIT(BTN_SIDE) | BIT(BTN_EXTRA); | ||
180 | input_dev->relbit[0] |= BIT(REL_WHEEL); | ||
181 | |||
182 | input_dev->private = mouse; | ||
183 | input_dev->open = usb_mouse_open; | ||
184 | input_dev->close = usb_mouse_close; | ||
185 | |||
186 | usb_fill_int_urb(mouse->irq, dev, pipe, mouse->data, | ||
187 | (maxp > 8 ? 8 : maxp), | ||
188 | usb_mouse_irq, mouse, endpoint->bInterval); | ||
189 | mouse->irq->transfer_dma = mouse->data_dma; | ||
190 | mouse->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
191 | |||
192 | error = input_register_device(mouse->dev); | ||
193 | if (error) | ||
194 | goto fail3; | ||
195 | |||
196 | usb_set_intfdata(intf, mouse); | ||
197 | return 0; | ||
198 | |||
199 | fail3: | ||
200 | usb_free_urb(mouse->irq); | ||
201 | fail2: | ||
202 | usb_buffer_free(dev, 8, mouse->data, mouse->data_dma); | ||
203 | fail1: | ||
204 | input_free_device(input_dev); | ||
205 | kfree(mouse); | ||
206 | return error; | ||
207 | } | ||
208 | |||
209 | static void usb_mouse_disconnect(struct usb_interface *intf) | ||
210 | { | ||
211 | struct usb_mouse *mouse = usb_get_intfdata (intf); | ||
212 | |||
213 | usb_set_intfdata(intf, NULL); | ||
214 | if (mouse) { | ||
215 | usb_kill_urb(mouse->irq); | ||
216 | input_unregister_device(mouse->dev); | ||
217 | usb_free_urb(mouse->irq); | ||
218 | usb_buffer_free(interface_to_usbdev(intf), 8, mouse->data, mouse->data_dma); | ||
219 | kfree(mouse); | ||
220 | } | ||
221 | } | ||
222 | |||
223 | static struct usb_device_id usb_mouse_id_table [] = { | ||
224 | { USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT, | ||
225 | USB_INTERFACE_PROTOCOL_MOUSE) }, | ||
226 | { } /* Terminating entry */ | ||
227 | }; | ||
228 | |||
229 | MODULE_DEVICE_TABLE (usb, usb_mouse_id_table); | ||
230 | |||
231 | static struct usb_driver usb_mouse_driver = { | ||
232 | .name = "usbmouse", | ||
233 | .probe = usb_mouse_probe, | ||
234 | .disconnect = usb_mouse_disconnect, | ||
235 | .id_table = usb_mouse_id_table, | ||
236 | }; | ||
237 | |||
238 | static int __init usb_mouse_init(void) | ||
239 | { | ||
240 | int retval = usb_register(&usb_mouse_driver); | ||
241 | if (retval == 0) | ||
242 | info(DRIVER_VERSION ":" DRIVER_DESC); | ||
243 | return retval; | ||
244 | } | ||
245 | |||
246 | static void __exit usb_mouse_exit(void) | ||
247 | { | ||
248 | usb_deregister(&usb_mouse_driver); | ||
249 | } | ||
250 | |||
251 | module_init(usb_mouse_init); | ||
252 | module_exit(usb_mouse_exit); | ||