diff options
Diffstat (limited to 'drivers/hid')
-rw-r--r-- | drivers/hid/Kconfig | 70 | ||||
-rw-r--r-- | drivers/hid/Makefile | 5 | ||||
-rw-r--r-- | drivers/hid/hid-bright.c | 71 | ||||
-rw-r--r-- | drivers/hid/hid-core.c | 120 | ||||
-rw-r--r-- | drivers/hid/hid-dell.c | 76 | ||||
-rw-r--r-- | drivers/hid/hid-dummy.c | 6 | ||||
-rw-r--r-- | drivers/hid/hid-gaff.c | 185 | ||||
-rw-r--r-- | drivers/hid/hid-ids.h | 21 | ||||
-rw-r--r-- | drivers/hid/hid-lg.c | 7 | ||||
-rw-r--r-- | drivers/hid/hid-ntrig.c | 82 | ||||
-rw-r--r-- | drivers/hid/hid-sony.c | 2 | ||||
-rw-r--r-- | drivers/hid/hid-topseed.c | 77 | ||||
-rw-r--r-- | drivers/hid/hidraw.c | 32 | ||||
-rw-r--r-- | drivers/hid/usbhid/Kconfig | 2 | ||||
-rw-r--r-- | drivers/hid/usbhid/hid-core.c | 34 | ||||
-rw-r--r-- | drivers/hid/usbhid/hid-quirks.c | 1 | ||||
-rw-r--r-- | drivers/hid/usbhid/hiddev.c | 135 | ||||
-rw-r--r-- | drivers/hid/usbhid/usbhid.h | 10 |
18 files changed, 676 insertions, 260 deletions
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index b4fd8ca701a4..e85c8fe9ffcf 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig | |||
@@ -85,14 +85,14 @@ config HID_COMPAT | |||
85 | config HID_A4TECH | 85 | config HID_A4TECH |
86 | tristate "A4 tech" if EMBEDDED | 86 | tristate "A4 tech" if EMBEDDED |
87 | depends on USB_HID | 87 | depends on USB_HID |
88 | default y | 88 | default !EMBEDDED |
89 | ---help--- | 89 | ---help--- |
90 | Support for A4 tech X5 and WOP-35 / Trust 450L mice. | 90 | Support for A4 tech X5 and WOP-35 / Trust 450L mice. |
91 | 91 | ||
92 | config HID_APPLE | 92 | config HID_APPLE |
93 | tristate "Apple" if EMBEDDED | 93 | tristate "Apple" if EMBEDDED |
94 | depends on (USB_HID || BT_HIDP) | 94 | depends on (USB_HID || BT_HIDP) |
95 | default y | 95 | default !EMBEDDED |
96 | ---help--- | 96 | ---help--- |
97 | Support for some Apple devices which less or more break | 97 | Support for some Apple devices which less or more break |
98 | HID specification. | 98 | HID specification. |
@@ -103,64 +103,49 @@ config HID_APPLE | |||
103 | config HID_BELKIN | 103 | config HID_BELKIN |
104 | tristate "Belkin" if EMBEDDED | 104 | tristate "Belkin" if EMBEDDED |
105 | depends on USB_HID | 105 | depends on USB_HID |
106 | default y | 106 | default !EMBEDDED |
107 | ---help--- | 107 | ---help--- |
108 | Support for Belkin Flip KVM and Wireless keyboard. | 108 | Support for Belkin Flip KVM and Wireless keyboard. |
109 | 109 | ||
110 | config HID_BRIGHT | ||
111 | tristate "Bright" if EMBEDDED | ||
112 | depends on USB_HID | ||
113 | default y | ||
114 | ---help--- | ||
115 | Support for Bright ABNT-2 keyboard. | ||
116 | |||
117 | config HID_CHERRY | 110 | config HID_CHERRY |
118 | tristate "Cherry" if EMBEDDED | 111 | tristate "Cherry" if EMBEDDED |
119 | depends on USB_HID | 112 | depends on USB_HID |
120 | default y | 113 | default !EMBEDDED |
121 | ---help--- | 114 | ---help--- |
122 | Support for Cherry Cymotion keyboard. | 115 | Support for Cherry Cymotion keyboard. |
123 | 116 | ||
124 | config HID_CHICONY | 117 | config HID_CHICONY |
125 | tristate "Chicony" if EMBEDDED | 118 | tristate "Chicony" if EMBEDDED |
126 | depends on USB_HID | 119 | depends on USB_HID |
127 | default y | 120 | default !EMBEDDED |
128 | ---help--- | 121 | ---help--- |
129 | Support for Chicony Tactical pad. | 122 | Support for Chicony Tactical pad. |
130 | 123 | ||
131 | config HID_CYPRESS | 124 | config HID_CYPRESS |
132 | tristate "Cypress" if EMBEDDED | 125 | tristate "Cypress" if EMBEDDED |
133 | depends on USB_HID | 126 | depends on USB_HID |
134 | default y | 127 | default !EMBEDDED |
135 | ---help--- | 128 | ---help--- |
136 | Support for cypress mouse and barcode readers. | 129 | Support for cypress mouse and barcode readers. |
137 | 130 | ||
138 | config HID_DELL | ||
139 | tristate "Dell" if EMBEDDED | ||
140 | depends on USB_HID | ||
141 | default y | ||
142 | ---help--- | ||
143 | Support for quirky Dell HID hardware that require | ||
144 | special LED handling (W7658 and SK8115 models) | ||
145 | |||
146 | config HID_EZKEY | 131 | config HID_EZKEY |
147 | tristate "Ezkey" if EMBEDDED | 132 | tristate "Ezkey" if EMBEDDED |
148 | depends on USB_HID | 133 | depends on USB_HID |
149 | default y | 134 | default !EMBEDDED |
150 | ---help--- | 135 | ---help--- |
151 | Support for Ezkey BTC 8193 keyboard. | 136 | Support for Ezkey BTC 8193 keyboard. |
152 | 137 | ||
153 | config HID_GYRATION | 138 | config HID_GYRATION |
154 | tristate "Gyration" if EMBEDDED | 139 | tristate "Gyration" if EMBEDDED |
155 | depends on USB_HID | 140 | depends on USB_HID |
156 | default y | 141 | default !EMBEDDED |
157 | ---help--- | 142 | ---help--- |
158 | Support for Gyration remote control. | 143 | Support for Gyration remote control. |
159 | 144 | ||
160 | config HID_LOGITECH | 145 | config HID_LOGITECH |
161 | tristate "Logitech" if EMBEDDED | 146 | tristate "Logitech" if EMBEDDED |
162 | depends on USB_HID | 147 | depends on USB_HID |
163 | default y | 148 | default !EMBEDDED |
164 | ---help--- | 149 | ---help--- |
165 | Support for Logitech devices that are not fully compliant with HID standard. | 150 | Support for Logitech devices that are not fully compliant with HID standard. |
166 | 151 | ||
@@ -191,21 +176,28 @@ config LOGIRUMBLEPAD2_FF | |||
191 | config HID_MICROSOFT | 176 | config HID_MICROSOFT |
192 | tristate "Microsoft" if EMBEDDED | 177 | tristate "Microsoft" if EMBEDDED |
193 | depends on USB_HID | 178 | depends on USB_HID |
194 | default y | 179 | default !EMBEDDED |
195 | ---help--- | 180 | ---help--- |
196 | Support for Microsoft devices that are not fully compliant with HID standard. | 181 | Support for Microsoft devices that are not fully compliant with HID standard. |
197 | 182 | ||
198 | config HID_MONTEREY | 183 | config HID_MONTEREY |
199 | tristate "Monterey" if EMBEDDED | 184 | tristate "Monterey" if EMBEDDED |
200 | depends on USB_HID | 185 | depends on USB_HID |
201 | default y | 186 | default !EMBEDDED |
202 | ---help--- | 187 | ---help--- |
203 | Support for Monterey Genius KB29E. | 188 | Support for Monterey Genius KB29E. |
204 | 189 | ||
190 | config HID_NTRIG | ||
191 | tristate "NTrig" if EMBEDDED | ||
192 | depends on USB_HID | ||
193 | default !EMBEDDED | ||
194 | ---help--- | ||
195 | Support for N-Trig touch screen. | ||
196 | |||
205 | config HID_PANTHERLORD | 197 | config HID_PANTHERLORD |
206 | tristate "Pantherlord devices support" if EMBEDDED | 198 | tristate "Pantherlord devices support" if EMBEDDED |
207 | depends on USB_HID | 199 | depends on USB_HID |
208 | default y | 200 | default !EMBEDDED |
209 | ---help--- | 201 | ---help--- |
210 | Support for PantherLord/GreenAsia based device support. | 202 | Support for PantherLord/GreenAsia based device support. |
211 | 203 | ||
@@ -220,31 +212,47 @@ config PANTHERLORD_FF | |||
220 | config HID_PETALYNX | 212 | config HID_PETALYNX |
221 | tristate "Petalynx" if EMBEDDED | 213 | tristate "Petalynx" if EMBEDDED |
222 | depends on USB_HID | 214 | depends on USB_HID |
223 | default y | 215 | default !EMBEDDED |
224 | ---help--- | 216 | ---help--- |
225 | Support for Petalynx Maxter remote control. | 217 | Support for Petalynx Maxter remote control. |
226 | 218 | ||
227 | config HID_SAMSUNG | 219 | config HID_SAMSUNG |
228 | tristate "Samsung" if EMBEDDED | 220 | tristate "Samsung" if EMBEDDED |
229 | depends on USB_HID | 221 | depends on USB_HID |
230 | default y | 222 | default !EMBEDDED |
231 | ---help--- | 223 | ---help--- |
232 | Support for Samsung InfraRed remote control. | 224 | Support for Samsung InfraRed remote control. |
233 | 225 | ||
234 | config HID_SONY | 226 | config HID_SONY |
235 | tristate "Sony" if EMBEDDED | 227 | tristate "Sony" if EMBEDDED |
236 | depends on USB_HID | 228 | depends on USB_HID |
237 | default y | 229 | default !EMBEDDED |
238 | ---help--- | 230 | ---help--- |
239 | Support for Sony PS3 controller. | 231 | Support for Sony PS3 controller. |
240 | 232 | ||
241 | config HID_SUNPLUS | 233 | config HID_SUNPLUS |
242 | tristate "Sunplus" if EMBEDDED | 234 | tristate "Sunplus" if EMBEDDED |
243 | depends on USB_HID | 235 | depends on USB_HID |
244 | default y | 236 | default !EMBEDDED |
245 | ---help--- | 237 | ---help--- |
246 | Support for Sunplus wireless desktop. | 238 | Support for Sunplus wireless desktop. |
247 | 239 | ||
240 | config GREENASIA_FF | ||
241 | tristate "GreenAsia (Product ID 0x12) force feedback support" | ||
242 | depends on USB_HID | ||
243 | select INPUT_FF_MEMLESS | ||
244 | ---help--- | ||
245 | Say Y here if you have a GreenAsia (Product ID 0x12) based game controller | ||
246 | (like MANTA Warior MM816 and SpeedLink Strike2 SL-6635) or adapter | ||
247 | and want to enable force feedback support for it. | ||
248 | |||
249 | config HID_TOPSEED | ||
250 | tristate "TopSeed Cyberlink remote control support" if EMBEDDED | ||
251 | depends on USB_HID | ||
252 | default !EMBEDDED | ||
253 | ---help--- | ||
254 | Say Y if you have a TopSeed Cyberlink remote control. | ||
255 | |||
248 | config THRUSTMASTER_FF | 256 | config THRUSTMASTER_FF |
249 | tristate "ThrustMaster devices support" | 257 | tristate "ThrustMaster devices support" |
250 | depends on USB_HID | 258 | depends on USB_HID |
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index b09e43e7413e..fbd021f153f1 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile | |||
@@ -23,22 +23,23 @@ endif | |||
23 | obj-$(CONFIG_HID_A4TECH) += hid-a4tech.o | 23 | obj-$(CONFIG_HID_A4TECH) += hid-a4tech.o |
24 | obj-$(CONFIG_HID_APPLE) += hid-apple.o | 24 | obj-$(CONFIG_HID_APPLE) += hid-apple.o |
25 | obj-$(CONFIG_HID_BELKIN) += hid-belkin.o | 25 | obj-$(CONFIG_HID_BELKIN) += hid-belkin.o |
26 | obj-$(CONFIG_HID_BRIGHT) += hid-bright.o | ||
27 | obj-$(CONFIG_HID_CHERRY) += hid-cherry.o | 26 | obj-$(CONFIG_HID_CHERRY) += hid-cherry.o |
28 | obj-$(CONFIG_HID_CHICONY) += hid-chicony.o | 27 | obj-$(CONFIG_HID_CHICONY) += hid-chicony.o |
29 | obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o | 28 | obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o |
30 | obj-$(CONFIG_HID_DELL) += hid-dell.o | ||
31 | obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o | 29 | obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o |
32 | obj-$(CONFIG_HID_GYRATION) += hid-gyration.o | 30 | obj-$(CONFIG_HID_GYRATION) += hid-gyration.o |
33 | obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o | 31 | obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o |
34 | obj-$(CONFIG_HID_MICROSOFT) += hid-microsoft.o | 32 | obj-$(CONFIG_HID_MICROSOFT) += hid-microsoft.o |
35 | obj-$(CONFIG_HID_MONTEREY) += hid-monterey.o | 33 | obj-$(CONFIG_HID_MONTEREY) += hid-monterey.o |
34 | obj-$(CONFIG_HID_NTRIG) += hid-ntrig.o | ||
36 | obj-$(CONFIG_HID_PANTHERLORD) += hid-pl.o | 35 | obj-$(CONFIG_HID_PANTHERLORD) += hid-pl.o |
37 | obj-$(CONFIG_HID_PETALYNX) += hid-petalynx.o | 36 | obj-$(CONFIG_HID_PETALYNX) += hid-petalynx.o |
38 | obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o | 37 | obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o |
39 | obj-$(CONFIG_HID_SONY) += hid-sony.o | 38 | obj-$(CONFIG_HID_SONY) += hid-sony.o |
40 | obj-$(CONFIG_HID_SUNPLUS) += hid-sunplus.o | 39 | obj-$(CONFIG_HID_SUNPLUS) += hid-sunplus.o |
40 | obj-$(CONFIG_GREENASIA_FF) += hid-gaff.o | ||
41 | obj-$(CONFIG_THRUSTMASTER_FF) += hid-tmff.o | 41 | obj-$(CONFIG_THRUSTMASTER_FF) += hid-tmff.o |
42 | obj-$(CONFIG_HID_TOPSEED) += hid-topseed.o | ||
42 | obj-$(CONFIG_ZEROPLUS_FF) += hid-zpff.o | 43 | obj-$(CONFIG_ZEROPLUS_FF) += hid-zpff.o |
43 | 44 | ||
44 | obj-$(CONFIG_USB_HID) += usbhid/ | 45 | obj-$(CONFIG_USB_HID) += usbhid/ |
diff --git a/drivers/hid/hid-bright.c b/drivers/hid/hid-bright.c deleted file mode 100644 index 38517a117dfd..000000000000 --- a/drivers/hid/hid-bright.c +++ /dev/null | |||
@@ -1,71 +0,0 @@ | |||
1 | /* | ||
2 | * HID driver for some bright "special" devices | ||
3 | * | ||
4 | * Copyright (c) 2008 Mauro Carvalho Chehab <mchehab@redhat.com> | ||
5 | * | ||
6 | * Based on hid-dell driver | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the Free | ||
12 | * Software Foundation; either version 2 of the License, or (at your option) | ||
13 | * any later version. | ||
14 | */ | ||
15 | |||
16 | #include <linux/device.h> | ||
17 | #include <linux/hid.h> | ||
18 | #include <linux/module.h> | ||
19 | |||
20 | #include "hid-ids.h" | ||
21 | |||
22 | static int bright_probe(struct hid_device *hdev, const struct hid_device_id *id) | ||
23 | { | ||
24 | int ret; | ||
25 | |||
26 | ret = hid_parse(hdev); | ||
27 | if (ret) { | ||
28 | dev_err(&hdev->dev, "parse failed\n"); | ||
29 | goto err_free; | ||
30 | } | ||
31 | |||
32 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); | ||
33 | if (ret) { | ||
34 | dev_err(&hdev->dev, "hw start failed\n"); | ||
35 | goto err_free; | ||
36 | } | ||
37 | |||
38 | usbhid_set_leds(hdev); | ||
39 | |||
40 | return 0; | ||
41 | err_free: | ||
42 | return ret; | ||
43 | } | ||
44 | |||
45 | static const struct hid_device_id bright_devices[] = { | ||
46 | { HID_USB_DEVICE(USB_VENDOR_ID_BRIGHT, USB_DEVICE_ID_BRIGHT_ABNT2) }, | ||
47 | { } | ||
48 | }; | ||
49 | MODULE_DEVICE_TABLE(hid, bright_devices); | ||
50 | |||
51 | static struct hid_driver bright_driver = { | ||
52 | .name = "bright", | ||
53 | .id_table = bright_devices, | ||
54 | .probe = bright_probe, | ||
55 | }; | ||
56 | |||
57 | static int bright_init(void) | ||
58 | { | ||
59 | return hid_register_driver(&bright_driver); | ||
60 | } | ||
61 | |||
62 | static void bright_exit(void) | ||
63 | { | ||
64 | hid_unregister_driver(&bright_driver); | ||
65 | } | ||
66 | |||
67 | module_init(bright_init); | ||
68 | module_exit(bright_exit); | ||
69 | MODULE_LICENSE("GPL"); | ||
70 | |||
71 | HID_COMPAT_LOAD_DRIVER(bright); | ||
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 40df3e1b4bd1..5d7640e49dc5 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
@@ -1256,19 +1256,16 @@ static const struct hid_device_id hid_blacklist[] = { | |||
1256 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, | 1256 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, |
1257 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, | 1257 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, |
1258 | { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) }, | 1258 | { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) }, |
1259 | { HID_USB_DEVICE(USB_VENDOR_ID_BRIGHT, USB_DEVICE_ID_BRIGHT_ABNT2) }, | ||
1260 | { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) }, | 1259 | { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) }, |
1261 | { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) }, | 1260 | { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) }, |
1262 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) }, | 1261 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) }, |
1263 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) }, | 1262 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) }, |
1264 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE) }, | 1263 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE) }, |
1265 | { HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658) }, | ||
1266 | { HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_SK8115) }, | ||
1267 | { HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) }, | 1264 | { HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) }, |
1268 | { HID_USB_DEVICE(USB_VENDOR_ID_GENERIC_13BA, USB_DEVICE_ID_GENERIC_13BA_KBD_MOUSE) }, | ||
1269 | { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) }, | 1265 | { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) }, |
1270 | { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR) }, | 1266 | { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR) }, |
1271 | { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003) }, | 1267 | { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003) }, |
1268 | { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0012) }, | ||
1272 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) }, | 1269 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) }, |
1273 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) }, | 1270 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) }, |
1274 | { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) }, | 1271 | { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) }, |
@@ -1279,7 +1276,6 @@ static const struct hid_device_id hid_blacklist[] = { | |||
1279 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP) }, | 1276 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP) }, |
1280 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE) }, | 1277 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE) }, |
1281 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI) }, | 1278 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI) }, |
1282 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KBD) }, | ||
1283 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD) }, | 1279 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD) }, |
1284 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500) }, | 1280 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500) }, |
1285 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D) }, | 1281 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D) }, |
@@ -1297,23 +1293,105 @@ static const struct hid_device_id hid_blacklist[] = { | |||
1297 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB) }, | 1293 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB) }, |
1298 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) }, | 1294 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) }, |
1299 | { HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) }, | 1295 | { HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) }, |
1296 | { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN) }, | ||
1300 | { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) }, | 1297 | { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) }, |
1301 | { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, | 1298 | { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, |
1302 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, | 1299 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, |
1303 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) }, | 1300 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) }, |
1304 | { HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) }, | 1301 | { HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) }, |
1302 | { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) }, | ||
1305 | 1303 | ||
1306 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, 0x030c) }, | 1304 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, 0x030c) }, |
1307 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT) }, | 1305 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT) }, |
1308 | { } | 1306 | { } |
1309 | }; | 1307 | }; |
1310 | 1308 | ||
1309 | struct hid_dynid { | ||
1310 | struct list_head list; | ||
1311 | struct hid_device_id id; | ||
1312 | }; | ||
1313 | |||
1314 | /** | ||
1315 | * store_new_id - add a new HID device ID to this driver and re-probe devices | ||
1316 | * @driver: target device driver | ||
1317 | * @buf: buffer for scanning device ID data | ||
1318 | * @count: input size | ||
1319 | * | ||
1320 | * Adds a new dynamic hid device ID to this driver, | ||
1321 | * and causes the driver to probe for all devices again. | ||
1322 | */ | ||
1323 | static ssize_t store_new_id(struct device_driver *drv, const char *buf, | ||
1324 | size_t count) | ||
1325 | { | ||
1326 | struct hid_driver *hdrv = container_of(drv, struct hid_driver, driver); | ||
1327 | struct hid_dynid *dynid; | ||
1328 | __u32 bus, vendor, product; | ||
1329 | unsigned long driver_data = 0; | ||
1330 | int ret; | ||
1331 | |||
1332 | ret = sscanf(buf, "%x %x %x %lx", | ||
1333 | &bus, &vendor, &product, &driver_data); | ||
1334 | if (ret < 3) | ||
1335 | return -EINVAL; | ||
1336 | |||
1337 | dynid = kzalloc(sizeof(*dynid), GFP_KERNEL); | ||
1338 | if (!dynid) | ||
1339 | return -ENOMEM; | ||
1340 | |||
1341 | dynid->id.bus = bus; | ||
1342 | dynid->id.vendor = vendor; | ||
1343 | dynid->id.product = product; | ||
1344 | dynid->id.driver_data = driver_data; | ||
1345 | |||
1346 | spin_lock(&hdrv->dyn_lock); | ||
1347 | list_add_tail(&dynid->list, &hdrv->dyn_list); | ||
1348 | spin_unlock(&hdrv->dyn_lock); | ||
1349 | |||
1350 | ret = 0; | ||
1351 | if (get_driver(&hdrv->driver)) { | ||
1352 | ret = driver_attach(&hdrv->driver); | ||
1353 | put_driver(&hdrv->driver); | ||
1354 | } | ||
1355 | |||
1356 | return ret ? : count; | ||
1357 | } | ||
1358 | static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id); | ||
1359 | |||
1360 | static void hid_free_dynids(struct hid_driver *hdrv) | ||
1361 | { | ||
1362 | struct hid_dynid *dynid, *n; | ||
1363 | |||
1364 | spin_lock(&hdrv->dyn_lock); | ||
1365 | list_for_each_entry_safe(dynid, n, &hdrv->dyn_list, list) { | ||
1366 | list_del(&dynid->list); | ||
1367 | kfree(dynid); | ||
1368 | } | ||
1369 | spin_unlock(&hdrv->dyn_lock); | ||
1370 | } | ||
1371 | |||
1372 | static const struct hid_device_id *hid_match_device(struct hid_device *hdev, | ||
1373 | struct hid_driver *hdrv) | ||
1374 | { | ||
1375 | struct hid_dynid *dynid; | ||
1376 | |||
1377 | spin_lock(&hdrv->dyn_lock); | ||
1378 | list_for_each_entry(dynid, &hdrv->dyn_list, list) { | ||
1379 | if (hid_match_one_id(hdev, &dynid->id)) { | ||
1380 | spin_unlock(&hdrv->dyn_lock); | ||
1381 | return &dynid->id; | ||
1382 | } | ||
1383 | } | ||
1384 | spin_unlock(&hdrv->dyn_lock); | ||
1385 | |||
1386 | return hid_match_id(hdev, hdrv->id_table); | ||
1387 | } | ||
1388 | |||
1311 | static int hid_bus_match(struct device *dev, struct device_driver *drv) | 1389 | static int hid_bus_match(struct device *dev, struct device_driver *drv) |
1312 | { | 1390 | { |
1313 | struct hid_driver *hdrv = container_of(drv, struct hid_driver, driver); | 1391 | struct hid_driver *hdrv = container_of(drv, struct hid_driver, driver); |
1314 | struct hid_device *hdev = container_of(dev, struct hid_device, dev); | 1392 | struct hid_device *hdev = container_of(dev, struct hid_device, dev); |
1315 | 1393 | ||
1316 | if (!hid_match_id(hdev, hdrv->id_table)) | 1394 | if (!hid_match_device(hdev, hdrv)) |
1317 | return 0; | 1395 | return 0; |
1318 | 1396 | ||
1319 | /* generic wants all non-blacklisted */ | 1397 | /* generic wants all non-blacklisted */ |
@@ -1332,7 +1410,7 @@ static int hid_device_probe(struct device *dev) | |||
1332 | int ret = 0; | 1410 | int ret = 0; |
1333 | 1411 | ||
1334 | if (!hdev->driver) { | 1412 | if (!hdev->driver) { |
1335 | id = hid_match_id(hdev, hdrv->id_table); | 1413 | id = hid_match_device(hdev, hdrv); |
1336 | if (id == NULL) | 1414 | if (id == NULL) |
1337 | return -ENODEV; | 1415 | return -ENODEV; |
1338 | 1416 | ||
@@ -1420,6 +1498,7 @@ static const struct hid_device_id hid_ignore_list[] = { | |||
1420 | { HID_USB_DEVICE(USB_VENDOR_ID_CMEDIA, USB_DEVICE_ID_CM109) }, | 1498 | { HID_USB_DEVICE(USB_VENDOR_ID_CMEDIA, USB_DEVICE_ID_CM109) }, |
1421 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_HIDCOM) }, | 1499 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_HIDCOM) }, |
1422 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_ULTRAMOUSE) }, | 1500 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_ULTRAMOUSE) }, |
1501 | { HID_USB_DEVICE(USB_VENDOR_ID_DEALEXTREAME, USB_DEVICE_ID_DEALEXTREAME_RADIO_SI4701) }, | ||
1423 | { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE) }, | 1502 | { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE) }, |
1424 | { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20) }, | 1503 | { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20) }, |
1425 | { HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) }, | 1504 | { HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) }, |
@@ -1577,6 +1656,9 @@ static const struct hid_device_id hid_mouse_ignore_list[] = { | |||
1577 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI) }, | 1656 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI) }, |
1578 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO) }, | 1657 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO) }, |
1579 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS) }, | 1658 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS) }, |
1659 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI) }, | ||
1660 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO) }, | ||
1661 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS) }, | ||
1580 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, | 1662 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, |
1581 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, | 1663 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, |
1582 | { } | 1664 | { } |
@@ -1618,9 +1700,10 @@ int hid_add_device(struct hid_device *hdev) | |||
1618 | if (hid_ignore(hdev)) | 1700 | if (hid_ignore(hdev)) |
1619 | return -ENODEV; | 1701 | return -ENODEV; |
1620 | 1702 | ||
1621 | /* XXX hack, any other cleaner solution < 20 bus_id bytes? */ | 1703 | /* XXX hack, any other cleaner solution after the driver core |
1622 | sprintf(hdev->dev.bus_id, "%04X:%04X:%04X.%04X", hdev->bus, | 1704 | * is converted to allow more than 20 bytes as the device name? */ |
1623 | hdev->vendor, hdev->product, atomic_inc_return(&id)); | 1705 | dev_set_name(&hdev->dev, "%04X:%04X:%04X.%04X", hdev->bus, |
1706 | hdev->vendor, hdev->product, atomic_inc_return(&id)); | ||
1624 | 1707 | ||
1625 | ret = device_add(&hdev->dev); | 1708 | ret = device_add(&hdev->dev); |
1626 | if (!ret) | 1709 | if (!ret) |
@@ -1695,18 +1778,33 @@ EXPORT_SYMBOL_GPL(hid_destroy_device); | |||
1695 | int __hid_register_driver(struct hid_driver *hdrv, struct module *owner, | 1778 | int __hid_register_driver(struct hid_driver *hdrv, struct module *owner, |
1696 | const char *mod_name) | 1779 | const char *mod_name) |
1697 | { | 1780 | { |
1781 | int ret; | ||
1782 | |||
1698 | hdrv->driver.name = hdrv->name; | 1783 | hdrv->driver.name = hdrv->name; |
1699 | hdrv->driver.bus = &hid_bus_type; | 1784 | hdrv->driver.bus = &hid_bus_type; |
1700 | hdrv->driver.owner = owner; | 1785 | hdrv->driver.owner = owner; |
1701 | hdrv->driver.mod_name = mod_name; | 1786 | hdrv->driver.mod_name = mod_name; |
1702 | 1787 | ||
1703 | return driver_register(&hdrv->driver); | 1788 | INIT_LIST_HEAD(&hdrv->dyn_list); |
1789 | spin_lock_init(&hdrv->dyn_lock); | ||
1790 | |||
1791 | ret = driver_register(&hdrv->driver); | ||
1792 | if (ret) | ||
1793 | return ret; | ||
1794 | |||
1795 | ret = driver_create_file(&hdrv->driver, &driver_attr_new_id); | ||
1796 | if (ret) | ||
1797 | driver_unregister(&hdrv->driver); | ||
1798 | |||
1799 | return ret; | ||
1704 | } | 1800 | } |
1705 | EXPORT_SYMBOL_GPL(__hid_register_driver); | 1801 | EXPORT_SYMBOL_GPL(__hid_register_driver); |
1706 | 1802 | ||
1707 | void hid_unregister_driver(struct hid_driver *hdrv) | 1803 | void hid_unregister_driver(struct hid_driver *hdrv) |
1708 | { | 1804 | { |
1805 | driver_remove_file(&hdrv->driver, &driver_attr_new_id); | ||
1709 | driver_unregister(&hdrv->driver); | 1806 | driver_unregister(&hdrv->driver); |
1807 | hid_free_dynids(hdrv); | ||
1710 | } | 1808 | } |
1711 | EXPORT_SYMBOL_GPL(hid_unregister_driver); | 1809 | EXPORT_SYMBOL_GPL(hid_unregister_driver); |
1712 | 1810 | ||
diff --git a/drivers/hid/hid-dell.c b/drivers/hid/hid-dell.c deleted file mode 100644 index f5474300b83a..000000000000 --- a/drivers/hid/hid-dell.c +++ /dev/null | |||
@@ -1,76 +0,0 @@ | |||
1 | /* | ||
2 | * HID driver for some dell "special" devices | ||
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 | * Copyright (c) 2008 Jiri Slaby | ||
10 | */ | ||
11 | |||
12 | /* | ||
13 | * This program is free software; you can redistribute it and/or modify it | ||
14 | * under the terms of the GNU General Public License as published by the Free | ||
15 | * Software Foundation; either version 2 of the License, or (at your option) | ||
16 | * any later version. | ||
17 | */ | ||
18 | |||
19 | #include <linux/device.h> | ||
20 | #include <linux/hid.h> | ||
21 | #include <linux/module.h> | ||
22 | |||
23 | #include "hid-ids.h" | ||
24 | |||
25 | static int dell_probe(struct hid_device *hdev, const struct hid_device_id *id) | ||
26 | { | ||
27 | int ret; | ||
28 | |||
29 | ret = hid_parse(hdev); | ||
30 | if (ret) { | ||
31 | dev_err(&hdev->dev, "parse failed\n"); | ||
32 | goto err_free; | ||
33 | } | ||
34 | |||
35 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); | ||
36 | if (ret) { | ||
37 | dev_err(&hdev->dev, "hw start failed\n"); | ||
38 | goto err_free; | ||
39 | } | ||
40 | |||
41 | usbhid_set_leds(hdev); | ||
42 | |||
43 | return 0; | ||
44 | err_free: | ||
45 | return ret; | ||
46 | } | ||
47 | |||
48 | static const struct hid_device_id dell_devices[] = { | ||
49 | { HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658) }, | ||
50 | { HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_SK8115) }, | ||
51 | { HID_USB_DEVICE(USB_VENDOR_ID_GENERIC_13BA, USB_DEVICE_ID_GENERIC_13BA_KBD_MOUSE) }, | ||
52 | { } | ||
53 | }; | ||
54 | MODULE_DEVICE_TABLE(hid, dell_devices); | ||
55 | |||
56 | static struct hid_driver dell_driver = { | ||
57 | .name = "dell", | ||
58 | .id_table = dell_devices, | ||
59 | .probe = dell_probe, | ||
60 | }; | ||
61 | |||
62 | static int dell_init(void) | ||
63 | { | ||
64 | return hid_register_driver(&dell_driver); | ||
65 | } | ||
66 | |||
67 | static void dell_exit(void) | ||
68 | { | ||
69 | hid_unregister_driver(&dell_driver); | ||
70 | } | ||
71 | |||
72 | module_init(dell_init); | ||
73 | module_exit(dell_exit); | ||
74 | MODULE_LICENSE("GPL"); | ||
75 | |||
76 | HID_COMPAT_LOAD_DRIVER(dell); | ||
diff --git a/drivers/hid/hid-dummy.c b/drivers/hid/hid-dummy.c index e148f86fb58e..b4cc0f743d63 100644 --- a/drivers/hid/hid-dummy.c +++ b/drivers/hid/hid-dummy.c | |||
@@ -43,6 +43,9 @@ static int __init hid_dummy_init(void) | |||
43 | #ifdef CONFIG_HID_MONTEREY_MODULE | 43 | #ifdef CONFIG_HID_MONTEREY_MODULE |
44 | HID_COMPAT_CALL_DRIVER(monterey); | 44 | HID_COMPAT_CALL_DRIVER(monterey); |
45 | #endif | 45 | #endif |
46 | #ifdef CONFIG_HID_NTRIG_MODULE | ||
47 | HID_COMPAT_CALL_DRIVER(ntrig); | ||
48 | #endif | ||
46 | #ifdef CONFIG_HID_PANTHERLORD_MODULE | 49 | #ifdef CONFIG_HID_PANTHERLORD_MODULE |
47 | HID_COMPAT_CALL_DRIVER(pantherlord); | 50 | HID_COMPAT_CALL_DRIVER(pantherlord); |
48 | #endif | 51 | #endif |
@@ -58,6 +61,9 @@ static int __init hid_dummy_init(void) | |||
58 | #ifdef CONFIG_HID_SUNPLUS_MODULE | 61 | #ifdef CONFIG_HID_SUNPLUS_MODULE |
59 | HID_COMPAT_CALL_DRIVER(sunplus); | 62 | HID_COMPAT_CALL_DRIVER(sunplus); |
60 | #endif | 63 | #endif |
64 | #ifdef CONFIG_GREENASIA_FF_MODULE | ||
65 | HID_COMPAT_CALL_DRIVER(greenasia); | ||
66 | #endif | ||
61 | #ifdef CONFIG_THRUSTMASTER_FF_MODULE | 67 | #ifdef CONFIG_THRUSTMASTER_FF_MODULE |
62 | HID_COMPAT_CALL_DRIVER(thrustmaster); | 68 | HID_COMPAT_CALL_DRIVER(thrustmaster); |
63 | #endif | 69 | #endif |
diff --git a/drivers/hid/hid-gaff.c b/drivers/hid/hid-gaff.c new file mode 100644 index 000000000000..71211f6a4f02 --- /dev/null +++ b/drivers/hid/hid-gaff.c | |||
@@ -0,0 +1,185 @@ | |||
1 | /* | ||
2 | * Force feedback support for GreenAsia (Product ID 0x12) based devices | ||
3 | * | ||
4 | * The devices are distributed under various names and the same USB device ID | ||
5 | * can be used in many game controllers. | ||
6 | * | ||
7 | * | ||
8 | * 0e8f:0012 "GreenAsia Inc. USB Joystick " | ||
9 | * - tested with MANTA Warior MM816 and SpeedLink Strike2 SL-6635. | ||
10 | * | ||
11 | * Copyright (c) 2008 Lukasz Lubojanski <lukasz@lubojanski.info> | ||
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 | #include <linux/usb.h> | ||
32 | #include <linux/hid.h> | ||
33 | #include "hid-ids.h" | ||
34 | #include "usbhid/usbhid.h" | ||
35 | |||
36 | struct gaff_device { | ||
37 | struct hid_report *report; | ||
38 | }; | ||
39 | |||
40 | static int hid_gaff_play(struct input_dev *dev, void *data, | ||
41 | struct ff_effect *effect) | ||
42 | { | ||
43 | struct hid_device *hid = input_get_drvdata(dev); | ||
44 | struct gaff_device *gaff = data; | ||
45 | int left, right; | ||
46 | |||
47 | left = effect->u.rumble.strong_magnitude; | ||
48 | right = effect->u.rumble.weak_magnitude; | ||
49 | |||
50 | dbg_hid("called with 0x%04x 0x%04x", left, right); | ||
51 | |||
52 | left = left * 0xfe / 0xffff; | ||
53 | right = right * 0xfe / 0xffff; | ||
54 | |||
55 | gaff->report->field[0]->value[0] = 0x51; | ||
56 | gaff->report->field[0]->value[1] = 0x0; | ||
57 | gaff->report->field[0]->value[2] = right; | ||
58 | gaff->report->field[0]->value[3] = 0; | ||
59 | gaff->report->field[0]->value[4] = left; | ||
60 | gaff->report->field[0]->value[5] = 0; | ||
61 | dbg_hid("running with 0x%02x 0x%02x", left, right); | ||
62 | usbhid_submit_report(hid, gaff->report, USB_DIR_OUT); | ||
63 | |||
64 | gaff->report->field[0]->value[0] = 0xfa; | ||
65 | gaff->report->field[0]->value[1] = 0xfe; | ||
66 | gaff->report->field[0]->value[2] = 0x0; | ||
67 | gaff->report->field[0]->value[4] = 0x0; | ||
68 | |||
69 | usbhid_submit_report(hid, gaff->report, USB_DIR_OUT); | ||
70 | |||
71 | return 0; | ||
72 | } | ||
73 | |||
74 | static int gaff_init(struct hid_device *hid) | ||
75 | { | ||
76 | struct gaff_device *gaff; | ||
77 | struct hid_report *report; | ||
78 | struct hid_input *hidinput = list_entry(hid->inputs.next, | ||
79 | struct hid_input, list); | ||
80 | struct list_head *report_list = | ||
81 | &hid->report_enum[HID_OUTPUT_REPORT].report_list; | ||
82 | struct list_head *report_ptr = report_list; | ||
83 | struct input_dev *dev = hidinput->input; | ||
84 | int error; | ||
85 | |||
86 | if (list_empty(report_list)) { | ||
87 | dev_err(&hid->dev, "no output reports found\n"); | ||
88 | return -ENODEV; | ||
89 | } | ||
90 | |||
91 | report_ptr = report_ptr->next; | ||
92 | |||
93 | report = list_entry(report_ptr, struct hid_report, list); | ||
94 | if (report->maxfield < 1) { | ||
95 | dev_err(&hid->dev, "no fields in the report\n"); | ||
96 | return -ENODEV; | ||
97 | } | ||
98 | |||
99 | if (report->field[0]->report_count < 6) { | ||
100 | dev_err(&hid->dev, "not enough values in the field\n"); | ||
101 | return -ENODEV; | ||
102 | } | ||
103 | |||
104 | gaff = kzalloc(sizeof(struct gaff_device), GFP_KERNEL); | ||
105 | if (!gaff) | ||
106 | return -ENOMEM; | ||
107 | |||
108 | set_bit(FF_RUMBLE, dev->ffbit); | ||
109 | |||
110 | error = input_ff_create_memless(dev, gaff, hid_gaff_play); | ||
111 | if (error) { | ||
112 | kfree(gaff); | ||
113 | return error; | ||
114 | } | ||
115 | |||
116 | gaff->report = report; | ||
117 | gaff->report->field[0]->value[0] = 0x51; | ||
118 | gaff->report->field[0]->value[1] = 0x00; | ||
119 | gaff->report->field[0]->value[2] = 0x00; | ||
120 | gaff->report->field[0]->value[3] = 0x00; | ||
121 | usbhid_submit_report(hid, gaff->report, USB_DIR_OUT); | ||
122 | |||
123 | gaff->report->field[0]->value[0] = 0xfa; | ||
124 | gaff->report->field[0]->value[1] = 0xfe; | ||
125 | |||
126 | usbhid_submit_report(hid, gaff->report, USB_DIR_OUT); | ||
127 | |||
128 | dev_info(&hid->dev, "Force Feedback for GreenAsia 0x12" | ||
129 | " devices by Lukasz Lubojanski <lukasz@lubojanski.info>\n"); | ||
130 | |||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | static int ga_probe(struct hid_device *hdev, const struct hid_device_id *id) | ||
135 | { | ||
136 | int ret; | ||
137 | |||
138 | dev_dbg(&hdev->dev, "Greenasia HID hardware probe..."); | ||
139 | |||
140 | ret = hid_parse(hdev); | ||
141 | if (ret) { | ||
142 | dev_err(&hdev->dev, "parse failed\n"); | ||
143 | goto err; | ||
144 | } | ||
145 | |||
146 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); | ||
147 | if (ret) { | ||
148 | dev_err(&hdev->dev, "hw start failed\n"); | ||
149 | goto err; | ||
150 | } | ||
151 | |||
152 | gaff_init(hdev); | ||
153 | |||
154 | return 0; | ||
155 | err: | ||
156 | return ret; | ||
157 | } | ||
158 | |||
159 | static const struct hid_device_id ga_devices[] = { | ||
160 | { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0012), }, | ||
161 | { } | ||
162 | }; | ||
163 | MODULE_DEVICE_TABLE(hid, ga_devices); | ||
164 | |||
165 | static struct hid_driver ga_driver = { | ||
166 | .name = "greenasia", | ||
167 | .id_table = ga_devices, | ||
168 | .probe = ga_probe, | ||
169 | }; | ||
170 | |||
171 | static int __init ga_init(void) | ||
172 | { | ||
173 | return hid_register_driver(&ga_driver); | ||
174 | } | ||
175 | |||
176 | static void __exit ga_exit(void) | ||
177 | { | ||
178 | hid_unregister_driver(&ga_driver); | ||
179 | } | ||
180 | |||
181 | module_init(ga_init); | ||
182 | module_exit(ga_exit); | ||
183 | MODULE_LICENSE("GPL"); | ||
184 | |||
185 | HID_COMPAT_LOAD_DRIVER(greenasia); | ||
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 39289699c32f..acc1abc834a4 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h | |||
@@ -107,9 +107,6 @@ | |||
107 | #define USB_VENDOR_ID_BELKIN 0x050d | 107 | #define USB_VENDOR_ID_BELKIN 0x050d |
108 | #define USB_DEVICE_ID_FLIP_KVM 0x3201 | 108 | #define USB_DEVICE_ID_FLIP_KVM 0x3201 |
109 | 109 | ||
110 | #define USB_VENDOR_ID_BRIGHT 0x1241 | ||
111 | #define USB_DEVICE_ID_BRIGHT_ABNT2 0x1503 | ||
112 | |||
113 | #define USB_VENDOR_ID_BERKSHIRE 0x0c98 | 110 | #define USB_VENDOR_ID_BERKSHIRE 0x0c98 |
114 | #define USB_DEVICE_ID_BERKSHIRE_PCWD 0x1140 | 111 | #define USB_DEVICE_ID_BERKSHIRE_PCWD 0x1140 |
115 | 112 | ||
@@ -141,9 +138,8 @@ | |||
141 | #define USB_DEVICE_ID_CYPRESS_BARCODE_1 0xde61 | 138 | #define USB_DEVICE_ID_CYPRESS_BARCODE_1 0xde61 |
142 | #define USB_DEVICE_ID_CYPRESS_BARCODE_2 0xde64 | 139 | #define USB_DEVICE_ID_CYPRESS_BARCODE_2 0xde64 |
143 | 140 | ||
144 | #define USB_VENDOR_ID_DELL 0x413c | 141 | #define USB_VENDOR_ID_DEALEXTREAME 0x10c5 |
145 | #define USB_DEVICE_ID_DELL_W7658 0x2005 | 142 | #define USB_DEVICE_ID_DEALEXTREAME_RADIO_SI4701 0x819a |
146 | #define USB_DEVICE_ID_DELL_SK8115 0x2105 | ||
147 | 143 | ||
148 | #define USB_VENDOR_ID_DELORME 0x1163 | 144 | #define USB_VENDOR_ID_DELORME 0x1163 |
149 | #define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100 | 145 | #define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100 |
@@ -167,9 +163,6 @@ | |||
167 | 163 | ||
168 | #define USB_VENDOR_ID_GENERAL_TOUCH 0x0dfc | 164 | #define USB_VENDOR_ID_GENERAL_TOUCH 0x0dfc |
169 | 165 | ||
170 | #define USB_VENDOR_ID_GENERIC_13BA 0x13ba | ||
171 | #define USB_DEVICE_ID_GENERIC_13BA_KBD_MOUSE 0x0017 | ||
172 | |||
173 | #define USB_VENDOR_ID_GLAB 0x06c2 | 166 | #define USB_VENDOR_ID_GLAB 0x06c2 |
174 | #define USB_DEVICE_ID_4_PHIDGETSERVO_30 0x0038 | 167 | #define USB_DEVICE_ID_4_PHIDGETSERVO_30 0x0038 |
175 | #define USB_DEVICE_ID_1_PHIDGETSERVO_30 0x0039 | 168 | #define USB_DEVICE_ID_1_PHIDGETSERVO_30 0x0039 |
@@ -292,7 +285,6 @@ | |||
292 | #define USB_DEVICE_ID_LOGITECH_WHEEL 0xc294 | 285 | #define USB_DEVICE_ID_LOGITECH_WHEEL 0xc294 |
293 | #define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL 0xc295 | 286 | #define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL 0xc295 |
294 | #define USB_DEVICE_ID_LOGITECH_ELITE_KBD 0xc30a | 287 | #define USB_DEVICE_ID_LOGITECH_ELITE_KBD 0xc30a |
295 | #define USB_DEVICE_ID_LOGITECH_KBD 0xc311 | ||
296 | #define USB_DEVICE_ID_S510_RECEIVER 0xc50c | 288 | #define USB_DEVICE_ID_S510_RECEIVER 0xc50c |
297 | #define USB_DEVICE_ID_S510_RECEIVER_2 0xc517 | 289 | #define USB_DEVICE_ID_S510_RECEIVER_2 0xc517 |
298 | #define USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500 0xc512 | 290 | #define USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500 0xc512 |
@@ -339,6 +331,9 @@ | |||
339 | #define USB_VENDOR_ID_NEC 0x073e | 331 | #define USB_VENDOR_ID_NEC 0x073e |
340 | #define USB_DEVICE_ID_NEC_USB_GAME_PAD 0x0301 | 332 | #define USB_DEVICE_ID_NEC_USB_GAME_PAD 0x0301 |
341 | 333 | ||
334 | #define USB_VENDOR_ID_NTRIG 0x1b96 | ||
335 | #define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN 0x0001 | ||
336 | |||
342 | #define USB_VENDOR_ID_ONTRAK 0x0a07 | 337 | #define USB_VENDOR_ID_ONTRAK 0x0a07 |
343 | #define USB_DEVICE_ID_ONTRAK_ADU100 0x0064 | 338 | #define USB_DEVICE_ID_ONTRAK_ADU100 0x0064 |
344 | 339 | ||
@@ -383,9 +378,15 @@ | |||
383 | #define USB_VENDOR_ID_TOPMAX 0x0663 | 378 | #define USB_VENDOR_ID_TOPMAX 0x0663 |
384 | #define USB_DEVICE_ID_TOPMAX_COBRAPAD 0x0103 | 379 | #define USB_DEVICE_ID_TOPMAX_COBRAPAD 0x0103 |
385 | 380 | ||
381 | #define USB_VENDOR_ID_TOPSEED 0x0766 | ||
382 | #define USB_DEVICE_ID_TOPSEED_CYBERLINK 0x0204 | ||
383 | |||
386 | #define USB_VENDOR_ID_TURBOX 0x062a | 384 | #define USB_VENDOR_ID_TURBOX 0x062a |
387 | #define USB_DEVICE_ID_TURBOX_KEYBOARD 0x0201 | 385 | #define USB_DEVICE_ID_TURBOX_KEYBOARD 0x0201 |
388 | 386 | ||
387 | #define USB_VENDOR_ID_UCLOGIC 0x5543 | ||
388 | #define USB_DEVICE_ID_UCLOGIC_TABLET_PF1209 0x0042 | ||
389 | |||
389 | #define USB_VENDOR_ID_VERNIER 0x08f7 | 390 | #define USB_VENDOR_ID_VERNIER 0x08f7 |
390 | #define USB_DEVICE_ID_VERNIER_LABPRO 0x0001 | 391 | #define USB_DEVICE_ID_VERNIER_LABPRO 0x0001 |
391 | #define USB_DEVICE_ID_VERNIER_GOTEMP 0x0002 | 392 | #define USB_DEVICE_ID_VERNIER_GOTEMP 0x0002 |
diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c index 2bae340eafe2..83e07c9f4144 100644 --- a/drivers/hid/hid-lg.c +++ b/drivers/hid/hid-lg.c | |||
@@ -26,7 +26,6 @@ | |||
26 | #define LG_RDESC 0x001 | 26 | #define LG_RDESC 0x001 |
27 | #define LG_BAD_RELATIVE_KEYS 0x002 | 27 | #define LG_BAD_RELATIVE_KEYS 0x002 |
28 | #define LG_DUPLICATE_USAGES 0x004 | 28 | #define LG_DUPLICATE_USAGES 0x004 |
29 | #define LG_RESET_LEDS 0x008 | ||
30 | #define LG_EXPANDED_KEYMAP 0x010 | 29 | #define LG_EXPANDED_KEYMAP 0x010 |
31 | #define LG_IGNORE_DOUBLED_WHEEL 0x020 | 30 | #define LG_IGNORE_DOUBLED_WHEEL 0x020 |
32 | #define LG_WIRELESS 0x040 | 31 | #define LG_WIRELESS 0x040 |
@@ -248,9 +247,6 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
248 | goto err_free; | 247 | goto err_free; |
249 | } | 248 | } |
250 | 249 | ||
251 | if (quirks & LG_RESET_LEDS) | ||
252 | usbhid_set_leds(hdev); | ||
253 | |||
254 | if (quirks & LG_FF) | 250 | if (quirks & LG_FF) |
255 | lgff_init(hdev); | 251 | lgff_init(hdev); |
256 | if (quirks & LG_FF2) | 252 | if (quirks & LG_FF2) |
@@ -279,9 +275,6 @@ static const struct hid_device_id lg_devices[] = { | |||
279 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI), | 275 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI), |
280 | .driver_data = LG_DUPLICATE_USAGES }, | 276 | .driver_data = LG_DUPLICATE_USAGES }, |
281 | 277 | ||
282 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KBD), | ||
283 | .driver_data = LG_RESET_LEDS }, | ||
284 | |||
285 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD), | 278 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD), |
286 | .driver_data = LG_IGNORE_DOUBLED_WHEEL | LG_EXPANDED_KEYMAP }, | 279 | .driver_data = LG_IGNORE_DOUBLED_WHEEL | LG_EXPANDED_KEYMAP }, |
287 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500), | 280 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500), |
diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c new file mode 100644 index 000000000000..db44fbd7bdf6 --- /dev/null +++ b/drivers/hid/hid-ntrig.c | |||
@@ -0,0 +1,82 @@ | |||
1 | /* | ||
2 | * HID driver for some ntrig "special" devices | ||
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 | * Copyright (c) 2008 Jiri Slaby | ||
10 | * Copyright (c) 2008 Rafi Rubin | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | /* | ||
15 | * This program is free software; you can redistribute it and/or modify it | ||
16 | * under the terms of the GNU General Public License as published by the Free | ||
17 | * Software Foundation; either version 2 of the License, or (at your option) | ||
18 | * any later version. | ||
19 | */ | ||
20 | |||
21 | #include <linux/device.h> | ||
22 | #include <linux/hid.h> | ||
23 | #include <linux/module.h> | ||
24 | |||
25 | #include "hid-ids.h" | ||
26 | |||
27 | #define NTRIG_DUPLICATE_USAGES 0x001 | ||
28 | |||
29 | #define nt_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ | ||
30 | EV_KEY, (c)) | ||
31 | |||
32 | static int ntrig_input_mapping(struct hid_device *hdev, struct hid_input *hi, | ||
33 | struct hid_field *field, struct hid_usage *usage, | ||
34 | unsigned long **bit, int *max) | ||
35 | { | ||
36 | if ((usage->hid & HID_USAGE_PAGE) == HID_UP_DIGITIZER && | ||
37 | (usage->hid & 0xff) == 0x47) { | ||
38 | nt_map_key_clear(BTN_TOOL_DOUBLETAP); | ||
39 | return 1; | ||
40 | } | ||
41 | return 0; | ||
42 | } | ||
43 | |||
44 | static int ntrig_input_mapped(struct hid_device *hdev, struct hid_input *hi, | ||
45 | struct hid_field *field, struct hid_usage *usage, | ||
46 | unsigned long **bit, int *max) | ||
47 | { | ||
48 | if (usage->type == EV_KEY || usage->type == EV_REL | ||
49 | || usage->type == EV_ABS) | ||
50 | clear_bit(usage->code, *bit); | ||
51 | |||
52 | return 0; | ||
53 | } | ||
54 | static const struct hid_device_id ntrig_devices[] = { | ||
55 | { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN), | ||
56 | .driver_data = NTRIG_DUPLICATE_USAGES }, | ||
57 | { } | ||
58 | }; | ||
59 | MODULE_DEVICE_TABLE(hid, ntrig_devices); | ||
60 | |||
61 | static struct hid_driver ntrig_driver = { | ||
62 | .name = "ntrig", | ||
63 | .id_table = ntrig_devices, | ||
64 | .input_mapping = ntrig_input_mapping, | ||
65 | .input_mapped = ntrig_input_mapped, | ||
66 | }; | ||
67 | |||
68 | static int ntrig_init(void) | ||
69 | { | ||
70 | return hid_register_driver(&ntrig_driver); | ||
71 | } | ||
72 | |||
73 | static void ntrig_exit(void) | ||
74 | { | ||
75 | hid_unregister_driver(&ntrig_driver); | ||
76 | } | ||
77 | |||
78 | module_init(ntrig_init); | ||
79 | module_exit(ntrig_exit); | ||
80 | MODULE_LICENSE("GPL"); | ||
81 | |||
82 | HID_COMPAT_LOAD_DRIVER(ntrig); | ||
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 86e563b8d644..dd5a3979a4de 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c | |||
@@ -102,7 +102,7 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
102 | } | 102 | } |
103 | 103 | ||
104 | ret = sony_set_operational(hdev); | 104 | ret = sony_set_operational(hdev); |
105 | if (ret) | 105 | if (ret < 0) |
106 | goto err_stop; | 106 | goto err_stop; |
107 | 107 | ||
108 | return 0; | 108 | return 0; |
diff --git a/drivers/hid/hid-topseed.c b/drivers/hid/hid-topseed.c new file mode 100644 index 000000000000..cca64a0564a9 --- /dev/null +++ b/drivers/hid/hid-topseed.c | |||
@@ -0,0 +1,77 @@ | |||
1 | /* | ||
2 | * HID driver for TopSeed Cyberlink remote | ||
3 | * | ||
4 | * Copyright (c) 2008 Lev Babiev | ||
5 | * based on hid-cherry driver | ||
6 | */ | ||
7 | |||
8 | /* | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the Free | ||
11 | * Software Foundation; either version 2 of the License, or (at your option) | ||
12 | * any later version. | ||
13 | */ | ||
14 | |||
15 | #include <linux/device.h> | ||
16 | #include <linux/hid.h> | ||
17 | #include <linux/module.h> | ||
18 | |||
19 | #include "hid-ids.h" | ||
20 | |||
21 | #define ts_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ | ||
22 | EV_KEY, (c)) | ||
23 | static int ts_input_mapping(struct hid_device *hdev, struct hid_input *hi, | ||
24 | struct hid_field *field, struct hid_usage *usage, | ||
25 | unsigned long **bit, int *max) | ||
26 | { | ||
27 | if ((usage->hid & HID_USAGE_PAGE) != 0x0ffbc0000) | ||
28 | return 0; | ||
29 | |||
30 | switch (usage->hid & HID_USAGE) { | ||
31 | case 0x00d: ts_map_key_clear(KEY_HOME); break; | ||
32 | case 0x024: ts_map_key_clear(KEY_MENU); break; | ||
33 | case 0x025: ts_map_key_clear(KEY_TV); break; | ||
34 | case 0x048: ts_map_key_clear(KEY_RED); break; | ||
35 | case 0x047: ts_map_key_clear(KEY_GREEN); break; | ||
36 | case 0x049: ts_map_key_clear(KEY_YELLOW); break; | ||
37 | case 0x04a: ts_map_key_clear(KEY_BLUE); break; | ||
38 | case 0x04b: ts_map_key_clear(KEY_ANGLE); break; | ||
39 | case 0x04c: ts_map_key_clear(KEY_LANGUAGE); break; | ||
40 | case 0x04d: ts_map_key_clear(KEY_SUBTITLE); break; | ||
41 | case 0x031: ts_map_key_clear(KEY_AUDIO); break; | ||
42 | case 0x032: ts_map_key_clear(KEY_TEXT); break; | ||
43 | case 0x033: ts_map_key_clear(KEY_CHANNEL); break; | ||
44 | default: | ||
45 | return 0; | ||
46 | } | ||
47 | |||
48 | return 1; | ||
49 | } | ||
50 | |||
51 | static const struct hid_device_id ts_devices[] = { | ||
52 | { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) }, | ||
53 | { } | ||
54 | }; | ||
55 | MODULE_DEVICE_TABLE(hid, ts_devices); | ||
56 | |||
57 | static struct hid_driver ts_driver = { | ||
58 | .name = "topseed", | ||
59 | .id_table = ts_devices, | ||
60 | .input_mapping = ts_input_mapping, | ||
61 | }; | ||
62 | |||
63 | static int ts_init(void) | ||
64 | { | ||
65 | return hid_register_driver(&ts_driver); | ||
66 | } | ||
67 | |||
68 | static void ts_exit(void) | ||
69 | { | ||
70 | hid_unregister_driver(&ts_driver); | ||
71 | } | ||
72 | |||
73 | module_init(ts_init); | ||
74 | module_exit(ts_exit); | ||
75 | MODULE_LICENSE("GPL"); | ||
76 | |||
77 | HID_COMPAT_LOAD_DRIVER(topseed); | ||
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c index 7685ae6808c4..732449628971 100644 --- a/drivers/hid/hidraw.c +++ b/drivers/hid/hidraw.c | |||
@@ -208,7 +208,7 @@ static int hidraw_release(struct inode * inode, struct file * file) | |||
208 | 208 | ||
209 | list_del(&list->node); | 209 | list_del(&list->node); |
210 | dev = hidraw_table[minor]; | 210 | dev = hidraw_table[minor]; |
211 | if (!dev->open--) { | 211 | if (!--dev->open) { |
212 | if (list->hidraw->exist) | 212 | if (list->hidraw->exist) |
213 | dev->hid->ll_driver->close(dev->hid); | 213 | dev->hid->ll_driver->close(dev->hid); |
214 | else | 214 | else |
@@ -265,6 +265,34 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd, | |||
265 | break; | 265 | break; |
266 | } | 266 | } |
267 | default: | 267 | default: |
268 | { | ||
269 | struct hid_device *hid = dev->hid; | ||
270 | if (_IOC_TYPE(cmd) != 'H' || _IOC_DIR(cmd) != _IOC_READ) | ||
271 | return -EINVAL; | ||
272 | |||
273 | if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWNAME(0))) { | ||
274 | int len; | ||
275 | if (!hid->name) | ||
276 | return 0; | ||
277 | len = strlen(hid->name) + 1; | ||
278 | if (len > _IOC_SIZE(cmd)) | ||
279 | len = _IOC_SIZE(cmd); | ||
280 | return copy_to_user(user_arg, hid->name, len) ? | ||
281 | -EFAULT : len; | ||
282 | } | ||
283 | |||
284 | if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWPHYS(0))) { | ||
285 | int len; | ||
286 | if (!hid->phys) | ||
287 | return 0; | ||
288 | len = strlen(hid->phys) + 1; | ||
289 | if (len > _IOC_SIZE(cmd)) | ||
290 | len = _IOC_SIZE(cmd); | ||
291 | return copy_to_user(user_arg, hid->phys, len) ? | ||
292 | -EFAULT : len; | ||
293 | } | ||
294 | } | ||
295 | |||
268 | ret = -ENOTTY; | 296 | ret = -ENOTTY; |
269 | } | 297 | } |
270 | unlock_kernel(); | 298 | unlock_kernel(); |
@@ -329,7 +357,7 @@ int hidraw_connect(struct hid_device *hid) | |||
329 | goto out; | 357 | goto out; |
330 | } | 358 | } |
331 | 359 | ||
332 | dev->dev = device_create(hidraw_class, NULL, MKDEV(hidraw_major, minor), | 360 | dev->dev = device_create(hidraw_class, &hid->dev, MKDEV(hidraw_major, minor), |
333 | NULL, "%s%d", "hidraw", minor); | 361 | NULL, "%s%d", "hidraw", minor); |
334 | 362 | ||
335 | if (IS_ERR(dev->dev)) { | 363 | if (IS_ERR(dev->dev)) { |
diff --git a/drivers/hid/usbhid/Kconfig b/drivers/hid/usbhid/Kconfig index 5d9aa95fc3ef..4edb3bef94a6 100644 --- a/drivers/hid/usbhid/Kconfig +++ b/drivers/hid/usbhid/Kconfig | |||
@@ -45,7 +45,7 @@ config USB_HIDDEV | |||
45 | If unsure, say Y. | 45 | If unsure, say Y. |
46 | 46 | ||
47 | menu "USB HID Boot Protocol drivers" | 47 | menu "USB HID Boot Protocol drivers" |
48 | depends on USB!=n && USB_HID!=y | 48 | depends on USB!=n && USB_HID!=y && EMBEDDED |
49 | 49 | ||
50 | config USB_KBD | 50 | config USB_KBD |
51 | tristate "USB HIDBP Keyboard (simple Boot) support" | 51 | tristate "USB HIDBP Keyboard (simple Boot) support" |
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 606369ea24ca..03cb494af1c5 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/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-2007 Jiri Kosina | 7 | * Copyright (c) 2006-2008 Jiri Kosina |
8 | */ | 8 | */ |
9 | 9 | ||
10 | /* | 10 | /* |
@@ -641,9 +641,7 @@ static void hid_find_max_report(struct hid_device *hid, unsigned int type, | |||
641 | unsigned int size; | 641 | unsigned int size; |
642 | 642 | ||
643 | list_for_each_entry(report, &hid->report_enum[type].report_list, list) { | 643 | list_for_each_entry(report, &hid->report_enum[type].report_list, list) { |
644 | size = ((report->size - 1) >> 3) + 1; | 644 | size = ((report->size - 1) >> 3) + 1 + hid->report_enum[type].numbered; |
645 | if (type == HID_INPUT_REPORT && hid->report_enum[type].numbered) | ||
646 | size++; | ||
647 | if (*max < size) | 645 | if (*max < size) |
648 | *max = size; | 646 | *max = size; |
649 | } | 647 | } |
@@ -653,13 +651,16 @@ static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid) | |||
653 | { | 651 | { |
654 | struct usbhid_device *usbhid = hid->driver_data; | 652 | struct usbhid_device *usbhid = hid->driver_data; |
655 | 653 | ||
656 | if (!(usbhid->inbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_ATOMIC, &usbhid->inbuf_dma))) | 654 | usbhid->inbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_KERNEL, |
657 | return -1; | 655 | &usbhid->inbuf_dma); |
658 | if (!(usbhid->outbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_ATOMIC, &usbhid->outbuf_dma))) | 656 | usbhid->outbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_KERNEL, |
659 | return -1; | 657 | &usbhid->outbuf_dma); |
660 | if (!(usbhid->cr = usb_buffer_alloc(dev, sizeof(*(usbhid->cr)), GFP_ATOMIC, &usbhid->cr_dma))) | 658 | usbhid->cr = usb_buffer_alloc(dev, sizeof(*usbhid->cr), GFP_KERNEL, |
661 | return -1; | 659 | &usbhid->cr_dma); |
662 | if (!(usbhid->ctrlbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_ATOMIC, &usbhid->ctrlbuf_dma))) | 660 | usbhid->ctrlbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_KERNEL, |
661 | &usbhid->ctrlbuf_dma); | ||
662 | if (!usbhid->inbuf || !usbhid->outbuf || !usbhid->cr || | ||
663 | !usbhid->ctrlbuf) | ||
663 | return -1; | 664 | return -1; |
664 | 665 | ||
665 | return 0; | 666 | return 0; |
@@ -807,7 +808,7 @@ static int usbhid_start(struct hid_device *hid) | |||
807 | int interval; | 808 | int interval; |
808 | 809 | ||
809 | endpoint = &interface->endpoint[n].desc; | 810 | endpoint = &interface->endpoint[n].desc; |
810 | if ((endpoint->bmAttributes & 3) != 3) /* Not an interrupt endpoint */ | 811 | if (!usb_endpoint_xfer_int(endpoint)) |
811 | continue; | 812 | continue; |
812 | 813 | ||
813 | interval = endpoint->bInterval; | 814 | interval = endpoint->bInterval; |
@@ -876,6 +877,15 @@ static int usbhid_start(struct hid_device *hid) | |||
876 | 877 | ||
877 | set_bit(HID_STARTED, &usbhid->iofl); | 878 | set_bit(HID_STARTED, &usbhid->iofl); |
878 | 879 | ||
880 | /* Some keyboards don't work until their LEDs have been set. | ||
881 | * Since BIOSes do set the LEDs, it must be safe for any device | ||
882 | * that supports the keyboard boot protocol. | ||
883 | */ | ||
884 | if (interface->desc.bInterfaceSubClass == USB_INTERFACE_SUBCLASS_BOOT && | ||
885 | interface->desc.bInterfaceProtocol == | ||
886 | USB_INTERFACE_PROTOCOL_KEYBOARD) | ||
887 | usbhid_set_leds(hid); | ||
888 | |||
879 | return 0; | 889 | return 0; |
880 | 890 | ||
881 | fail: | 891 | fail: |
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 47ebe045f9b5..4391717d2519 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c | |||
@@ -54,6 +54,7 @@ static const struct hid_blacklist { | |||
54 | { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET }, | 54 | { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET }, |
55 | { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET }, | 55 | { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET }, |
56 | { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET }, | 56 | { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET }, |
57 | { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209, HID_QUIRK_MULTI_INPUT }, | ||
57 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS }, | 58 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS }, |
58 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, | 59 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, |
59 | 60 | ||
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index 83e851a5ed30..6a98f9f572b0 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c | |||
@@ -49,6 +49,7 @@ | |||
49 | struct hiddev { | 49 | struct hiddev { |
50 | int exist; | 50 | int exist; |
51 | int open; | 51 | int open; |
52 | struct mutex existancelock; | ||
52 | wait_queue_head_t wait; | 53 | wait_queue_head_t wait; |
53 | struct hid_device *hid; | 54 | struct hid_device *hid; |
54 | struct list_head list; | 55 | struct list_head list; |
@@ -63,6 +64,7 @@ struct hiddev_list { | |||
63 | struct fasync_struct *fasync; | 64 | struct fasync_struct *fasync; |
64 | struct hiddev *hiddev; | 65 | struct hiddev *hiddev; |
65 | struct list_head node; | 66 | struct list_head node; |
67 | struct mutex thread_lock; | ||
66 | }; | 68 | }; |
67 | 69 | ||
68 | static struct hiddev *hiddev_table[HIDDEV_MINORS]; | 70 | static struct hiddev *hiddev_table[HIDDEV_MINORS]; |
@@ -264,29 +266,48 @@ static int hiddev_release(struct inode * inode, struct file * file) | |||
264 | static int hiddev_open(struct inode *inode, struct file *file) | 266 | static int hiddev_open(struct inode *inode, struct file *file) |
265 | { | 267 | { |
266 | struct hiddev_list *list; | 268 | struct hiddev_list *list; |
267 | unsigned long flags; | 269 | int res; |
268 | 270 | ||
269 | int i = iminor(inode) - HIDDEV_MINOR_BASE; | 271 | int i = iminor(inode) - HIDDEV_MINOR_BASE; |
270 | 272 | ||
271 | if (i >= HIDDEV_MINORS || !hiddev_table[i]) | 273 | if (i >= HIDDEV_MINORS || i < 0 || !hiddev_table[i]) |
272 | return -ENODEV; | 274 | return -ENODEV; |
273 | 275 | ||
274 | if (!(list = kzalloc(sizeof(struct hiddev_list), GFP_KERNEL))) | 276 | if (!(list = kzalloc(sizeof(struct hiddev_list), GFP_KERNEL))) |
275 | return -ENOMEM; | 277 | return -ENOMEM; |
278 | mutex_init(&list->thread_lock); | ||
276 | 279 | ||
277 | list->hiddev = hiddev_table[i]; | 280 | list->hiddev = hiddev_table[i]; |
278 | 281 | ||
279 | spin_lock_irqsave(&list->hiddev->list_lock, flags); | ||
280 | list_add_tail(&list->node, &hiddev_table[i]->list); | ||
281 | spin_unlock_irqrestore(&list->hiddev->list_lock, flags); | ||
282 | 282 | ||
283 | file->private_data = list; | 283 | file->private_data = list; |
284 | 284 | ||
285 | if (!list->hiddev->open++) | 285 | /* |
286 | if (list->hiddev->exist) | 286 | * no need for locking because the USB major number |
287 | usbhid_open(hiddev_table[i]->hid); | 287 | * is shared which usbcore guards against disconnect |
288 | */ | ||
289 | if (list->hiddev->exist) { | ||
290 | if (!list->hiddev->open++) { | ||
291 | res = usbhid_open(hiddev_table[i]->hid); | ||
292 | if (res < 0) { | ||
293 | res = -EIO; | ||
294 | goto bail; | ||
295 | } | ||
296 | } | ||
297 | } else { | ||
298 | res = -ENODEV; | ||
299 | goto bail; | ||
300 | } | ||
301 | |||
302 | spin_lock_irq(&list->hiddev->list_lock); | ||
303 | list_add_tail(&list->node, &hiddev_table[i]->list); | ||
304 | spin_unlock_irq(&list->hiddev->list_lock); | ||
288 | 305 | ||
289 | return 0; | 306 | return 0; |
307 | bail: | ||
308 | file->private_data = NULL; | ||
309 | kfree(list->hiddev); | ||
310 | return res; | ||
290 | } | 311 | } |
291 | 312 | ||
292 | /* | 313 | /* |
@@ -305,7 +326,7 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun | |||
305 | DECLARE_WAITQUEUE(wait, current); | 326 | DECLARE_WAITQUEUE(wait, current); |
306 | struct hiddev_list *list = file->private_data; | 327 | struct hiddev_list *list = file->private_data; |
307 | int event_size; | 328 | int event_size; |
308 | int retval = 0; | 329 | int retval; |
309 | 330 | ||
310 | event_size = ((list->flags & HIDDEV_FLAG_UREF) != 0) ? | 331 | event_size = ((list->flags & HIDDEV_FLAG_UREF) != 0) ? |
311 | sizeof(struct hiddev_usage_ref) : sizeof(struct hiddev_event); | 332 | sizeof(struct hiddev_usage_ref) : sizeof(struct hiddev_event); |
@@ -313,10 +334,14 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun | |||
313 | if (count < event_size) | 334 | if (count < event_size) |
314 | return 0; | 335 | return 0; |
315 | 336 | ||
337 | /* lock against other threads */ | ||
338 | retval = mutex_lock_interruptible(&list->thread_lock); | ||
339 | if (retval) | ||
340 | return -ERESTARTSYS; | ||
341 | |||
316 | while (retval == 0) { | 342 | while (retval == 0) { |
317 | if (list->head == list->tail) { | 343 | if (list->head == list->tail) { |
318 | add_wait_queue(&list->hiddev->wait, &wait); | 344 | prepare_to_wait(&list->hiddev->wait, &wait, TASK_INTERRUPTIBLE); |
319 | set_current_state(TASK_INTERRUPTIBLE); | ||
320 | 345 | ||
321 | while (list->head == list->tail) { | 346 | while (list->head == list->tail) { |
322 | if (file->f_flags & O_NONBLOCK) { | 347 | if (file->f_flags & O_NONBLOCK) { |
@@ -332,35 +357,45 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun | |||
332 | break; | 357 | break; |
333 | } | 358 | } |
334 | 359 | ||
360 | /* let O_NONBLOCK tasks run */ | ||
361 | mutex_unlock(&list->thread_lock); | ||
335 | schedule(); | 362 | schedule(); |
363 | if (mutex_lock_interruptible(&list->thread_lock)) | ||
364 | return -EINTR; | ||
336 | set_current_state(TASK_INTERRUPTIBLE); | 365 | set_current_state(TASK_INTERRUPTIBLE); |
337 | } | 366 | } |
367 | finish_wait(&list->hiddev->wait, &wait); | ||
338 | 368 | ||
339 | set_current_state(TASK_RUNNING); | ||
340 | remove_wait_queue(&list->hiddev->wait, &wait); | ||
341 | } | 369 | } |
342 | 370 | ||
343 | if (retval) | 371 | if (retval) { |
372 | mutex_unlock(&list->thread_lock); | ||
344 | return retval; | 373 | return retval; |
374 | } | ||
345 | 375 | ||
346 | 376 | ||
347 | while (list->head != list->tail && | 377 | while (list->head != list->tail && |
348 | retval + event_size <= count) { | 378 | retval + event_size <= count) { |
349 | if ((list->flags & HIDDEV_FLAG_UREF) == 0) { | 379 | if ((list->flags & HIDDEV_FLAG_UREF) == 0) { |
350 | if (list->buffer[list->tail].field_index != | 380 | if (list->buffer[list->tail].field_index != HID_FIELD_INDEX_NONE) { |
351 | HID_FIELD_INDEX_NONE) { | ||
352 | struct hiddev_event event; | 381 | struct hiddev_event event; |
382 | |||
353 | event.hid = list->buffer[list->tail].usage_code; | 383 | event.hid = list->buffer[list->tail].usage_code; |
354 | event.value = list->buffer[list->tail].value; | 384 | event.value = list->buffer[list->tail].value; |
355 | if (copy_to_user(buffer + retval, &event, sizeof(struct hiddev_event))) | 385 | if (copy_to_user(buffer + retval, &event, sizeof(struct hiddev_event))) { |
386 | mutex_unlock(&list->thread_lock); | ||
356 | return -EFAULT; | 387 | return -EFAULT; |
388 | } | ||
357 | retval += sizeof(struct hiddev_event); | 389 | retval += sizeof(struct hiddev_event); |
358 | } | 390 | } |
359 | } else { | 391 | } else { |
360 | if (list->buffer[list->tail].field_index != HID_FIELD_INDEX_NONE || | 392 | if (list->buffer[list->tail].field_index != HID_FIELD_INDEX_NONE || |
361 | (list->flags & HIDDEV_FLAG_REPORT) != 0) { | 393 | (list->flags & HIDDEV_FLAG_REPORT) != 0) { |
362 | if (copy_to_user(buffer + retval, list->buffer + list->tail, sizeof(struct hiddev_usage_ref))) | 394 | |
395 | if (copy_to_user(buffer + retval, list->buffer + list->tail, sizeof(struct hiddev_usage_ref))) { | ||
396 | mutex_unlock(&list->thread_lock); | ||
363 | return -EFAULT; | 397 | return -EFAULT; |
398 | } | ||
364 | retval += sizeof(struct hiddev_usage_ref); | 399 | retval += sizeof(struct hiddev_usage_ref); |
365 | } | 400 | } |
366 | } | 401 | } |
@@ -368,6 +403,7 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun | |||
368 | } | 403 | } |
369 | 404 | ||
370 | } | 405 | } |
406 | mutex_unlock(&list->thread_lock); | ||
371 | 407 | ||
372 | return retval; | 408 | return retval; |
373 | } | 409 | } |
@@ -555,7 +591,7 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
555 | struct hid_field *field; | 591 | struct hid_field *field; |
556 | struct usbhid_device *usbhid = hid->driver_data; | 592 | struct usbhid_device *usbhid = hid->driver_data; |
557 | void __user *user_arg = (void __user *)arg; | 593 | void __user *user_arg = (void __user *)arg; |
558 | int i; | 594 | int i, r; |
559 | 595 | ||
560 | /* Called without BKL by compat methods so no BKL taken */ | 596 | /* Called without BKL by compat methods so no BKL taken */ |
561 | 597 | ||
@@ -619,10 +655,22 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
619 | } | 655 | } |
620 | 656 | ||
621 | case HIDIOCGSTRING: | 657 | case HIDIOCGSTRING: |
622 | return hiddev_ioctl_string(hiddev, cmd, user_arg); | 658 | mutex_lock(&hiddev->existancelock); |
659 | if (!hiddev->exist) | ||
660 | r = hiddev_ioctl_string(hiddev, cmd, user_arg); | ||
661 | else | ||
662 | r = -ENODEV; | ||
663 | mutex_unlock(&hiddev->existancelock); | ||
664 | return r; | ||
623 | 665 | ||
624 | case HIDIOCINITREPORT: | 666 | case HIDIOCINITREPORT: |
667 | mutex_lock(&hiddev->existancelock); | ||
668 | if (!hiddev->exist) { | ||
669 | mutex_unlock(&hiddev->existancelock); | ||
670 | return -ENODEV; | ||
671 | } | ||
625 | usbhid_init_reports(hid); | 672 | usbhid_init_reports(hid); |
673 | mutex_unlock(&hiddev->existancelock); | ||
626 | 674 | ||
627 | return 0; | 675 | return 0; |
628 | 676 | ||
@@ -636,8 +684,12 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
636 | if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) | 684 | if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) |
637 | return -EINVAL; | 685 | return -EINVAL; |
638 | 686 | ||
639 | usbhid_submit_report(hid, report, USB_DIR_IN); | 687 | mutex_lock(&hiddev->existancelock); |
640 | usbhid_wait_io(hid); | 688 | if (hiddev->exist) { |
689 | usbhid_submit_report(hid, report, USB_DIR_IN); | ||
690 | usbhid_wait_io(hid); | ||
691 | } | ||
692 | mutex_unlock(&hiddev->existancelock); | ||
641 | 693 | ||
642 | return 0; | 694 | return 0; |
643 | 695 | ||
@@ -651,8 +703,12 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
651 | if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) | 703 | if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL) |
652 | return -EINVAL; | 704 | return -EINVAL; |
653 | 705 | ||
654 | usbhid_submit_report(hid, report, USB_DIR_OUT); | 706 | mutex_lock(&hiddev->existancelock); |
655 | usbhid_wait_io(hid); | 707 | if (hiddev->exist) { |
708 | usbhid_submit_report(hid, report, USB_DIR_OUT); | ||
709 | usbhid_wait_io(hid); | ||
710 | } | ||
711 | mutex_unlock(&hiddev->existancelock); | ||
656 | 712 | ||
657 | return 0; | 713 | return 0; |
658 | 714 | ||
@@ -710,7 +766,13 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
710 | case HIDIOCGUSAGES: | 766 | case HIDIOCGUSAGES: |
711 | case HIDIOCSUSAGES: | 767 | case HIDIOCSUSAGES: |
712 | case HIDIOCGCOLLECTIONINDEX: | 768 | case HIDIOCGCOLLECTIONINDEX: |
713 | return hiddev_ioctl_usage(hiddev, cmd, user_arg); | 769 | mutex_lock(&hiddev->existancelock); |
770 | if (hiddev->exist) | ||
771 | r = hiddev_ioctl_usage(hiddev, cmd, user_arg); | ||
772 | else | ||
773 | r = -ENODEV; | ||
774 | mutex_unlock(&hiddev->existancelock); | ||
775 | return r; | ||
714 | 776 | ||
715 | case HIDIOCGCOLLECTIONINFO: | 777 | case HIDIOCGCOLLECTIONINFO: |
716 | if (copy_from_user(&cinfo, user_arg, sizeof(cinfo))) | 778 | if (copy_from_user(&cinfo, user_arg, sizeof(cinfo))) |
@@ -808,23 +870,22 @@ int hiddev_connect(struct hid_device *hid, unsigned int force) | |||
808 | if (!(hiddev = kzalloc(sizeof(struct hiddev), GFP_KERNEL))) | 870 | if (!(hiddev = kzalloc(sizeof(struct hiddev), GFP_KERNEL))) |
809 | return -1; | 871 | return -1; |
810 | 872 | ||
811 | retval = usb_register_dev(usbhid->intf, &hiddev_class); | ||
812 | if (retval) { | ||
813 | err_hid("Not able to get a minor for this device."); | ||
814 | kfree(hiddev); | ||
815 | return -1; | ||
816 | } | ||
817 | |||
818 | init_waitqueue_head(&hiddev->wait); | 873 | init_waitqueue_head(&hiddev->wait); |
819 | INIT_LIST_HEAD(&hiddev->list); | 874 | INIT_LIST_HEAD(&hiddev->list); |
820 | spin_lock_init(&hiddev->list_lock); | 875 | spin_lock_init(&hiddev->list_lock); |
876 | mutex_init(&hiddev->existancelock); | ||
821 | hiddev->hid = hid; | 877 | hiddev->hid = hid; |
822 | hiddev->exist = 1; | 878 | hiddev->exist = 1; |
823 | 879 | ||
824 | hid->minor = usbhid->intf->minor; | 880 | retval = usb_register_dev(usbhid->intf, &hiddev_class); |
825 | hid->hiddev = hiddev; | 881 | if (retval) { |
826 | 882 | err_hid("Not able to get a minor for this device."); | |
827 | hiddev_table[usbhid->intf->minor - HIDDEV_MINOR_BASE] = hiddev; | 883 | kfree(hiddev); |
884 | return -1; | ||
885 | } else { | ||
886 | hid->minor = usbhid->intf->minor; | ||
887 | hiddev_table[usbhid->intf->minor - HIDDEV_MINOR_BASE] = hiddev; | ||
888 | } | ||
828 | 889 | ||
829 | return 0; | 890 | return 0; |
830 | } | 891 | } |
@@ -839,7 +900,9 @@ void hiddev_disconnect(struct hid_device *hid) | |||
839 | struct hiddev *hiddev = hid->hiddev; | 900 | struct hiddev *hiddev = hid->hiddev; |
840 | struct usbhid_device *usbhid = hid->driver_data; | 901 | struct usbhid_device *usbhid = hid->driver_data; |
841 | 902 | ||
903 | mutex_lock(&hiddev->existancelock); | ||
842 | hiddev->exist = 0; | 904 | hiddev->exist = 0; |
905 | mutex_unlock(&hiddev->existancelock); | ||
843 | 906 | ||
844 | hiddev_table[hiddev->hid->minor - HIDDEV_MINOR_BASE] = NULL; | 907 | hiddev_table[hiddev->hid->minor - HIDDEV_MINOR_BASE] = NULL; |
845 | usb_deregister_dev(usbhid->intf, &hiddev_class); | 908 | usb_deregister_dev(usbhid->intf, &hiddev_class); |
diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h index 332abcdf9956..9eb30564be9c 100644 --- a/drivers/hid/usbhid/usbhid.h +++ b/drivers/hid/usbhid/usbhid.h | |||
@@ -40,6 +40,16 @@ int usbhid_open(struct hid_device *hid); | |||
40 | void usbhid_init_reports(struct hid_device *hid); | 40 | void usbhid_init_reports(struct hid_device *hid); |
41 | void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir); | 41 | void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir); |
42 | 42 | ||
43 | /* iofl flags */ | ||
44 | #define HID_CTRL_RUNNING 1 | ||
45 | #define HID_OUT_RUNNING 2 | ||
46 | #define HID_IN_RUNNING 3 | ||
47 | #define HID_RESET_PENDING 4 | ||
48 | #define HID_SUSPENDED 5 | ||
49 | #define HID_CLEAR_HALT 6 | ||
50 | #define HID_DISCONNECTED 7 | ||
51 | #define HID_STARTED 8 | ||
52 | |||
43 | /* | 53 | /* |
44 | * USB-specific HID struct, to be pointed to | 54 | * USB-specific HID struct, to be pointed to |
45 | * from struct hid_device->driver_data | 55 | * from struct hid_device->driver_data |