diff options
| -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 | ||||
| -rw-r--r-- | include/linux/hid.h | 16 | ||||
| -rw-r--r-- | include/linux/hidraw.h | 2 |
20 files changed, 685 insertions, 269 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 |
diff --git a/include/linux/hid.h b/include/linux/hid.h index e5780f8c934a..81aa84d60c6b 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h | |||
| @@ -403,15 +403,6 @@ struct hid_output_fifo { | |||
| 403 | #define HID_STAT_ADDED 1 | 403 | #define HID_STAT_ADDED 1 |
| 404 | #define HID_STAT_PARSED 2 | 404 | #define HID_STAT_PARSED 2 |
| 405 | 405 | ||
| 406 | #define HID_CTRL_RUNNING 1 | ||
| 407 | #define HID_OUT_RUNNING 2 | ||
| 408 | #define HID_IN_RUNNING 3 | ||
| 409 | #define HID_RESET_PENDING 4 | ||
| 410 | #define HID_SUSPENDED 5 | ||
| 411 | #define HID_CLEAR_HALT 6 | ||
| 412 | #define HID_DISCONNECTED 7 | ||
| 413 | #define HID_STARTED 8 | ||
| 414 | |||
| 415 | struct hid_input { | 406 | struct hid_input { |
| 416 | struct list_head list; | 407 | struct list_head list; |
| 417 | struct hid_report *report; | 408 | struct hid_report *report; |
| @@ -540,6 +531,8 @@ struct hid_usage_id { | |||
| 540 | * @name: driver name (e.g. "Footech_bar-wheel") | 531 | * @name: driver name (e.g. "Footech_bar-wheel") |
| 541 | * @id_table: which devices is this driver for (must be non-NULL for probe | 532 | * @id_table: which devices is this driver for (must be non-NULL for probe |
| 542 | * to be called) | 533 | * to be called) |
| 534 | * @dyn_list: list of dynamically added device ids | ||
| 535 | * @dyn_lock: lock protecting @dyn_list | ||
| 543 | * @probe: new device inserted | 536 | * @probe: new device inserted |
| 544 | * @remove: device removed (NULL if not a hot-plug capable driver) | 537 | * @remove: device removed (NULL if not a hot-plug capable driver) |
| 545 | * @report_table: on which reports to call raw_event (NULL means all) | 538 | * @report_table: on which reports to call raw_event (NULL means all) |
| @@ -567,6 +560,9 @@ struct hid_driver { | |||
| 567 | char *name; | 560 | char *name; |
| 568 | const struct hid_device_id *id_table; | 561 | const struct hid_device_id *id_table; |
| 569 | 562 | ||
| 563 | struct list_head dyn_list; | ||
| 564 | spinlock_t dyn_lock; | ||
| 565 | |||
| 570 | int (*probe)(struct hid_device *dev, const struct hid_device_id *id); | 566 | int (*probe)(struct hid_device *dev, const struct hid_device_id *id); |
| 571 | void (*remove)(struct hid_device *dev); | 567 | void (*remove)(struct hid_device *dev); |
| 572 | 568 | ||
| @@ -797,6 +793,8 @@ dbg_hid(const char *fmt, ...) | |||
| 797 | 793 | ||
| 798 | #ifdef CONFIG_HID_COMPAT | 794 | #ifdef CONFIG_HID_COMPAT |
| 799 | #define HID_COMPAT_LOAD_DRIVER(name) \ | 795 | #define HID_COMPAT_LOAD_DRIVER(name) \ |
| 796 | /* prototype to avoid sparse warning */ \ | ||
| 797 | extern void hid_compat_##name(void); \ | ||
| 800 | void hid_compat_##name(void) { } \ | 798 | void hid_compat_##name(void) { } \ |
| 801 | EXPORT_SYMBOL(hid_compat_##name) | 799 | EXPORT_SYMBOL(hid_compat_##name) |
| 802 | #else | 800 | #else |
diff --git a/include/linux/hidraw.h b/include/linux/hidraw.h index dbb5c8c374f0..dd8d69269176 100644 --- a/include/linux/hidraw.h +++ b/include/linux/hidraw.h | |||
| @@ -33,6 +33,8 @@ struct hidraw_devinfo { | |||
| 33 | #define HIDIOCGRDESCSIZE _IOR('H', 0x01, int) | 33 | #define HIDIOCGRDESCSIZE _IOR('H', 0x01, int) |
| 34 | #define HIDIOCGRDESC _IOR('H', 0x02, struct hidraw_report_descriptor) | 34 | #define HIDIOCGRDESC _IOR('H', 0x02, struct hidraw_report_descriptor) |
| 35 | #define HIDIOCGRAWINFO _IOR('H', 0x03, struct hidraw_devinfo) | 35 | #define HIDIOCGRAWINFO _IOR('H', 0x03, struct hidraw_devinfo) |
| 36 | #define HIDIOCGRAWNAME(len) _IOC(_IOC_READ, 'H', 0x04, len) | ||
| 37 | #define HIDIOCGRAWPHYS(len) _IOC(_IOC_READ, 'H', 0x05, len) | ||
| 36 | 38 | ||
| 37 | #define HIDRAW_FIRST_MINOR 0 | 39 | #define HIDRAW_FIRST_MINOR 0 |
| 38 | #define HIDRAW_MAX_DEVICES 64 | 40 | #define HIDRAW_MAX_DEVICES 64 |
