diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-03 18:25:44 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-03 18:25:44 -0400 |
commit | 5fba0925fd6b67d94181055b7222e3d934b4efee (patch) | |
tree | 167c0e259ec94f426674d3f79563c3e556cda845 /drivers/hid | |
parent | 811158b147a503fbdf9773224004ffd32002d1fe (diff) | |
parent | 621de593081524da2f0f7b060f5951b4155eb4a2 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid:
HID: remove compat stuff
HID: constify arrays of struct apple_key_translation
HID: add support for Kye/Genius Ergo 525V
HID: Support Apple mini aluminum keyboard
HID: support for Kensington slimblade device
HID: DragonRise game controller force feedback driver
HID: add support for another version of 0e8f:0003 device in hid-pl
HID: fix race between usb_register_dev() and hiddev_open()
HID: bring back possibility to specify vid/pid ignore on module load
HID: make HID_DEBUG defaults consistent
HID: autosuspend -- fix lockup of hid on reset
HID: hid_reset_resume() needs to be defined only when CONFIG_PM is set
HID: fix USB HID devices after STD with autosuspend
HID: do not try to compile PM code with CONFIG_PM unset
HID: autosuspend support for USB HID
Diffstat (limited to 'drivers/hid')
33 files changed, 844 insertions, 292 deletions
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 504cfaa6160f..7e67dcb3d4f6 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig | |||
@@ -29,11 +29,11 @@ config HID | |||
29 | 29 | ||
30 | For docs and specs, see http://www.usb.org/developers/hidpage/ | 30 | For docs and specs, see http://www.usb.org/developers/hidpage/ |
31 | 31 | ||
32 | If unsure, say Y | 32 | If unsure, say Y. |
33 | 33 | ||
34 | config HID_DEBUG | 34 | config HID_DEBUG |
35 | bool "HID debugging support" | 35 | bool "HID debugging support" |
36 | default y if !EMBEDDED | 36 | default y |
37 | depends on HID | 37 | depends on HID |
38 | ---help--- | 38 | ---help--- |
39 | This option lets the HID layer output diagnostics about its internal | 39 | This option lets the HID layer output diagnostics about its internal |
@@ -44,7 +44,7 @@ config HID_DEBUG | |||
44 | This feature is useful for those who are either debugging the HID parser | 44 | This feature is useful for those who are either debugging the HID parser |
45 | or any HID hardware device. | 45 | or any HID hardware device. |
46 | 46 | ||
47 | If unsure, say N | 47 | If unsure, say Y. |
48 | 48 | ||
49 | config HIDRAW | 49 | config HIDRAW |
50 | bool "/dev/hidraw raw HID device support" | 50 | bool "/dev/hidraw raw HID device support" |
@@ -70,18 +70,6 @@ source "drivers/hid/usbhid/Kconfig" | |||
70 | menu "Special HID drivers" | 70 | menu "Special HID drivers" |
71 | depends on HID | 71 | depends on HID |
72 | 72 | ||
73 | config HID_COMPAT | ||
74 | bool "Load all HID drivers on hid core load" | ||
75 | default y | ||
76 | ---help--- | ||
77 | Compatible option for older userspace. If you have system without udev | ||
78 | support of module loading through aliases and also old | ||
79 | module-init-tools which can't handle hid bus, choose Y here. Otherwise | ||
80 | say N. If you say N and your userspace is old enough, the only | ||
81 | functionality you lose is modules autoloading. | ||
82 | |||
83 | If unsure, say Y. | ||
84 | |||
85 | config HID_A4TECH | 73 | config HID_A4TECH |
86 | tristate "A4 tech" if EMBEDDED | 74 | tristate "A4 tech" if EMBEDDED |
87 | depends on USB_HID | 75 | depends on USB_HID |
@@ -128,6 +116,14 @@ config HID_CYPRESS | |||
128 | ---help--- | 116 | ---help--- |
129 | Support for cypress mouse and barcode readers. | 117 | Support for cypress mouse and barcode readers. |
130 | 118 | ||
119 | config DRAGONRISE_FF | ||
120 | tristate "DragonRise Inc. force feedback support" | ||
121 | depends on USB_HID | ||
122 | select INPUT_FF_MEMLESS | ||
123 | ---help--- | ||
124 | Say Y here if you want to enable force feedback support for DragonRise Inc. | ||
125 | game controllers. | ||
126 | |||
131 | config HID_EZKEY | 127 | config HID_EZKEY |
132 | tristate "Ezkey" if EMBEDDED | 128 | tristate "Ezkey" if EMBEDDED |
133 | depends on USB_HID | 129 | depends on USB_HID |
@@ -135,6 +131,13 @@ config HID_EZKEY | |||
135 | ---help--- | 131 | ---help--- |
136 | Support for Ezkey BTC 8193 keyboard. | 132 | Support for Ezkey BTC 8193 keyboard. |
137 | 133 | ||
134 | config HID_KYE | ||
135 | tristate "Kye" if EMBEDDED | ||
136 | depends on USB_HID | ||
137 | default !EMBEDDED | ||
138 | ---help--- | ||
139 | Support for Kye/Genius Ergo Mouse. | ||
140 | |||
138 | config HID_GYRATION | 141 | config HID_GYRATION |
139 | tristate "Gyration" if EMBEDDED | 142 | tristate "Gyration" if EMBEDDED |
140 | depends on USB_HID | 143 | depends on USB_HID |
@@ -142,6 +145,13 @@ config HID_GYRATION | |||
142 | ---help--- | 145 | ---help--- |
143 | Support for Gyration remote control. | 146 | Support for Gyration remote control. |
144 | 147 | ||
148 | config HID_KENSINGTON | ||
149 | tristate "Kensington" if EMBEDDED | ||
150 | depends on USB_HID | ||
151 | default !EMBEDDED | ||
152 | ---help--- | ||
153 | Support for Kensington Slimblade Trackball. | ||
154 | |||
145 | config HID_LOGITECH | 155 | config HID_LOGITECH |
146 | tristate "Logitech" if EMBEDDED | 156 | tristate "Logitech" if EMBEDDED |
147 | depends on USB_HID | 157 | depends on USB_HID |
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index fbd021f153f1..1f7cb0fd4505 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile | |||
@@ -8,10 +8,6 @@ obj-$(CONFIG_HID) += hid.o | |||
8 | hid-$(CONFIG_HID_DEBUG) += hid-debug.o | 8 | hid-$(CONFIG_HID_DEBUG) += hid-debug.o |
9 | hid-$(CONFIG_HIDRAW) += hidraw.o | 9 | hid-$(CONFIG_HIDRAW) += hidraw.o |
10 | 10 | ||
11 | ifdef CONFIG_HID_COMPAT | ||
12 | obj-m += hid-dummy.o | ||
13 | endif | ||
14 | |||
15 | hid-logitech-objs := hid-lg.o | 11 | hid-logitech-objs := hid-lg.o |
16 | ifdef CONFIG_LOGITECH_FF | 12 | ifdef CONFIG_LOGITECH_FF |
17 | hid-logitech-objs += hid-lgff.o | 13 | hid-logitech-objs += hid-lgff.o |
@@ -26,8 +22,11 @@ obj-$(CONFIG_HID_BELKIN) += hid-belkin.o | |||
26 | obj-$(CONFIG_HID_CHERRY) += hid-cherry.o | 22 | obj-$(CONFIG_HID_CHERRY) += hid-cherry.o |
27 | obj-$(CONFIG_HID_CHICONY) += hid-chicony.o | 23 | obj-$(CONFIG_HID_CHICONY) += hid-chicony.o |
28 | obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o | 24 | obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o |
25 | obj-$(CONFIG_DRAGONRISE_FF) += hid-drff.o | ||
29 | obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o | 26 | obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o |
30 | obj-$(CONFIG_HID_GYRATION) += hid-gyration.o | 27 | obj-$(CONFIG_HID_GYRATION) += hid-gyration.o |
28 | obj-$(CONFIG_HID_KENSINGTON) += hid-kensington.o | ||
29 | obj-$(CONFIG_HID_KYE) += hid-kye.o | ||
31 | obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o | 30 | obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o |
32 | obj-$(CONFIG_HID_MICROSOFT) += hid-microsoft.o | 31 | obj-$(CONFIG_HID_MICROSOFT) += hid-microsoft.o |
33 | obj-$(CONFIG_HID_MONTEREY) += hid-monterey.o | 32 | obj-$(CONFIG_HID_MONTEREY) += hid-monterey.o |
diff --git a/drivers/hid/hid-a4tech.c b/drivers/hid/hid-a4tech.c index ebca00e6c103..42ea359e94cf 100644 --- a/drivers/hid/hid-a4tech.c +++ b/drivers/hid/hid-a4tech.c | |||
@@ -158,5 +158,3 @@ static void a4_exit(void) | |||
158 | module_init(a4_init); | 158 | module_init(a4_init); |
159 | module_exit(a4_exit); | 159 | module_exit(a4_exit); |
160 | MODULE_LICENSE("GPL"); | 160 | MODULE_LICENSE("GPL"); |
161 | |||
162 | HID_COMPAT_LOAD_DRIVER(a4tech); | ||
diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index aa28aed0e46c..7359d9d88e46 100644 --- a/drivers/hid/hid-apple.c +++ b/drivers/hid/hid-apple.c | |||
@@ -53,7 +53,7 @@ struct apple_key_translation { | |||
53 | u8 flags; | 53 | u8 flags; |
54 | }; | 54 | }; |
55 | 55 | ||
56 | static struct apple_key_translation apple_fn_keys[] = { | 56 | static const struct apple_key_translation apple_fn_keys[] = { |
57 | { KEY_BACKSPACE, KEY_DELETE }, | 57 | { KEY_BACKSPACE, KEY_DELETE }, |
58 | { KEY_ENTER, KEY_INSERT }, | 58 | { KEY_ENTER, KEY_INSERT }, |
59 | { KEY_F1, KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY }, | 59 | { KEY_F1, KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY }, |
@@ -75,7 +75,7 @@ static struct apple_key_translation apple_fn_keys[] = { | |||
75 | { } | 75 | { } |
76 | }; | 76 | }; |
77 | 77 | ||
78 | static struct apple_key_translation powerbook_fn_keys[] = { | 78 | static const struct apple_key_translation powerbook_fn_keys[] = { |
79 | { KEY_BACKSPACE, KEY_DELETE }, | 79 | { KEY_BACKSPACE, KEY_DELETE }, |
80 | { KEY_F1, KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY }, | 80 | { KEY_F1, KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY }, |
81 | { KEY_F2, KEY_BRIGHTNESSUP, APPLE_FLAG_FKEY }, | 81 | { KEY_F2, KEY_BRIGHTNESSUP, APPLE_FLAG_FKEY }, |
@@ -94,7 +94,7 @@ static struct apple_key_translation powerbook_fn_keys[] = { | |||
94 | { } | 94 | { } |
95 | }; | 95 | }; |
96 | 96 | ||
97 | static struct apple_key_translation powerbook_numlock_keys[] = { | 97 | static const struct apple_key_translation powerbook_numlock_keys[] = { |
98 | { KEY_J, KEY_KP1 }, | 98 | { KEY_J, KEY_KP1 }, |
99 | { KEY_K, KEY_KP2 }, | 99 | { KEY_K, KEY_KP2 }, |
100 | { KEY_L, KEY_KP3 }, | 100 | { KEY_L, KEY_KP3 }, |
@@ -117,16 +117,16 @@ static struct apple_key_translation powerbook_numlock_keys[] = { | |||
117 | { } | 117 | { } |
118 | }; | 118 | }; |
119 | 119 | ||
120 | static struct apple_key_translation apple_iso_keyboard[] = { | 120 | static const struct apple_key_translation apple_iso_keyboard[] = { |
121 | { KEY_GRAVE, KEY_102ND }, | 121 | { KEY_GRAVE, KEY_102ND }, |
122 | { KEY_102ND, KEY_GRAVE }, | 122 | { KEY_102ND, KEY_GRAVE }, |
123 | { } | 123 | { } |
124 | }; | 124 | }; |
125 | 125 | ||
126 | static struct apple_key_translation *apple_find_translation( | 126 | static const struct apple_key_translation *apple_find_translation( |
127 | struct apple_key_translation *table, u16 from) | 127 | const struct apple_key_translation *table, u16 from) |
128 | { | 128 | { |
129 | struct apple_key_translation *trans; | 129 | const struct apple_key_translation *trans; |
130 | 130 | ||
131 | /* Look for the translation */ | 131 | /* Look for the translation */ |
132 | for (trans = table; trans->from; trans++) | 132 | for (trans = table; trans->from; trans++) |
@@ -140,7 +140,7 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input, | |||
140 | struct hid_usage *usage, __s32 value) | 140 | struct hid_usage *usage, __s32 value) |
141 | { | 141 | { |
142 | struct apple_sc *asc = hid_get_drvdata(hid); | 142 | struct apple_sc *asc = hid_get_drvdata(hid); |
143 | struct apple_key_translation *trans; | 143 | const struct apple_key_translation *trans; |
144 | 144 | ||
145 | if (usage->code == KEY_FN) { | 145 | if (usage->code == KEY_FN) { |
146 | asc->fn_on = !!value; | 146 | asc->fn_on = !!value; |
@@ -253,7 +253,7 @@ static void apple_report_fixup(struct hid_device *hdev, __u8 *rdesc, | |||
253 | 253 | ||
254 | static void apple_setup_input(struct input_dev *input) | 254 | static void apple_setup_input(struct input_dev *input) |
255 | { | 255 | { |
256 | struct apple_key_translation *trans; | 256 | const struct apple_key_translation *trans; |
257 | 257 | ||
258 | set_bit(KEY_NUMLOCK, input->keybit); | 258 | set_bit(KEY_NUMLOCK, input->keybit); |
259 | 259 | ||
@@ -387,6 +387,12 @@ static const struct hid_device_id apple_devices[] = { | |||
387 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS), | 387 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS), |
388 | .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN | | 388 | .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN | |
389 | APPLE_RDESC_JIS }, | 389 | APPLE_RDESC_JIS }, |
390 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_MINI_ANSI), | ||
391 | .driver_data = APPLE_HAS_FN }, | ||
392 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_MINI_ISO), | ||
393 | .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, | ||
394 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_MINI_JIS), | ||
395 | .driver_data = APPLE_HAS_FN }, | ||
390 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ANSI), | 396 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ANSI), |
391 | .driver_data = APPLE_HAS_FN }, | 397 | .driver_data = APPLE_HAS_FN }, |
392 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ISO), | 398 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ISO), |
@@ -468,5 +474,3 @@ static void apple_exit(void) | |||
468 | module_init(apple_init); | 474 | module_init(apple_init); |
469 | module_exit(apple_exit); | 475 | module_exit(apple_exit); |
470 | MODULE_LICENSE("GPL"); | 476 | MODULE_LICENSE("GPL"); |
471 | |||
472 | HID_COMPAT_LOAD_DRIVER(apple); | ||
diff --git a/drivers/hid/hid-belkin.c b/drivers/hid/hid-belkin.c index 12c8a9ba6ed6..2f6723133a4b 100644 --- a/drivers/hid/hid-belkin.c +++ b/drivers/hid/hid-belkin.c | |||
@@ -101,5 +101,3 @@ static void belkin_exit(void) | |||
101 | module_init(belkin_init); | 101 | module_init(belkin_init); |
102 | module_exit(belkin_exit); | 102 | module_exit(belkin_exit); |
103 | MODULE_LICENSE("GPL"); | 103 | MODULE_LICENSE("GPL"); |
104 | |||
105 | HID_COMPAT_LOAD_DRIVER(belkin); | ||
diff --git a/drivers/hid/hid-cherry.c b/drivers/hid/hid-cherry.c index b833b9769aba..ab8209e7e45c 100644 --- a/drivers/hid/hid-cherry.c +++ b/drivers/hid/hid-cherry.c | |||
@@ -83,5 +83,3 @@ static void ch_exit(void) | |||
83 | module_init(ch_init); | 83 | module_init(ch_init); |
84 | module_exit(ch_exit); | 84 | module_exit(ch_exit); |
85 | MODULE_LICENSE("GPL"); | 85 | MODULE_LICENSE("GPL"); |
86 | |||
87 | HID_COMPAT_LOAD_DRIVER(cherry); | ||
diff --git a/drivers/hid/hid-chicony.c b/drivers/hid/hid-chicony.c index a54d4096e0f7..7f91076d8493 100644 --- a/drivers/hid/hid-chicony.c +++ b/drivers/hid/hid-chicony.c | |||
@@ -76,5 +76,3 @@ static void ch_exit(void) | |||
76 | module_init(ch_init); | 76 | module_init(ch_init); |
77 | module_exit(ch_exit); | 77 | module_exit(ch_exit); |
78 | MODULE_LICENSE("GPL"); | 78 | MODULE_LICENSE("GPL"); |
79 | |||
80 | HID_COMPAT_LOAD_DRIVER(chicony); | ||
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 1cc967448f4d..5746a5903bce 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
@@ -1236,6 +1236,9 @@ static const struct hid_device_id hid_blacklist[] = { | |||
1236 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI) }, | 1236 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI) }, |
1237 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO) }, | 1237 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO) }, |
1238 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS) }, | 1238 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS) }, |
1239 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_MINI_ANSI) }, | ||
1240 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_MINI_ISO) }, | ||
1241 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_MINI_JIS) }, | ||
1239 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ANSI) }, | 1242 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ANSI) }, |
1240 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ISO) }, | 1243 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ISO) }, |
1241 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_JIS) }, | 1244 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_JIS) }, |
@@ -1262,6 +1265,7 @@ static const struct hid_device_id hid_blacklist[] = { | |||
1262 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) }, | 1265 | { 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) }, | 1266 | { 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) }, | 1267 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE) }, |
1268 | { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) }, | ||
1265 | { HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) }, | 1269 | { HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) }, |
1266 | { 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_PSX_ADAPTOR) }, |
1267 | { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR) }, | 1271 | { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR) }, |
@@ -1269,6 +1273,8 @@ static const struct hid_device_id hid_blacklist[] = { | |||
1269 | { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0012) }, | 1273 | { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0012) }, |
1270 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) }, | 1274 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) }, |
1271 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) }, | 1275 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) }, |
1276 | { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) }, | ||
1277 | { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) }, | ||
1272 | { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) }, | 1278 | { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) }, |
1273 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) }, | 1279 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) }, |
1274 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) }, | 1280 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) }, |
@@ -1813,14 +1819,21 @@ void hid_unregister_driver(struct hid_driver *hdrv) | |||
1813 | } | 1819 | } |
1814 | EXPORT_SYMBOL_GPL(hid_unregister_driver); | 1820 | EXPORT_SYMBOL_GPL(hid_unregister_driver); |
1815 | 1821 | ||
1816 | #ifdef CONFIG_HID_COMPAT | 1822 | int hid_check_keys_pressed(struct hid_device *hid) |
1817 | static void hid_compat_load(struct work_struct *ws) | ||
1818 | { | 1823 | { |
1819 | request_module("hid-dummy"); | 1824 | struct hid_input *hidinput; |
1825 | int i; | ||
1826 | |||
1827 | list_for_each_entry(hidinput, &hid->inputs, list) { | ||
1828 | for (i = 0; i < BITS_TO_LONGS(KEY_MAX); i++) | ||
1829 | if (hidinput->input->key[i]) | ||
1830 | return 1; | ||
1831 | } | ||
1832 | |||
1833 | return 0; | ||
1820 | } | 1834 | } |
1821 | static DECLARE_WORK(hid_compat_work, hid_compat_load); | 1835 | |
1822 | static struct workqueue_struct *hid_compat_wq; | 1836 | EXPORT_SYMBOL_GPL(hid_check_keys_pressed); |
1823 | #endif | ||
1824 | 1837 | ||
1825 | static int __init hid_init(void) | 1838 | static int __init hid_init(void) |
1826 | { | 1839 | { |
@@ -1836,15 +1849,6 @@ static int __init hid_init(void) | |||
1836 | if (ret) | 1849 | if (ret) |
1837 | goto err_bus; | 1850 | goto err_bus; |
1838 | 1851 | ||
1839 | #ifdef CONFIG_HID_COMPAT | ||
1840 | hid_compat_wq = create_singlethread_workqueue("hid_compat"); | ||
1841 | if (!hid_compat_wq) { | ||
1842 | hidraw_exit(); | ||
1843 | goto err; | ||
1844 | } | ||
1845 | queue_work(hid_compat_wq, &hid_compat_work); | ||
1846 | #endif | ||
1847 | |||
1848 | return 0; | 1852 | return 0; |
1849 | err_bus: | 1853 | err_bus: |
1850 | bus_unregister(&hid_bus_type); | 1854 | bus_unregister(&hid_bus_type); |
@@ -1854,9 +1858,6 @@ err: | |||
1854 | 1858 | ||
1855 | static void __exit hid_exit(void) | 1859 | static void __exit hid_exit(void) |
1856 | { | 1860 | { |
1857 | #ifdef CONFIG_HID_COMPAT | ||
1858 | destroy_workqueue(hid_compat_wq); | ||
1859 | #endif | ||
1860 | hidraw_exit(); | 1861 | hidraw_exit(); |
1861 | bus_unregister(&hid_bus_type); | 1862 | bus_unregister(&hid_bus_type); |
1862 | } | 1863 | } |
diff --git a/drivers/hid/hid-cypress.c b/drivers/hid/hid-cypress.c index 5d69d27b935d..9d6d3b91773b 100644 --- a/drivers/hid/hid-cypress.c +++ b/drivers/hid/hid-cypress.c | |||
@@ -154,5 +154,3 @@ static void cp_exit(void) | |||
154 | module_init(cp_init); | 154 | module_init(cp_init); |
155 | module_exit(cp_exit); | 155 | module_exit(cp_exit); |
156 | MODULE_LICENSE("GPL"); | 156 | MODULE_LICENSE("GPL"); |
157 | |||
158 | HID_COMPAT_LOAD_DRIVER(cypress); | ||
diff --git a/drivers/hid/hid-drff.c b/drivers/hid/hid-drff.c new file mode 100644 index 000000000000..34f3eb65100b --- /dev/null +++ b/drivers/hid/hid-drff.c | |||
@@ -0,0 +1,188 @@ | |||
1 | /* | ||
2 | * Force feedback support for DragonRise Inc. game controllers | ||
3 | * | ||
4 | * From what I have gathered, these devices are mass produced in China and are | ||
5 | * distributed under several vendors. They often share the same design as | ||
6 | * the original PlayStation DualShock controller. | ||
7 | * | ||
8 | * 0079:0006 "DragonRise Inc. Generic USB Joystick " | ||
9 | * - tested with a Tesun USB-703 game controller. | ||
10 | * | ||
11 | * Copyright (c) 2009 Richard Walmsley <richwalm@gmail.com> | ||
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 | |||
34 | #include "hid-ids.h" | ||
35 | #include "usbhid/usbhid.h" | ||
36 | |||
37 | struct drff_device { | ||
38 | struct hid_report *report; | ||
39 | }; | ||
40 | |||
41 | static int drff_play(struct input_dev *dev, void *data, | ||
42 | struct ff_effect *effect) | ||
43 | { | ||
44 | struct hid_device *hid = input_get_drvdata(dev); | ||
45 | struct drff_device *drff = data; | ||
46 | int strong, weak; | ||
47 | |||
48 | strong = effect->u.rumble.strong_magnitude; | ||
49 | weak = effect->u.rumble.weak_magnitude; | ||
50 | |||
51 | dbg_hid("called with 0x%04x 0x%04x", strong, weak); | ||
52 | |||
53 | if (strong || weak) { | ||
54 | strong = strong * 0xff / 0xffff; | ||
55 | weak = weak * 0xff / 0xffff; | ||
56 | |||
57 | /* While reverse engineering this device, I found that when | ||
58 | this value is set, it causes the strong rumble to function | ||
59 | at a near maximum speed, so we'll bypass it. */ | ||
60 | if (weak == 0x0a) | ||
61 | weak = 0x0b; | ||
62 | |||
63 | drff->report->field[0]->value[0] = 0x51; | ||
64 | drff->report->field[0]->value[1] = 0x00; | ||
65 | drff->report->field[0]->value[2] = weak; | ||
66 | drff->report->field[0]->value[4] = strong; | ||
67 | usbhid_submit_report(hid, drff->report, USB_DIR_OUT); | ||
68 | |||
69 | drff->report->field[0]->value[0] = 0xfa; | ||
70 | drff->report->field[0]->value[1] = 0xfe; | ||
71 | } else { | ||
72 | drff->report->field[0]->value[0] = 0xf3; | ||
73 | drff->report->field[0]->value[1] = 0x00; | ||
74 | } | ||
75 | |||
76 | drff->report->field[0]->value[2] = 0x00; | ||
77 | drff->report->field[0]->value[4] = 0x00; | ||
78 | dbg_hid("running with 0x%02x 0x%02x", strong, weak); | ||
79 | usbhid_submit_report(hid, drff->report, USB_DIR_OUT); | ||
80 | |||
81 | return 0; | ||
82 | } | ||
83 | |||
84 | static int drff_init(struct hid_device *hid) | ||
85 | { | ||
86 | struct drff_device *drff; | ||
87 | struct hid_report *report; | ||
88 | struct hid_input *hidinput = list_first_entry(&hid->inputs, | ||
89 | struct hid_input, list); | ||
90 | struct list_head *report_list = | ||
91 | &hid->report_enum[HID_OUTPUT_REPORT].report_list; | ||
92 | struct input_dev *dev = hidinput->input; | ||
93 | int error; | ||
94 | |||
95 | if (list_empty(report_list)) { | ||
96 | dev_err(&hid->dev, "no output reports found\n"); | ||
97 | return -ENODEV; | ||
98 | } | ||
99 | |||
100 | report = list_first_entry(report_list, struct hid_report, list); | ||
101 | if (report->maxfield < 1) { | ||
102 | dev_err(&hid->dev, "no fields in the report\n"); | ||
103 | return -ENODEV; | ||
104 | } | ||
105 | |||
106 | if (report->field[0]->report_count < 7) { | ||
107 | dev_err(&hid->dev, "not enough values in the field\n"); | ||
108 | return -ENODEV; | ||
109 | } | ||
110 | |||
111 | drff = kzalloc(sizeof(struct drff_device), GFP_KERNEL); | ||
112 | if (!drff) | ||
113 | return -ENOMEM; | ||
114 | |||
115 | set_bit(FF_RUMBLE, dev->ffbit); | ||
116 | |||
117 | error = input_ff_create_memless(dev, drff, drff_play); | ||
118 | if (error) { | ||
119 | kfree(drff); | ||
120 | return error; | ||
121 | } | ||
122 | |||
123 | drff->report = report; | ||
124 | drff->report->field[0]->value[0] = 0xf3; | ||
125 | drff->report->field[0]->value[1] = 0x00; | ||
126 | drff->report->field[0]->value[2] = 0x00; | ||
127 | drff->report->field[0]->value[3] = 0x00; | ||
128 | drff->report->field[0]->value[4] = 0x00; | ||
129 | drff->report->field[0]->value[5] = 0x00; | ||
130 | drff->report->field[0]->value[6] = 0x00; | ||
131 | usbhid_submit_report(hid, drff->report, USB_DIR_OUT); | ||
132 | |||
133 | dev_info(&hid->dev, "Force Feedback for DragonRise Inc. game " | ||
134 | "controllers by Richard Walmsley <richwalm@gmail.com>\n"); | ||
135 | |||
136 | return 0; | ||
137 | } | ||
138 | |||
139 | static int dr_probe(struct hid_device *hdev, const struct hid_device_id *id) | ||
140 | { | ||
141 | int ret; | ||
142 | |||
143 | dev_dbg(&hdev->dev, "DragonRise Inc. HID hardware probe..."); | ||
144 | |||
145 | ret = hid_parse(hdev); | ||
146 | if (ret) { | ||
147 | dev_err(&hdev->dev, "parse failed\n"); | ||
148 | goto err; | ||
149 | } | ||
150 | |||
151 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); | ||
152 | if (ret) { | ||
153 | dev_err(&hdev->dev, "hw start failed\n"); | ||
154 | goto err; | ||
155 | } | ||
156 | |||
157 | drff_init(hdev); | ||
158 | |||
159 | return 0; | ||
160 | err: | ||
161 | return ret; | ||
162 | } | ||
163 | |||
164 | static const struct hid_device_id dr_devices[] = { | ||
165 | { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006), }, | ||
166 | { } | ||
167 | }; | ||
168 | MODULE_DEVICE_TABLE(hid, dr_devices); | ||
169 | |||
170 | static struct hid_driver dr_driver = { | ||
171 | .name = "dragonrise", | ||
172 | .id_table = dr_devices, | ||
173 | .probe = dr_probe, | ||
174 | }; | ||
175 | |||
176 | static int __init dr_init(void) | ||
177 | { | ||
178 | return hid_register_driver(&dr_driver); | ||
179 | } | ||
180 | |||
181 | static void __exit dr_exit(void) | ||
182 | { | ||
183 | hid_unregister_driver(&dr_driver); | ||
184 | } | ||
185 | |||
186 | module_init(dr_init); | ||
187 | module_exit(dr_exit); | ||
188 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/hid/hid-dummy.c b/drivers/hid/hid-dummy.c deleted file mode 100644 index b4cc0f743d63..000000000000 --- a/drivers/hid/hid-dummy.c +++ /dev/null | |||
@@ -1,78 +0,0 @@ | |||
1 | #include <linux/autoconf.h> | ||
2 | #include <linux/module.h> | ||
3 | #include <linux/hid.h> | ||
4 | |||
5 | static int __init hid_dummy_init(void) | ||
6 | { | ||
7 | #ifdef CONFIG_HID_A4TECH_MODULE | ||
8 | HID_COMPAT_CALL_DRIVER(a4tech); | ||
9 | #endif | ||
10 | #ifdef CONFIG_HID_APPLE_MODULE | ||
11 | HID_COMPAT_CALL_DRIVER(apple); | ||
12 | #endif | ||
13 | #ifdef CONFIG_HID_BELKIN_MODULE | ||
14 | HID_COMPAT_CALL_DRIVER(belkin); | ||
15 | #endif | ||
16 | #ifdef CONFIG_HID_BRIGHT_MODULE | ||
17 | HID_COMPAT_CALL_DRIVER(bright); | ||
18 | #endif | ||
19 | #ifdef CONFIG_HID_CHERRY_MODULE | ||
20 | HID_COMPAT_CALL_DRIVER(cherry); | ||
21 | #endif | ||
22 | #ifdef CONFIG_HID_CHICONY_MODULE | ||
23 | HID_COMPAT_CALL_DRIVER(chicony); | ||
24 | #endif | ||
25 | #ifdef CONFIG_HID_CYPRESS_MODULE | ||
26 | HID_COMPAT_CALL_DRIVER(cypress); | ||
27 | #endif | ||
28 | #ifdef CONFIG_HID_DELL_MODULE | ||
29 | HID_COMPAT_CALL_DRIVER(dell); | ||
30 | #endif | ||
31 | #ifdef CONFIG_HID_EZKEY_MODULE | ||
32 | HID_COMPAT_CALL_DRIVER(ezkey); | ||
33 | #endif | ||
34 | #ifdef CONFIG_HID_GYRATION_MODULE | ||
35 | HID_COMPAT_CALL_DRIVER(gyration); | ||
36 | #endif | ||
37 | #ifdef CONFIG_HID_LOGITECH_MODULE | ||
38 | HID_COMPAT_CALL_DRIVER(logitech); | ||
39 | #endif | ||
40 | #ifdef CONFIG_HID_MICROSOFT_MODULE | ||
41 | HID_COMPAT_CALL_DRIVER(microsoft); | ||
42 | #endif | ||
43 | #ifdef CONFIG_HID_MONTEREY_MODULE | ||
44 | HID_COMPAT_CALL_DRIVER(monterey); | ||
45 | #endif | ||
46 | #ifdef CONFIG_HID_NTRIG_MODULE | ||
47 | HID_COMPAT_CALL_DRIVER(ntrig); | ||
48 | #endif | ||
49 | #ifdef CONFIG_HID_PANTHERLORD_MODULE | ||
50 | HID_COMPAT_CALL_DRIVER(pantherlord); | ||
51 | #endif | ||
52 | #ifdef CONFIG_HID_PETALYNX_MODULE | ||
53 | HID_COMPAT_CALL_DRIVER(petalynx); | ||
54 | #endif | ||
55 | #ifdef CONFIG_HID_SAMSUNG_MODULE | ||
56 | HID_COMPAT_CALL_DRIVER(samsung); | ||
57 | #endif | ||
58 | #ifdef CONFIG_HID_SONY_MODULE | ||
59 | HID_COMPAT_CALL_DRIVER(sony); | ||
60 | #endif | ||
61 | #ifdef CONFIG_HID_SUNPLUS_MODULE | ||
62 | HID_COMPAT_CALL_DRIVER(sunplus); | ||
63 | #endif | ||
64 | #ifdef CONFIG_GREENASIA_FF_MODULE | ||
65 | HID_COMPAT_CALL_DRIVER(greenasia); | ||
66 | #endif | ||
67 | #ifdef CONFIG_THRUSTMASTER_FF_MODULE | ||
68 | HID_COMPAT_CALL_DRIVER(thrustmaster); | ||
69 | #endif | ||
70 | #ifdef CONFIG_ZEROPLUS_FF_MODULE | ||
71 | HID_COMPAT_CALL_DRIVER(zeroplus); | ||
72 | #endif | ||
73 | |||
74 | return -EIO; | ||
75 | } | ||
76 | module_init(hid_dummy_init); | ||
77 | |||
78 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/hid/hid-ezkey.c b/drivers/hid/hid-ezkey.c index deb42f931b7e..0a1fe054799b 100644 --- a/drivers/hid/hid-ezkey.c +++ b/drivers/hid/hid-ezkey.c | |||
@@ -91,5 +91,3 @@ static void ez_exit(void) | |||
91 | module_init(ez_init); | 91 | module_init(ez_init); |
92 | module_exit(ez_exit); | 92 | module_exit(ez_exit); |
93 | MODULE_LICENSE("GPL"); | 93 | MODULE_LICENSE("GPL"); |
94 | |||
95 | HID_COMPAT_LOAD_DRIVER(ezkey); | ||
diff --git a/drivers/hid/hid-gaff.c b/drivers/hid/hid-gaff.c index 71211f6a4f02..510ad3ab8d33 100644 --- a/drivers/hid/hid-gaff.c +++ b/drivers/hid/hid-gaff.c | |||
@@ -181,5 +181,3 @@ static void __exit ga_exit(void) | |||
181 | module_init(ga_init); | 181 | module_init(ga_init); |
182 | module_exit(ga_exit); | 182 | module_exit(ga_exit); |
183 | MODULE_LICENSE("GPL"); | 183 | MODULE_LICENSE("GPL"); |
184 | |||
185 | HID_COMPAT_LOAD_DRIVER(greenasia); | ||
diff --git a/drivers/hid/hid-gyration.c b/drivers/hid/hid-gyration.c index 04a0afec52ac..d42d222097a8 100644 --- a/drivers/hid/hid-gyration.c +++ b/drivers/hid/hid-gyration.c | |||
@@ -94,5 +94,3 @@ static void gyration_exit(void) | |||
94 | module_init(gyration_init); | 94 | module_init(gyration_init); |
95 | module_exit(gyration_exit); | 95 | module_exit(gyration_exit); |
96 | MODULE_LICENSE("GPL"); | 96 | MODULE_LICENSE("GPL"); |
97 | |||
98 | HID_COMPAT_LOAD_DRIVER(gyration); | ||
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 88511970508d..bdeda4c7cc13 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h | |||
@@ -67,6 +67,9 @@ | |||
67 | #define USB_DEVICE_ID_APPLE_GEYSER4_ANSI 0x021a | 67 | #define USB_DEVICE_ID_APPLE_GEYSER4_ANSI 0x021a |
68 | #define USB_DEVICE_ID_APPLE_GEYSER4_ISO 0x021b | 68 | #define USB_DEVICE_ID_APPLE_GEYSER4_ISO 0x021b |
69 | #define USB_DEVICE_ID_APPLE_GEYSER4_JIS 0x021c | 69 | #define USB_DEVICE_ID_APPLE_GEYSER4_JIS 0x021c |
70 | #define USB_DEVICE_ID_APPLE_ALU_MINI_ANSI 0x021d | ||
71 | #define USB_DEVICE_ID_APPLE_ALU_MINI_ISO 0x021e | ||
72 | #define USB_DEVICE_ID_APPLE_ALU_MINI_JIS 0x021f | ||
70 | #define USB_DEVICE_ID_APPLE_ALU_ANSI 0x0220 | 73 | #define USB_DEVICE_ID_APPLE_ALU_ANSI 0x0220 |
71 | #define USB_DEVICE_ID_APPLE_ALU_ISO 0x0221 | 74 | #define USB_DEVICE_ID_APPLE_ALU_ISO 0x0221 |
72 | #define USB_DEVICE_ID_APPLE_ALU_JIS 0x0222 | 75 | #define USB_DEVICE_ID_APPLE_ALU_JIS 0x0222 |
@@ -148,6 +151,8 @@ | |||
148 | #define USB_VENDOR_ID_DMI 0x0c0b | 151 | #define USB_VENDOR_ID_DMI 0x0c0b |
149 | #define USB_DEVICE_ID_DMI_ENC 0x5fab | 152 | #define USB_DEVICE_ID_DMI_ENC 0x5fab |
150 | 153 | ||
154 | #define USB_VENDOR_ID_DRAGONRISE 0x0079 | ||
155 | |||
151 | #define USB_VENDOR_ID_ELO 0x04E7 | 156 | #define USB_VENDOR_ID_ELO 0x04E7 |
152 | #define USB_DEVICE_ID_ELO_TS2700 0x0020 | 157 | #define USB_DEVICE_ID_ELO_TS2700 0x0020 |
153 | 158 | ||
@@ -272,6 +277,9 @@ | |||
272 | #define USB_DEVICE_ID_LD_POWERCONTROL 0x2030 | 277 | #define USB_DEVICE_ID_LD_POWERCONTROL 0x2030 |
273 | #define USB_DEVICE_ID_LD_MACHINETEST 0x2040 | 278 | #define USB_DEVICE_ID_LD_MACHINETEST 0x2040 |
274 | 279 | ||
280 | #define USB_VENDOR_ID_KENSINGTON 0x047d | ||
281 | #define USB_DEVICE_ID_KS_SLIMBLADE 0x2041 | ||
282 | |||
275 | #define USB_VENDOR_ID_LOGITECH 0x046d | 283 | #define USB_VENDOR_ID_LOGITECH 0x046d |
276 | #define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101 | 284 | #define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101 |
277 | #define USB_DEVICE_ID_LOGITECH_HARMONY_FIRST 0xc110 | 285 | #define USB_DEVICE_ID_LOGITECH_HARMONY_FIRST 0xc110 |
@@ -418,6 +426,8 @@ | |||
418 | #define USB_VENDOR_ID_ZEROPLUS 0x0c12 | 426 | #define USB_VENDOR_ID_ZEROPLUS 0x0c12 |
419 | 427 | ||
420 | #define USB_VENDOR_ID_KYE 0x0458 | 428 | #define USB_VENDOR_ID_KYE 0x0458 |
429 | #define USB_DEVICE_ID_KYE_ERGO_525V 0x0087 | ||
421 | #define USB_DEVICE_ID_KYE_GPEN_560 0x5003 | 430 | #define USB_DEVICE_ID_KYE_GPEN_560 0x5003 |
422 | 431 | ||
432 | |||
423 | #endif | 433 | #endif |
diff --git a/drivers/hid/hid-kensington.c b/drivers/hid/hid-kensington.c new file mode 100644 index 000000000000..7353bd79cbe9 --- /dev/null +++ b/drivers/hid/hid-kensington.c | |||
@@ -0,0 +1,63 @@ | |||
1 | /* | ||
2 | * HID driver for Kensigton Slimblade Trackball | ||
3 | * | ||
4 | * Copyright (c) 2009 Jiri Kosina | ||
5 | */ | ||
6 | |||
7 | /* | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the Free | ||
10 | * Software Foundation; either version 2 of the License, or (at your option) | ||
11 | * any later version. | ||
12 | */ | ||
13 | |||
14 | #include <linux/device.h> | ||
15 | #include <linux/input.h> | ||
16 | #include <linux/hid.h> | ||
17 | #include <linux/module.h> | ||
18 | |||
19 | #include "hid-ids.h" | ||
20 | |||
21 | #define ks_map_key(c) hid_map_usage(hi, usage, bit, max, EV_KEY, (c)) | ||
22 | |||
23 | static int ks_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) != HID_UP_MSVENDOR) | ||
28 | return 0; | ||
29 | |||
30 | switch (usage->hid & HID_USAGE) { | ||
31 | case 0x01: ks_map_key(BTN_MIDDLE); break; | ||
32 | case 0x02: ks_map_key(BTN_SIDE); break; | ||
33 | default: | ||
34 | return 0; | ||
35 | } | ||
36 | return 1; | ||
37 | } | ||
38 | |||
39 | static const struct hid_device_id ks_devices[] = { | ||
40 | { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) }, | ||
41 | { } | ||
42 | }; | ||
43 | MODULE_DEVICE_TABLE(hid, ks_devices); | ||
44 | |||
45 | static struct hid_driver ks_driver = { | ||
46 | .name = "kensington", | ||
47 | .id_table = ks_devices, | ||
48 | .input_mapping = ks_input_mapping, | ||
49 | }; | ||
50 | |||
51 | static int ks_init(void) | ||
52 | { | ||
53 | return hid_register_driver(&ks_driver); | ||
54 | } | ||
55 | |||
56 | static void ks_exit(void) | ||
57 | { | ||
58 | hid_unregister_driver(&ks_driver); | ||
59 | } | ||
60 | |||
61 | module_init(ks_init); | ||
62 | module_exit(ks_exit); | ||
63 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/hid/hid-kye.c b/drivers/hid/hid-kye.c new file mode 100644 index 000000000000..72ee3fec56d9 --- /dev/null +++ b/drivers/hid/hid-kye.c | |||
@@ -0,0 +1,69 @@ | |||
1 | /* | ||
2 | * HID driver for Kye/Genius devices not fully compliant with HID standard | ||
3 | * | ||
4 | * Copyright (c) 2009 Jiri Kosina | ||
5 | * Copyright (c) 2009 Tomas Hanak | ||
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 | /* the fixups that need to be done: | ||
22 | * - change led usage page to button for extra buttons | ||
23 | * - report size 8 count 1 must be size 1 count 8 for button bitfield | ||
24 | * - change the button usage range to 4-7 for the extra buttons | ||
25 | */ | ||
26 | static void kye_report_fixup(struct hid_device *hdev, __u8 *rdesc, | ||
27 | unsigned int rsize) | ||
28 | { | ||
29 | if (rsize >= 74 && | ||
30 | rdesc[61] == 0x05 && rdesc[62] == 0x08 && | ||
31 | rdesc[63] == 0x19 && rdesc[64] == 0x08 && | ||
32 | rdesc[65] == 0x29 && rdesc[66] == 0x0f && | ||
33 | rdesc[71] == 0x75 && rdesc[72] == 0x08 && | ||
34 | rdesc[73] == 0x95 && rdesc[74] == 0x01) { | ||
35 | dev_info(&hdev->dev, "fixing up Kye/Genius Ergo Mouse report " | ||
36 | "descriptor\n"); | ||
37 | rdesc[62] = 0x09; | ||
38 | rdesc[64] = 0x04; | ||
39 | rdesc[66] = 0x07; | ||
40 | rdesc[72] = 0x01; | ||
41 | rdesc[74] = 0x08; | ||
42 | } | ||
43 | } | ||
44 | |||
45 | static const struct hid_device_id kye_devices[] = { | ||
46 | { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) }, | ||
47 | { } | ||
48 | }; | ||
49 | MODULE_DEVICE_TABLE(hid, kye_devices); | ||
50 | |||
51 | static struct hid_driver kye_driver = { | ||
52 | .name = "kye", | ||
53 | .id_table = kye_devices, | ||
54 | .report_fixup = kye_report_fixup, | ||
55 | }; | ||
56 | |||
57 | static int kye_init(void) | ||
58 | { | ||
59 | return hid_register_driver(&kye_driver); | ||
60 | } | ||
61 | |||
62 | static void kye_exit(void) | ||
63 | { | ||
64 | hid_unregister_driver(&kye_driver); | ||
65 | } | ||
66 | |||
67 | module_init(kye_init); | ||
68 | module_exit(kye_exit); | ||
69 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c index 83e07c9f4144..7b80cb694982 100644 --- a/drivers/hid/hid-lg.c +++ b/drivers/hid/hid-lg.c | |||
@@ -326,5 +326,3 @@ static void lg_exit(void) | |||
326 | module_init(lg_init); | 326 | module_init(lg_init); |
327 | module_exit(lg_exit); | 327 | module_exit(lg_exit); |
328 | MODULE_LICENSE("GPL"); | 328 | MODULE_LICENSE("GPL"); |
329 | |||
330 | HID_COMPAT_LOAD_DRIVER(logitech); | ||
diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c index 25b10dcad90d..5e9e37a0506d 100644 --- a/drivers/hid/hid-microsoft.c +++ b/drivers/hid/hid-microsoft.c | |||
@@ -210,5 +210,3 @@ static void ms_exit(void) | |||
210 | module_init(ms_init); | 210 | module_init(ms_init); |
211 | module_exit(ms_exit); | 211 | module_exit(ms_exit); |
212 | MODULE_LICENSE("GPL"); | 212 | MODULE_LICENSE("GPL"); |
213 | |||
214 | HID_COMPAT_LOAD_DRIVER(microsoft); | ||
diff --git a/drivers/hid/hid-monterey.c b/drivers/hid/hid-monterey.c index f3a85a065f18..240f87618be6 100644 --- a/drivers/hid/hid-monterey.c +++ b/drivers/hid/hid-monterey.c | |||
@@ -78,5 +78,3 @@ static void mr_exit(void) | |||
78 | module_init(mr_init); | 78 | module_init(mr_init); |
79 | module_exit(mr_exit); | 79 | module_exit(mr_exit); |
80 | MODULE_LICENSE("GPL"); | 80 | MODULE_LICENSE("GPL"); |
81 | |||
82 | HID_COMPAT_LOAD_DRIVER(monterey); | ||
diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c index db44fbd7bdf6..c5b252be9c21 100644 --- a/drivers/hid/hid-ntrig.c +++ b/drivers/hid/hid-ntrig.c | |||
@@ -78,5 +78,3 @@ static void ntrig_exit(void) | |||
78 | module_init(ntrig_init); | 78 | module_init(ntrig_init); |
79 | module_exit(ntrig_exit); | 79 | module_exit(ntrig_exit); |
80 | MODULE_LICENSE("GPL"); | 80 | MODULE_LICENSE("GPL"); |
81 | |||
82 | HID_COMPAT_LOAD_DRIVER(ntrig); | ||
diff --git a/drivers/hid/hid-petalynx.c b/drivers/hid/hid-petalynx.c index 10945fe12d50..2e83e8ff891a 100644 --- a/drivers/hid/hid-petalynx.c +++ b/drivers/hid/hid-petalynx.c | |||
@@ -118,5 +118,3 @@ static void pl_exit(void) | |||
118 | module_init(pl_init); | 118 | module_init(pl_init); |
119 | module_exit(pl_exit); | 119 | module_exit(pl_exit); |
120 | MODULE_LICENSE("GPL"); | 120 | MODULE_LICENSE("GPL"); |
121 | |||
122 | HID_COMPAT_LOAD_DRIVER(petalynx); | ||
diff --git a/drivers/hid/hid-pl.c b/drivers/hid/hid-pl.c index 46941f979b9d..4db9a3483760 100644 --- a/drivers/hid/hid-pl.c +++ b/drivers/hid/hid-pl.c | |||
@@ -9,9 +9,12 @@ | |||
9 | * - contains two reports, one for each port (HID_QUIRK_MULTI_INPUT) | 9 | * - contains two reports, one for each port (HID_QUIRK_MULTI_INPUT) |
10 | * | 10 | * |
11 | * 0e8f:0003 "GreenAsia Inc. USB Joystick " | 11 | * 0e8f:0003 "GreenAsia Inc. USB Joystick " |
12 | * - tested with K??ng Gaming gamepad | 12 | * - tested with König Gaming gamepad |
13 | * | 13 | * |
14 | * Copyright (c) 2007 Anssi Hannula <anssi.hannula@gmail.com> | 14 | * 0e8f:0003 "GASIA USB Gamepad" |
15 | * - another version of the König gamepad | ||
16 | * | ||
17 | * Copyright (c) 2007, 2009 Anssi Hannula <anssi.hannula@gmail.com> | ||
15 | */ | 18 | */ |
16 | 19 | ||
17 | /* | 20 | /* |
@@ -46,6 +49,8 @@ | |||
46 | 49 | ||
47 | struct plff_device { | 50 | struct plff_device { |
48 | struct hid_report *report; | 51 | struct hid_report *report; |
52 | s32 *strong; | ||
53 | s32 *weak; | ||
49 | }; | 54 | }; |
50 | 55 | ||
51 | static int hid_plff_play(struct input_dev *dev, void *data, | 56 | static int hid_plff_play(struct input_dev *dev, void *data, |
@@ -62,8 +67,8 @@ static int hid_plff_play(struct input_dev *dev, void *data, | |||
62 | left = left * 0x7f / 0xffff; | 67 | left = left * 0x7f / 0xffff; |
63 | right = right * 0x7f / 0xffff; | 68 | right = right * 0x7f / 0xffff; |
64 | 69 | ||
65 | plff->report->field[0]->value[2] = left; | 70 | *plff->strong = left; |
66 | plff->report->field[0]->value[3] = right; | 71 | *plff->weak = right; |
67 | debug("running with 0x%02x 0x%02x", left, right); | 72 | debug("running with 0x%02x 0x%02x", left, right); |
68 | usbhid_submit_report(hid, plff->report, USB_DIR_OUT); | 73 | usbhid_submit_report(hid, plff->report, USB_DIR_OUT); |
69 | 74 | ||
@@ -80,6 +85,8 @@ static int plff_init(struct hid_device *hid) | |||
80 | struct list_head *report_ptr = report_list; | 85 | struct list_head *report_ptr = report_list; |
81 | struct input_dev *dev; | 86 | struct input_dev *dev; |
82 | int error; | 87 | int error; |
88 | s32 *strong; | ||
89 | s32 *weak; | ||
83 | 90 | ||
84 | /* The device contains one output report per physical device, all | 91 | /* The device contains one output report per physical device, all |
85 | containing 1 field, which contains 4 ff00.0002 usages and 4 16bit | 92 | containing 1 field, which contains 4 ff00.0002 usages and 4 16bit |
@@ -87,7 +94,12 @@ static int plff_init(struct hid_device *hid) | |||
87 | 94 | ||
88 | The input reports also contain a field which contains | 95 | The input reports also contain a field which contains |
89 | 8 ff00.0001 usages and 8 boolean values. Their meaning is | 96 | 8 ff00.0001 usages and 8 boolean values. Their meaning is |
90 | currently unknown. */ | 97 | currently unknown. |
98 | |||
99 | A version of the 0e8f:0003 exists that has all the values in | ||
100 | separate fields and misses the extra input field, thus resembling | ||
101 | Zeroplus (hid-zpff) devices. | ||
102 | */ | ||
91 | 103 | ||
92 | if (list_empty(report_list)) { | 104 | if (list_empty(report_list)) { |
93 | dev_err(&hid->dev, "no output reports found\n"); | 105 | dev_err(&hid->dev, "no output reports found\n"); |
@@ -110,8 +122,21 @@ static int plff_init(struct hid_device *hid) | |||
110 | return -ENODEV; | 122 | return -ENODEV; |
111 | } | 123 | } |
112 | 124 | ||
113 | if (report->field[0]->report_count < 4) { | 125 | if (report->field[0]->report_count >= 4) { |
114 | dev_err(&hid->dev, "not enough values in the field\n"); | 126 | report->field[0]->value[0] = 0x00; |
127 | report->field[0]->value[1] = 0x00; | ||
128 | strong = &report->field[0]->value[2]; | ||
129 | weak = &report->field[0]->value[3]; | ||
130 | debug("detected single-field device"); | ||
131 | } else if (report->maxfield >= 4 && report->field[0]->maxusage == 1 && | ||
132 | report->field[0]->usage[0].hid == (HID_UP_LED | 0x43)) { | ||
133 | report->field[0]->value[0] = 0x00; | ||
134 | report->field[1]->value[0] = 0x00; | ||
135 | strong = &report->field[2]->value[0]; | ||
136 | weak = &report->field[3]->value[0]; | ||
137 | debug("detected 4-field device"); | ||
138 | } else { | ||
139 | dev_err(&hid->dev, "not enough fields or values\n"); | ||
115 | return -ENODEV; | 140 | return -ENODEV; |
116 | } | 141 | } |
117 | 142 | ||
@@ -130,10 +155,11 @@ static int plff_init(struct hid_device *hid) | |||
130 | } | 155 | } |
131 | 156 | ||
132 | plff->report = report; | 157 | plff->report = report; |
133 | plff->report->field[0]->value[0] = 0x00; | 158 | plff->strong = strong; |
134 | plff->report->field[0]->value[1] = 0x00; | 159 | plff->weak = weak; |
135 | plff->report->field[0]->value[2] = 0x00; | 160 | |
136 | plff->report->field[0]->value[3] = 0x00; | 161 | *strong = 0x00; |
162 | *weak = 0x00; | ||
137 | usbhid_submit_report(hid, plff->report, USB_DIR_OUT); | 163 | usbhid_submit_report(hid, plff->report, USB_DIR_OUT); |
138 | } | 164 | } |
139 | 165 | ||
@@ -180,7 +206,7 @@ static const struct hid_device_id pl_devices[] = { | |||
180 | .driver_data = 1 }, /* Twin USB Joystick */ | 206 | .driver_data = 1 }, /* Twin USB Joystick */ |
181 | { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR), | 207 | { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR), |
182 | .driver_data = 1 }, /* Twin USB Joystick */ | 208 | .driver_data = 1 }, /* Twin USB Joystick */ |
183 | { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003), }, /* GreenAsia Inc. USB Joystick */ | 209 | { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003), }, |
184 | { } | 210 | { } |
185 | }; | 211 | }; |
186 | MODULE_DEVICE_TABLE(hid, pl_devices); | 212 | MODULE_DEVICE_TABLE(hid, pl_devices); |
@@ -204,5 +230,3 @@ static void pl_exit(void) | |||
204 | module_init(pl_init); | 230 | module_init(pl_init); |
205 | module_exit(pl_exit); | 231 | module_exit(pl_exit); |
206 | MODULE_LICENSE("GPL"); | 232 | MODULE_LICENSE("GPL"); |
207 | |||
208 | HID_COMPAT_LOAD_DRIVER(pantherlord); | ||
diff --git a/drivers/hid/hid-samsung.c b/drivers/hid/hid-samsung.c index 15f3c0492450..07083aa6c19a 100644 --- a/drivers/hid/hid-samsung.c +++ b/drivers/hid/hid-samsung.c | |||
@@ -96,5 +96,3 @@ static void samsung_exit(void) | |||
96 | module_init(samsung_init); | 96 | module_init(samsung_init); |
97 | module_exit(samsung_exit); | 97 | module_exit(samsung_exit); |
98 | MODULE_LICENSE("GPL"); | 98 | MODULE_LICENSE("GPL"); |
99 | |||
100 | HID_COMPAT_LOAD_DRIVER(samsung); | ||
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index dd5a3979a4de..c2599388a350 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c | |||
@@ -148,5 +148,3 @@ static void sony_exit(void) | |||
148 | module_init(sony_init); | 148 | module_init(sony_init); |
149 | module_exit(sony_exit); | 149 | module_exit(sony_exit); |
150 | MODULE_LICENSE("GPL"); | 150 | MODULE_LICENSE("GPL"); |
151 | |||
152 | HID_COMPAT_LOAD_DRIVER(sony); | ||
diff --git a/drivers/hid/hid-sunplus.c b/drivers/hid/hid-sunplus.c index 5ba68f7dbb78..e0a8fd36a85b 100644 --- a/drivers/hid/hid-sunplus.c +++ b/drivers/hid/hid-sunplus.c | |||
@@ -78,5 +78,3 @@ static void sp_exit(void) | |||
78 | module_init(sp_init); | 78 | module_init(sp_init); |
79 | module_exit(sp_exit); | 79 | module_exit(sp_exit); |
80 | MODULE_LICENSE("GPL"); | 80 | MODULE_LICENSE("GPL"); |
81 | |||
82 | HID_COMPAT_LOAD_DRIVER(sunplus); | ||
diff --git a/drivers/hid/hid-tmff.c b/drivers/hid/hid-tmff.c index 1b7cba0f7e1f..7c1f7b50330c 100644 --- a/drivers/hid/hid-tmff.c +++ b/drivers/hid/hid-tmff.c | |||
@@ -265,5 +265,3 @@ static void tm_exit(void) | |||
265 | module_init(tm_init); | 265 | module_init(tm_init); |
266 | module_exit(tm_exit); | 266 | module_exit(tm_exit); |
267 | MODULE_LICENSE("GPL"); | 267 | MODULE_LICENSE("GPL"); |
268 | |||
269 | HID_COMPAT_LOAD_DRIVER(thrustmaster); | ||
diff --git a/drivers/hid/hid-topseed.c b/drivers/hid/hid-topseed.c index cca64a0564a9..152ccfabeba5 100644 --- a/drivers/hid/hid-topseed.c +++ b/drivers/hid/hid-topseed.c | |||
@@ -73,5 +73,3 @@ static void ts_exit(void) | |||
73 | module_init(ts_init); | 73 | module_init(ts_init); |
74 | module_exit(ts_exit); | 74 | module_exit(ts_exit); |
75 | MODULE_LICENSE("GPL"); | 75 | MODULE_LICENSE("GPL"); |
76 | |||
77 | HID_COMPAT_LOAD_DRIVER(topseed); | ||
diff --git a/drivers/hid/hid-zpff.c b/drivers/hid/hid-zpff.c index ea82f3718b21..85a198a18537 100644 --- a/drivers/hid/hid-zpff.c +++ b/drivers/hid/hid-zpff.c | |||
@@ -158,5 +158,3 @@ static void zp_exit(void) | |||
158 | module_init(zp_init); | 158 | module_init(zp_init); |
159 | module_exit(zp_exit); | 159 | module_exit(zp_exit); |
160 | MODULE_LICENSE("GPL"); | 160 | MODULE_LICENSE("GPL"); |
161 | |||
162 | HID_COMPAT_LOAD_DRIVER(zeroplus); | ||
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c index 02b19db5442e..e263d4731179 100644 --- a/drivers/hid/hidraw.c +++ b/drivers/hid/hidraw.c | |||
@@ -181,9 +181,17 @@ static int hidraw_open(struct inode *inode, struct file *file) | |||
181 | 181 | ||
182 | dev = hidraw_table[minor]; | 182 | dev = hidraw_table[minor]; |
183 | if (!dev->open++) { | 183 | if (!dev->open++) { |
184 | if (dev->hid->ll_driver->power) { | ||
185 | err = dev->hid->ll_driver->power(dev->hid, PM_HINT_FULLON); | ||
186 | if (err < 0) | ||
187 | goto out_unlock; | ||
188 | } | ||
184 | err = dev->hid->ll_driver->open(dev->hid); | 189 | err = dev->hid->ll_driver->open(dev->hid); |
185 | if (err < 0) | 190 | if (err < 0) { |
191 | if (dev->hid->ll_driver->power) | ||
192 | dev->hid->ll_driver->power(dev->hid, PM_HINT_NORMAL); | ||
186 | dev->open--; | 193 | dev->open--; |
194 | } | ||
187 | } | 195 | } |
188 | 196 | ||
189 | out_unlock: | 197 | out_unlock: |
@@ -209,10 +217,13 @@ static int hidraw_release(struct inode * inode, struct file * file) | |||
209 | list_del(&list->node); | 217 | list_del(&list->node); |
210 | dev = hidraw_table[minor]; | 218 | dev = hidraw_table[minor]; |
211 | if (!--dev->open) { | 219 | if (!--dev->open) { |
212 | if (list->hidraw->exist) | 220 | if (list->hidraw->exist) { |
221 | if (dev->hid->ll_driver->power) | ||
222 | dev->hid->ll_driver->power(dev->hid, PM_HINT_NORMAL); | ||
213 | dev->hid->ll_driver->close(dev->hid); | 223 | dev->hid->ll_driver->close(dev->hid); |
214 | else | 224 | } else { |
215 | kfree(list->hidraw); | 225 | kfree(list->hidraw); |
226 | } | ||
216 | } | 227 | } |
217 | 228 | ||
218 | kfree(list); | 229 | kfree(list); |
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index f0a0f72238ab..4306cb1b8ce5 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c | |||
@@ -5,6 +5,7 @@ | |||
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-2008 Jiri Kosina | 7 | * Copyright (c) 2006-2008 Jiri Kosina |
8 | * Copyright (c) 2007-2008 Oliver Neukum | ||
8 | */ | 9 | */ |
9 | 10 | ||
10 | /* | 11 | /* |
@@ -27,6 +28,7 @@ | |||
27 | #include <asm/byteorder.h> | 28 | #include <asm/byteorder.h> |
28 | #include <linux/input.h> | 29 | #include <linux/input.h> |
29 | #include <linux/wait.h> | 30 | #include <linux/wait.h> |
31 | #include <linux/workqueue.h> | ||
30 | 32 | ||
31 | #include <linux/usb.h> | 33 | #include <linux/usb.h> |
32 | 34 | ||
@@ -53,6 +55,10 @@ static unsigned int hid_mousepoll_interval; | |||
53 | module_param_named(mousepoll, hid_mousepoll_interval, uint, 0644); | 55 | module_param_named(mousepoll, hid_mousepoll_interval, uint, 0644); |
54 | MODULE_PARM_DESC(mousepoll, "Polling interval of mice"); | 56 | MODULE_PARM_DESC(mousepoll, "Polling interval of mice"); |
55 | 57 | ||
58 | static unsigned int ignoreled; | ||
59 | module_param_named(ignoreled, ignoreled, uint, 0644); | ||
60 | MODULE_PARM_DESC(ignoreled, "Autosuspend with active leds"); | ||
61 | |||
56 | /* Quirks specified at module load time */ | 62 | /* Quirks specified at module load time */ |
57 | static char *quirks_param[MAX_USBHID_BOOT_QUIRKS] = { [ 0 ... (MAX_USBHID_BOOT_QUIRKS - 1) ] = NULL }; | 63 | static char *quirks_param[MAX_USBHID_BOOT_QUIRKS] = { [ 0 ... (MAX_USBHID_BOOT_QUIRKS - 1) ] = NULL }; |
58 | module_param_array_named(quirks, quirks_param, charp, NULL, 0444); | 64 | module_param_array_named(quirks, quirks_param, charp, NULL, 0444); |
@@ -63,8 +69,13 @@ MODULE_PARM_DESC(quirks, "Add/modify USB HID quirks by specifying " | |||
63 | /* | 69 | /* |
64 | * Input submission and I/O error handler. | 70 | * Input submission and I/O error handler. |
65 | */ | 71 | */ |
72 | static DEFINE_MUTEX(hid_open_mut); | ||
73 | static struct workqueue_struct *resumption_waker; | ||
66 | 74 | ||
67 | static void hid_io_error(struct hid_device *hid); | 75 | static void hid_io_error(struct hid_device *hid); |
76 | static int hid_submit_out(struct hid_device *hid); | ||
77 | static int hid_submit_ctrl(struct hid_device *hid); | ||
78 | static void hid_cancel_delayed_stuff(struct usbhid_device *usbhid); | ||
68 | 79 | ||
69 | /* Start up the input URB */ | 80 | /* Start up the input URB */ |
70 | static int hid_start_in(struct hid_device *hid) | 81 | static int hid_start_in(struct hid_device *hid) |
@@ -73,15 +84,16 @@ static int hid_start_in(struct hid_device *hid) | |||
73 | int rc = 0; | 84 | int rc = 0; |
74 | struct usbhid_device *usbhid = hid->driver_data; | 85 | struct usbhid_device *usbhid = hid->driver_data; |
75 | 86 | ||
76 | spin_lock_irqsave(&usbhid->inlock, flags); | 87 | spin_lock_irqsave(&usbhid->lock, flags); |
77 | if (hid->open > 0 && !test_bit(HID_SUSPENDED, &usbhid->iofl) && | 88 | if (hid->open > 0 && |
78 | !test_bit(HID_DISCONNECTED, &usbhid->iofl) && | 89 | !test_bit(HID_DISCONNECTED, &usbhid->iofl) && |
90 | !test_bit(HID_REPORTED_IDLE, &usbhid->iofl) && | ||
79 | !test_and_set_bit(HID_IN_RUNNING, &usbhid->iofl)) { | 91 | !test_and_set_bit(HID_IN_RUNNING, &usbhid->iofl)) { |
80 | rc = usb_submit_urb(usbhid->urbin, GFP_ATOMIC); | 92 | rc = usb_submit_urb(usbhid->urbin, GFP_ATOMIC); |
81 | if (rc != 0) | 93 | if (rc != 0) |
82 | clear_bit(HID_IN_RUNNING, &usbhid->iofl); | 94 | clear_bit(HID_IN_RUNNING, &usbhid->iofl); |
83 | } | 95 | } |
84 | spin_unlock_irqrestore(&usbhid->inlock, flags); | 96 | spin_unlock_irqrestore(&usbhid->lock, flags); |
85 | return rc; | 97 | return rc; |
86 | } | 98 | } |
87 | 99 | ||
@@ -145,7 +157,7 @@ static void hid_io_error(struct hid_device *hid) | |||
145 | unsigned long flags; | 157 | unsigned long flags; |
146 | struct usbhid_device *usbhid = hid->driver_data; | 158 | struct usbhid_device *usbhid = hid->driver_data; |
147 | 159 | ||
148 | spin_lock_irqsave(&usbhid->inlock, flags); | 160 | spin_lock_irqsave(&usbhid->lock, flags); |
149 | 161 | ||
150 | /* Stop when disconnected */ | 162 | /* Stop when disconnected */ |
151 | if (test_bit(HID_DISCONNECTED, &usbhid->iofl)) | 163 | if (test_bit(HID_DISCONNECTED, &usbhid->iofl)) |
@@ -175,7 +187,51 @@ static void hid_io_error(struct hid_device *hid) | |||
175 | mod_timer(&usbhid->io_retry, | 187 | mod_timer(&usbhid->io_retry, |
176 | jiffies + msecs_to_jiffies(usbhid->retry_delay)); | 188 | jiffies + msecs_to_jiffies(usbhid->retry_delay)); |
177 | done: | 189 | done: |
178 | spin_unlock_irqrestore(&usbhid->inlock, flags); | 190 | spin_unlock_irqrestore(&usbhid->lock, flags); |
191 | } | ||
192 | |||
193 | static void usbhid_mark_busy(struct usbhid_device *usbhid) | ||
194 | { | ||
195 | struct usb_interface *intf = usbhid->intf; | ||
196 | |||
197 | usb_mark_last_busy(interface_to_usbdev(intf)); | ||
198 | } | ||
199 | |||
200 | static int usbhid_restart_out_queue(struct usbhid_device *usbhid) | ||
201 | { | ||
202 | struct hid_device *hid = usb_get_intfdata(usbhid->intf); | ||
203 | int kicked; | ||
204 | |||
205 | if (!hid) | ||
206 | return 0; | ||
207 | |||
208 | if ((kicked = (usbhid->outhead != usbhid->outtail))) { | ||
209 | dbg("Kicking head %d tail %d", usbhid->outhead, usbhid->outtail); | ||
210 | if (hid_submit_out(hid)) { | ||
211 | clear_bit(HID_OUT_RUNNING, &usbhid->iofl); | ||
212 | wake_up(&usbhid->wait); | ||
213 | } | ||
214 | } | ||
215 | return kicked; | ||
216 | } | ||
217 | |||
218 | static int usbhid_restart_ctrl_queue(struct usbhid_device *usbhid) | ||
219 | { | ||
220 | struct hid_device *hid = usb_get_intfdata(usbhid->intf); | ||
221 | int kicked; | ||
222 | |||
223 | WARN_ON(hid == NULL); | ||
224 | if (!hid) | ||
225 | return 0; | ||
226 | |||
227 | if ((kicked = (usbhid->ctrlhead != usbhid->ctrltail))) { | ||
228 | dbg("Kicking head %d tail %d", usbhid->ctrlhead, usbhid->ctrltail); | ||
229 | if (hid_submit_ctrl(hid)) { | ||
230 | clear_bit(HID_CTRL_RUNNING, &usbhid->iofl); | ||
231 | wake_up(&usbhid->wait); | ||
232 | } | ||
233 | } | ||
234 | return kicked; | ||
179 | } | 235 | } |
180 | 236 | ||
181 | /* | 237 | /* |
@@ -190,12 +246,23 @@ static void hid_irq_in(struct urb *urb) | |||
190 | 246 | ||
191 | switch (urb->status) { | 247 | switch (urb->status) { |
192 | case 0: /* success */ | 248 | case 0: /* success */ |
249 | usbhid_mark_busy(usbhid); | ||
193 | usbhid->retry_delay = 0; | 250 | usbhid->retry_delay = 0; |
194 | hid_input_report(urb->context, HID_INPUT_REPORT, | 251 | hid_input_report(urb->context, HID_INPUT_REPORT, |
195 | urb->transfer_buffer, | 252 | urb->transfer_buffer, |
196 | urb->actual_length, 1); | 253 | urb->actual_length, 1); |
254 | /* | ||
255 | * autosuspend refused while keys are pressed | ||
256 | * because most keyboards don't wake up when | ||
257 | * a key is released | ||
258 | */ | ||
259 | if (hid_check_keys_pressed(hid)) | ||
260 | set_bit(HID_KEYS_PRESSED, &usbhid->iofl); | ||
261 | else | ||
262 | clear_bit(HID_KEYS_PRESSED, &usbhid->iofl); | ||
197 | break; | 263 | break; |
198 | case -EPIPE: /* stall */ | 264 | case -EPIPE: /* stall */ |
265 | usbhid_mark_busy(usbhid); | ||
199 | clear_bit(HID_IN_RUNNING, &usbhid->iofl); | 266 | clear_bit(HID_IN_RUNNING, &usbhid->iofl); |
200 | set_bit(HID_CLEAR_HALT, &usbhid->iofl); | 267 | set_bit(HID_CLEAR_HALT, &usbhid->iofl); |
201 | schedule_work(&usbhid->reset_work); | 268 | schedule_work(&usbhid->reset_work); |
@@ -209,6 +276,7 @@ static void hid_irq_in(struct urb *urb) | |||
209 | case -EPROTO: /* protocol error or unplug */ | 276 | case -EPROTO: /* protocol error or unplug */ |
210 | case -ETIME: /* protocol error or unplug */ | 277 | case -ETIME: /* protocol error or unplug */ |
211 | case -ETIMEDOUT: /* Should never happen, but... */ | 278 | case -ETIMEDOUT: /* Should never happen, but... */ |
279 | usbhid_mark_busy(usbhid); | ||
212 | clear_bit(HID_IN_RUNNING, &usbhid->iofl); | 280 | clear_bit(HID_IN_RUNNING, &usbhid->iofl); |
213 | hid_io_error(hid); | 281 | hid_io_error(hid); |
214 | return; | 282 | return; |
@@ -239,16 +307,25 @@ static int hid_submit_out(struct hid_device *hid) | |||
239 | report = usbhid->out[usbhid->outtail].report; | 307 | report = usbhid->out[usbhid->outtail].report; |
240 | raw_report = usbhid->out[usbhid->outtail].raw_report; | 308 | raw_report = usbhid->out[usbhid->outtail].raw_report; |
241 | 309 | ||
242 | usbhid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + (report->id > 0); | 310 | if (!test_bit(HID_REPORTED_IDLE, &usbhid->iofl)) { |
243 | usbhid->urbout->dev = hid_to_usb_dev(hid); | 311 | usbhid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + (report->id > 0); |
244 | memcpy(usbhid->outbuf, raw_report, usbhid->urbout->transfer_buffer_length); | 312 | usbhid->urbout->dev = hid_to_usb_dev(hid); |
245 | kfree(raw_report); | 313 | memcpy(usbhid->outbuf, raw_report, usbhid->urbout->transfer_buffer_length); |
314 | kfree(raw_report); | ||
246 | 315 | ||
247 | dbg_hid("submitting out urb\n"); | 316 | dbg_hid("submitting out urb\n"); |
248 | 317 | ||
249 | if (usb_submit_urb(usbhid->urbout, GFP_ATOMIC)) { | 318 | if (usb_submit_urb(usbhid->urbout, GFP_ATOMIC)) { |
250 | err_hid("usb_submit_urb(out) failed"); | 319 | err_hid("usb_submit_urb(out) failed"); |
251 | return -1; | 320 | return -1; |
321 | } | ||
322 | } else { | ||
323 | /* | ||
324 | * queue work to wake up the device. | ||
325 | * as the work queue is freezeable, this is safe | ||
326 | * with respect to STD and STR | ||
327 | */ | ||
328 | queue_work(resumption_waker, &usbhid->restart_work); | ||
252 | } | 329 | } |
253 | 330 | ||
254 | return 0; | 331 | return 0; |
@@ -266,41 +343,50 @@ static int hid_submit_ctrl(struct hid_device *hid) | |||
266 | raw_report = usbhid->ctrl[usbhid->ctrltail].raw_report; | 343 | raw_report = usbhid->ctrl[usbhid->ctrltail].raw_report; |
267 | dir = usbhid->ctrl[usbhid->ctrltail].dir; | 344 | dir = usbhid->ctrl[usbhid->ctrltail].dir; |
268 | 345 | ||
269 | len = ((report->size - 1) >> 3) + 1 + (report->id > 0); | 346 | if (!test_bit(HID_REPORTED_IDLE, &usbhid->iofl)) { |
270 | if (dir == USB_DIR_OUT) { | 347 | len = ((report->size - 1) >> 3) + 1 + (report->id > 0); |
271 | usbhid->urbctrl->pipe = usb_sndctrlpipe(hid_to_usb_dev(hid), 0); | 348 | if (dir == USB_DIR_OUT) { |
272 | usbhid->urbctrl->transfer_buffer_length = len; | 349 | usbhid->urbctrl->pipe = usb_sndctrlpipe(hid_to_usb_dev(hid), 0); |
273 | memcpy(usbhid->ctrlbuf, raw_report, len); | 350 | usbhid->urbctrl->transfer_buffer_length = len; |
274 | kfree(raw_report); | 351 | memcpy(usbhid->ctrlbuf, raw_report, len); |
275 | } else { | 352 | kfree(raw_report); |
276 | int maxpacket, padlen; | 353 | } else { |
277 | 354 | int maxpacket, padlen; | |
278 | usbhid->urbctrl->pipe = usb_rcvctrlpipe(hid_to_usb_dev(hid), 0); | 355 | |
279 | maxpacket = usb_maxpacket(hid_to_usb_dev(hid), usbhid->urbctrl->pipe, 0); | 356 | usbhid->urbctrl->pipe = usb_rcvctrlpipe(hid_to_usb_dev(hid), 0); |
280 | if (maxpacket > 0) { | 357 | maxpacket = usb_maxpacket(hid_to_usb_dev(hid), usbhid->urbctrl->pipe, 0); |
281 | padlen = DIV_ROUND_UP(len, maxpacket); | 358 | if (maxpacket > 0) { |
282 | padlen *= maxpacket; | 359 | padlen = DIV_ROUND_UP(len, maxpacket); |
283 | if (padlen > usbhid->bufsize) | 360 | padlen *= maxpacket; |
284 | padlen = usbhid->bufsize; | 361 | if (padlen > usbhid->bufsize) |
285 | } else | 362 | padlen = usbhid->bufsize; |
286 | padlen = 0; | 363 | } else |
287 | usbhid->urbctrl->transfer_buffer_length = padlen; | 364 | padlen = 0; |
288 | } | 365 | usbhid->urbctrl->transfer_buffer_length = padlen; |
289 | usbhid->urbctrl->dev = hid_to_usb_dev(hid); | 366 | } |
367 | usbhid->urbctrl->dev = hid_to_usb_dev(hid); | ||
290 | 368 | ||
291 | usbhid->cr->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE | dir; | 369 | usbhid->cr->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE | dir; |
292 | usbhid->cr->bRequest = (dir == USB_DIR_OUT) ? HID_REQ_SET_REPORT : HID_REQ_GET_REPORT; | 370 | usbhid->cr->bRequest = (dir == USB_DIR_OUT) ? HID_REQ_SET_REPORT : HID_REQ_GET_REPORT; |
293 | usbhid->cr->wValue = cpu_to_le16(((report->type + 1) << 8) | report->id); | 371 | usbhid->cr->wValue = cpu_to_le16(((report->type + 1) << 8) | report->id); |
294 | usbhid->cr->wIndex = cpu_to_le16(usbhid->ifnum); | 372 | usbhid->cr->wIndex = cpu_to_le16(usbhid->ifnum); |
295 | usbhid->cr->wLength = cpu_to_le16(len); | 373 | usbhid->cr->wLength = cpu_to_le16(len); |
296 | 374 | ||
297 | dbg_hid("submitting ctrl urb: %s wValue=0x%04x wIndex=0x%04x wLength=%u\n", | 375 | dbg_hid("submitting ctrl urb: %s wValue=0x%04x wIndex=0x%04x wLength=%u\n", |
298 | usbhid->cr->bRequest == HID_REQ_SET_REPORT ? "Set_Report" : "Get_Report", | 376 | usbhid->cr->bRequest == HID_REQ_SET_REPORT ? "Set_Report" : "Get_Report", |
299 | usbhid->cr->wValue, usbhid->cr->wIndex, usbhid->cr->wLength); | 377 | usbhid->cr->wValue, usbhid->cr->wIndex, usbhid->cr->wLength); |
300 | 378 | ||
301 | if (usb_submit_urb(usbhid->urbctrl, GFP_ATOMIC)) { | 379 | if (usb_submit_urb(usbhid->urbctrl, GFP_ATOMIC)) { |
302 | err_hid("usb_submit_urb(ctrl) failed"); | 380 | err_hid("usb_submit_urb(ctrl) failed"); |
303 | return -1; | 381 | return -1; |
382 | } | ||
383 | } else { | ||
384 | /* | ||
385 | * queue work to wake up the device. | ||
386 | * as the work queue is freezeable, this is safe | ||
387 | * with respect to STD and STR | ||
388 | */ | ||
389 | queue_work(resumption_waker, &usbhid->restart_work); | ||
304 | } | 390 | } |
305 | 391 | ||
306 | return 0; | 392 | return 0; |
@@ -332,7 +418,7 @@ static void hid_irq_out(struct urb *urb) | |||
332 | "received\n", urb->status); | 418 | "received\n", urb->status); |
333 | } | 419 | } |
334 | 420 | ||
335 | spin_lock_irqsave(&usbhid->outlock, flags); | 421 | spin_lock_irqsave(&usbhid->lock, flags); |
336 | 422 | ||
337 | if (unplug) | 423 | if (unplug) |
338 | usbhid->outtail = usbhid->outhead; | 424 | usbhid->outtail = usbhid->outhead; |
@@ -344,12 +430,12 @@ static void hid_irq_out(struct urb *urb) | |||
344 | clear_bit(HID_OUT_RUNNING, &usbhid->iofl); | 430 | clear_bit(HID_OUT_RUNNING, &usbhid->iofl); |
345 | wake_up(&usbhid->wait); | 431 | wake_up(&usbhid->wait); |
346 | } | 432 | } |
347 | spin_unlock_irqrestore(&usbhid->outlock, flags); | 433 | spin_unlock_irqrestore(&usbhid->lock, flags); |
348 | return; | 434 | return; |
349 | } | 435 | } |
350 | 436 | ||
351 | clear_bit(HID_OUT_RUNNING, &usbhid->iofl); | 437 | clear_bit(HID_OUT_RUNNING, &usbhid->iofl); |
352 | spin_unlock_irqrestore(&usbhid->outlock, flags); | 438 | spin_unlock_irqrestore(&usbhid->lock, flags); |
353 | wake_up(&usbhid->wait); | 439 | wake_up(&usbhid->wait); |
354 | } | 440 | } |
355 | 441 | ||
@@ -361,12 +447,11 @@ static void hid_ctrl(struct urb *urb) | |||
361 | { | 447 | { |
362 | struct hid_device *hid = urb->context; | 448 | struct hid_device *hid = urb->context; |
363 | struct usbhid_device *usbhid = hid->driver_data; | 449 | struct usbhid_device *usbhid = hid->driver_data; |
364 | unsigned long flags; | 450 | int unplug = 0, status = urb->status; |
365 | int unplug = 0; | ||
366 | 451 | ||
367 | spin_lock_irqsave(&usbhid->ctrllock, flags); | 452 | spin_lock(&usbhid->lock); |
368 | 453 | ||
369 | switch (urb->status) { | 454 | switch (status) { |
370 | case 0: /* success */ | 455 | case 0: /* success */ |
371 | if (usbhid->ctrl[usbhid->ctrltail].dir == USB_DIR_IN) | 456 | if (usbhid->ctrl[usbhid->ctrltail].dir == USB_DIR_IN) |
372 | hid_input_report(urb->context, | 457 | hid_input_report(urb->context, |
@@ -383,7 +468,7 @@ static void hid_ctrl(struct urb *urb) | |||
383 | break; | 468 | break; |
384 | default: /* error */ | 469 | default: /* error */ |
385 | dev_warn(&urb->dev->dev, "ctrl urb status %d " | 470 | dev_warn(&urb->dev->dev, "ctrl urb status %d " |
386 | "received\n", urb->status); | 471 | "received\n", status); |
387 | } | 472 | } |
388 | 473 | ||
389 | if (unplug) | 474 | if (unplug) |
@@ -396,19 +481,18 @@ static void hid_ctrl(struct urb *urb) | |||
396 | clear_bit(HID_CTRL_RUNNING, &usbhid->iofl); | 481 | clear_bit(HID_CTRL_RUNNING, &usbhid->iofl); |
397 | wake_up(&usbhid->wait); | 482 | wake_up(&usbhid->wait); |
398 | } | 483 | } |
399 | spin_unlock_irqrestore(&usbhid->ctrllock, flags); | 484 | spin_unlock(&usbhid->lock); |
400 | return; | 485 | return; |
401 | } | 486 | } |
402 | 487 | ||
403 | clear_bit(HID_CTRL_RUNNING, &usbhid->iofl); | 488 | clear_bit(HID_CTRL_RUNNING, &usbhid->iofl); |
404 | spin_unlock_irqrestore(&usbhid->ctrllock, flags); | 489 | spin_unlock(&usbhid->lock); |
405 | wake_up(&usbhid->wait); | 490 | wake_up(&usbhid->wait); |
406 | } | 491 | } |
407 | 492 | ||
408 | void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir) | 493 | void __usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir) |
409 | { | 494 | { |
410 | int head; | 495 | int head; |
411 | unsigned long flags; | ||
412 | struct usbhid_device *usbhid = hid->driver_data; | 496 | struct usbhid_device *usbhid = hid->driver_data; |
413 | int len = ((report->size - 1) >> 3) + 1 + (report->id > 0); | 497 | int len = ((report->size - 1) >> 3) + 1 + (report->id > 0); |
414 | 498 | ||
@@ -416,18 +500,13 @@ void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, uns | |||
416 | return; | 500 | return; |
417 | 501 | ||
418 | if (usbhid->urbout && dir == USB_DIR_OUT && report->type == HID_OUTPUT_REPORT) { | 502 | if (usbhid->urbout && dir == USB_DIR_OUT && report->type == HID_OUTPUT_REPORT) { |
419 | |||
420 | spin_lock_irqsave(&usbhid->outlock, flags); | ||
421 | |||
422 | if ((head = (usbhid->outhead + 1) & (HID_OUTPUT_FIFO_SIZE - 1)) == usbhid->outtail) { | 503 | if ((head = (usbhid->outhead + 1) & (HID_OUTPUT_FIFO_SIZE - 1)) == usbhid->outtail) { |
423 | spin_unlock_irqrestore(&usbhid->outlock, flags); | ||
424 | dev_warn(&hid->dev, "output queue full\n"); | 504 | dev_warn(&hid->dev, "output queue full\n"); |
425 | return; | 505 | return; |
426 | } | 506 | } |
427 | 507 | ||
428 | usbhid->out[usbhid->outhead].raw_report = kmalloc(len, GFP_ATOMIC); | 508 | usbhid->out[usbhid->outhead].raw_report = kmalloc(len, GFP_ATOMIC); |
429 | if (!usbhid->out[usbhid->outhead].raw_report) { | 509 | if (!usbhid->out[usbhid->outhead].raw_report) { |
430 | spin_unlock_irqrestore(&usbhid->outlock, flags); | ||
431 | dev_warn(&hid->dev, "output queueing failed\n"); | 510 | dev_warn(&hid->dev, "output queueing failed\n"); |
432 | return; | 511 | return; |
433 | } | 512 | } |
@@ -438,15 +517,10 @@ void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, uns | |||
438 | if (!test_and_set_bit(HID_OUT_RUNNING, &usbhid->iofl)) | 517 | if (!test_and_set_bit(HID_OUT_RUNNING, &usbhid->iofl)) |
439 | if (hid_submit_out(hid)) | 518 | if (hid_submit_out(hid)) |
440 | clear_bit(HID_OUT_RUNNING, &usbhid->iofl); | 519 | clear_bit(HID_OUT_RUNNING, &usbhid->iofl); |
441 | |||
442 | spin_unlock_irqrestore(&usbhid->outlock, flags); | ||
443 | return; | 520 | return; |
444 | } | 521 | } |
445 | 522 | ||
446 | spin_lock_irqsave(&usbhid->ctrllock, flags); | ||
447 | |||
448 | if ((head = (usbhid->ctrlhead + 1) & (HID_CONTROL_FIFO_SIZE - 1)) == usbhid->ctrltail) { | 523 | if ((head = (usbhid->ctrlhead + 1) & (HID_CONTROL_FIFO_SIZE - 1)) == usbhid->ctrltail) { |
449 | spin_unlock_irqrestore(&usbhid->ctrllock, flags); | ||
450 | dev_warn(&hid->dev, "control queue full\n"); | 524 | dev_warn(&hid->dev, "control queue full\n"); |
451 | return; | 525 | return; |
452 | } | 526 | } |
@@ -454,7 +528,6 @@ void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, uns | |||
454 | if (dir == USB_DIR_OUT) { | 528 | if (dir == USB_DIR_OUT) { |
455 | usbhid->ctrl[usbhid->ctrlhead].raw_report = kmalloc(len, GFP_ATOMIC); | 529 | usbhid->ctrl[usbhid->ctrlhead].raw_report = kmalloc(len, GFP_ATOMIC); |
456 | if (!usbhid->ctrl[usbhid->ctrlhead].raw_report) { | 530 | if (!usbhid->ctrl[usbhid->ctrlhead].raw_report) { |
457 | spin_unlock_irqrestore(&usbhid->ctrllock, flags); | ||
458 | dev_warn(&hid->dev, "control queueing failed\n"); | 531 | dev_warn(&hid->dev, "control queueing failed\n"); |
459 | return; | 532 | return; |
460 | } | 533 | } |
@@ -467,15 +540,25 @@ void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, uns | |||
467 | if (!test_and_set_bit(HID_CTRL_RUNNING, &usbhid->iofl)) | 540 | if (!test_and_set_bit(HID_CTRL_RUNNING, &usbhid->iofl)) |
468 | if (hid_submit_ctrl(hid)) | 541 | if (hid_submit_ctrl(hid)) |
469 | clear_bit(HID_CTRL_RUNNING, &usbhid->iofl); | 542 | clear_bit(HID_CTRL_RUNNING, &usbhid->iofl); |
543 | } | ||
544 | |||
545 | void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir) | ||
546 | { | ||
547 | struct usbhid_device *usbhid = hid->driver_data; | ||
548 | unsigned long flags; | ||
470 | 549 | ||
471 | spin_unlock_irqrestore(&usbhid->ctrllock, flags); | 550 | spin_lock_irqsave(&usbhid->lock, flags); |
551 | __usbhid_submit_report(hid, report, dir); | ||
552 | spin_unlock_irqrestore(&usbhid->lock, flags); | ||
472 | } | 553 | } |
473 | EXPORT_SYMBOL_GPL(usbhid_submit_report); | 554 | EXPORT_SYMBOL_GPL(usbhid_submit_report); |
474 | 555 | ||
475 | static int usb_hidinput_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) | 556 | static int usb_hidinput_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) |
476 | { | 557 | { |
477 | struct hid_device *hid = input_get_drvdata(dev); | 558 | struct hid_device *hid = input_get_drvdata(dev); |
559 | struct usbhid_device *usbhid = hid->driver_data; | ||
478 | struct hid_field *field; | 560 | struct hid_field *field; |
561 | unsigned long flags; | ||
479 | int offset; | 562 | int offset; |
480 | 563 | ||
481 | if (type == EV_FF) | 564 | if (type == EV_FF) |
@@ -490,6 +573,15 @@ static int usb_hidinput_input_event(struct input_dev *dev, unsigned int type, un | |||
490 | } | 573 | } |
491 | 574 | ||
492 | hid_set_field(field, offset, value); | 575 | hid_set_field(field, offset, value); |
576 | if (value) { | ||
577 | spin_lock_irqsave(&usbhid->lock, flags); | ||
578 | usbhid->ledcount++; | ||
579 | spin_unlock_irqrestore(&usbhid->lock, flags); | ||
580 | } else { | ||
581 | spin_lock_irqsave(&usbhid->lock, flags); | ||
582 | usbhid->ledcount--; | ||
583 | spin_unlock_irqrestore(&usbhid->lock, flags); | ||
584 | } | ||
493 | usbhid_submit_report(hid, field->report, USB_DIR_OUT); | 585 | usbhid_submit_report(hid, field->report, USB_DIR_OUT); |
494 | 586 | ||
495 | return 0; | 587 | return 0; |
@@ -538,15 +630,22 @@ int usbhid_open(struct hid_device *hid) | |||
538 | struct usbhid_device *usbhid = hid->driver_data; | 630 | struct usbhid_device *usbhid = hid->driver_data; |
539 | int res; | 631 | int res; |
540 | 632 | ||
633 | mutex_lock(&hid_open_mut); | ||
541 | if (!hid->open++) { | 634 | if (!hid->open++) { |
542 | res = usb_autopm_get_interface(usbhid->intf); | 635 | res = usb_autopm_get_interface(usbhid->intf); |
636 | /* the device must be awake to reliable request remote wakeup */ | ||
543 | if (res < 0) { | 637 | if (res < 0) { |
544 | hid->open--; | 638 | hid->open--; |
639 | mutex_unlock(&hid_open_mut); | ||
545 | return -EIO; | 640 | return -EIO; |
546 | } | 641 | } |
642 | usbhid->intf->needs_remote_wakeup = 1; | ||
643 | if (hid_start_in(hid)) | ||
644 | hid_io_error(hid); | ||
645 | |||
646 | usb_autopm_put_interface(usbhid->intf); | ||
547 | } | 647 | } |
548 | if (hid_start_in(hid)) | 648 | mutex_unlock(&hid_open_mut); |
549 | hid_io_error(hid); | ||
550 | return 0; | 649 | return 0; |
551 | } | 650 | } |
552 | 651 | ||
@@ -554,10 +653,22 @@ void usbhid_close(struct hid_device *hid) | |||
554 | { | 653 | { |
555 | struct usbhid_device *usbhid = hid->driver_data; | 654 | struct usbhid_device *usbhid = hid->driver_data; |
556 | 655 | ||
656 | mutex_lock(&hid_open_mut); | ||
657 | |||
658 | /* protecting hid->open to make sure we don't restart | ||
659 | * data acquistion due to a resumption we no longer | ||
660 | * care about | ||
661 | */ | ||
662 | spin_lock_irq(&usbhid->lock); | ||
557 | if (!--hid->open) { | 663 | if (!--hid->open) { |
664 | spin_unlock_irq(&usbhid->lock); | ||
558 | usb_kill_urb(usbhid->urbin); | 665 | usb_kill_urb(usbhid->urbin); |
559 | usb_autopm_put_interface(usbhid->intf); | 666 | flush_scheduled_work(); |
667 | usbhid->intf->needs_remote_wakeup = 0; | ||
668 | } else { | ||
669 | spin_unlock_irq(&usbhid->lock); | ||
560 | } | 670 | } |
671 | mutex_unlock(&hid_open_mut); | ||
561 | } | 672 | } |
562 | 673 | ||
563 | /* | 674 | /* |
@@ -687,6 +798,25 @@ static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t co | |||
687 | return ret; | 798 | return ret; |
688 | } | 799 | } |
689 | 800 | ||
801 | static void usbhid_restart_queues(struct usbhid_device *usbhid) | ||
802 | { | ||
803 | if (usbhid->urbout) | ||
804 | usbhid_restart_out_queue(usbhid); | ||
805 | usbhid_restart_ctrl_queue(usbhid); | ||
806 | } | ||
807 | |||
808 | static void __usbhid_restart_queues(struct work_struct *work) | ||
809 | { | ||
810 | struct usbhid_device *usbhid = | ||
811 | container_of(work, struct usbhid_device, restart_work); | ||
812 | int r; | ||
813 | |||
814 | r = usb_autopm_get_interface(usbhid->intf); | ||
815 | if (r < 0) | ||
816 | return; | ||
817 | usb_autopm_put_interface(usbhid->intf); | ||
818 | } | ||
819 | |||
690 | static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid) | 820 | static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid) |
691 | { | 821 | { |
692 | struct usbhid_device *usbhid = hid->driver_data; | 822 | struct usbhid_device *usbhid = hid->driver_data; |
@@ -711,6 +841,9 @@ static int usbhid_parse(struct hid_device *hid) | |||
711 | quirks = usbhid_lookup_quirk(le16_to_cpu(dev->descriptor.idVendor), | 841 | quirks = usbhid_lookup_quirk(le16_to_cpu(dev->descriptor.idVendor), |
712 | le16_to_cpu(dev->descriptor.idProduct)); | 842 | le16_to_cpu(dev->descriptor.idProduct)); |
713 | 843 | ||
844 | if (quirks & HID_QUIRK_IGNORE) | ||
845 | return -ENODEV; | ||
846 | |||
714 | /* Many keyboards and mice don't like to be polled for reports, | 847 | /* Many keyboards and mice don't like to be polled for reports, |
715 | * so we will always set the HID_QUIRK_NOGET flag for them. */ | 848 | * so we will always set the HID_QUIRK_NOGET flag for them. */ |
716 | if (interface->desc.bInterfaceSubClass == USB_INTERFACE_SUBCLASS_BOOT) { | 849 | if (interface->desc.bInterfaceSubClass == USB_INTERFACE_SUBCLASS_BOOT) { |
@@ -850,11 +983,11 @@ static int usbhid_start(struct hid_device *hid) | |||
850 | 983 | ||
851 | init_waitqueue_head(&usbhid->wait); | 984 | init_waitqueue_head(&usbhid->wait); |
852 | INIT_WORK(&usbhid->reset_work, hid_reset); | 985 | INIT_WORK(&usbhid->reset_work, hid_reset); |
986 | INIT_WORK(&usbhid->restart_work, __usbhid_restart_queues); | ||
853 | setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid); | 987 | setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid); |
854 | 988 | ||
855 | spin_lock_init(&usbhid->inlock); | 989 | spin_lock_init(&usbhid->lock); |
856 | spin_lock_init(&usbhid->outlock); | 990 | spin_lock_init(&usbhid->lock); |
857 | spin_lock_init(&usbhid->ctrllock); | ||
858 | 991 | ||
859 | usbhid->intf = intf; | 992 | usbhid->intf = intf; |
860 | usbhid->ifnum = interface->desc.bInterfaceNumber; | 993 | usbhid->ifnum = interface->desc.bInterfaceNumber; |
@@ -906,15 +1039,14 @@ static void usbhid_stop(struct hid_device *hid) | |||
906 | return; | 1039 | return; |
907 | 1040 | ||
908 | clear_bit(HID_STARTED, &usbhid->iofl); | 1041 | clear_bit(HID_STARTED, &usbhid->iofl); |
909 | spin_lock_irq(&usbhid->inlock); /* Sync with error handler */ | 1042 | spin_lock_irq(&usbhid->lock); /* Sync with error handler */ |
910 | set_bit(HID_DISCONNECTED, &usbhid->iofl); | 1043 | set_bit(HID_DISCONNECTED, &usbhid->iofl); |
911 | spin_unlock_irq(&usbhid->inlock); | 1044 | spin_unlock_irq(&usbhid->lock); |
912 | usb_kill_urb(usbhid->urbin); | 1045 | usb_kill_urb(usbhid->urbin); |
913 | usb_kill_urb(usbhid->urbout); | 1046 | usb_kill_urb(usbhid->urbout); |
914 | usb_kill_urb(usbhid->urbctrl); | 1047 | usb_kill_urb(usbhid->urbctrl); |
915 | 1048 | ||
916 | del_timer_sync(&usbhid->io_retry); | 1049 | hid_cancel_delayed_stuff(usbhid); |
917 | cancel_work_sync(&usbhid->reset_work); | ||
918 | 1050 | ||
919 | if (hid->claimed & HID_CLAIMED_INPUT) | 1051 | if (hid->claimed & HID_CLAIMED_INPUT) |
920 | hidinput_disconnect(hid); | 1052 | hidinput_disconnect(hid); |
@@ -935,12 +1067,28 @@ static void usbhid_stop(struct hid_device *hid) | |||
935 | hid_free_buffers(hid_to_usb_dev(hid), hid); | 1067 | hid_free_buffers(hid_to_usb_dev(hid), hid); |
936 | } | 1068 | } |
937 | 1069 | ||
1070 | static int usbhid_power(struct hid_device *hid, int lvl) | ||
1071 | { | ||
1072 | int r = 0; | ||
1073 | |||
1074 | switch (lvl) { | ||
1075 | case PM_HINT_FULLON: | ||
1076 | r = usbhid_get_power(hid); | ||
1077 | break; | ||
1078 | case PM_HINT_NORMAL: | ||
1079 | usbhid_put_power(hid); | ||
1080 | break; | ||
1081 | } | ||
1082 | return r; | ||
1083 | } | ||
1084 | |||
938 | static struct hid_ll_driver usb_hid_driver = { | 1085 | static struct hid_ll_driver usb_hid_driver = { |
939 | .parse = usbhid_parse, | 1086 | .parse = usbhid_parse, |
940 | .start = usbhid_start, | 1087 | .start = usbhid_start, |
941 | .stop = usbhid_stop, | 1088 | .stop = usbhid_stop, |
942 | .open = usbhid_open, | 1089 | .open = usbhid_open, |
943 | .close = usbhid_close, | 1090 | .close = usbhid_close, |
1091 | .power = usbhid_power, | ||
944 | .hidinput_input_event = usb_hidinput_input_event, | 1092 | .hidinput_input_event = usb_hidinput_input_event, |
945 | }; | 1093 | }; |
946 | 1094 | ||
@@ -1049,19 +1197,126 @@ static void hid_disconnect(struct usb_interface *intf) | |||
1049 | kfree(usbhid); | 1197 | kfree(usbhid); |
1050 | } | 1198 | } |
1051 | 1199 | ||
1200 | static void hid_cancel_delayed_stuff(struct usbhid_device *usbhid) | ||
1201 | { | ||
1202 | del_timer_sync(&usbhid->io_retry); | ||
1203 | cancel_work_sync(&usbhid->restart_work); | ||
1204 | cancel_work_sync(&usbhid->reset_work); | ||
1205 | } | ||
1206 | |||
1207 | static void hid_cease_io(struct usbhid_device *usbhid) | ||
1208 | { | ||
1209 | del_timer(&usbhid->io_retry); | ||
1210 | usb_kill_urb(usbhid->urbin); | ||
1211 | usb_kill_urb(usbhid->urbctrl); | ||
1212 | usb_kill_urb(usbhid->urbout); | ||
1213 | } | ||
1214 | |||
1215 | /* Treat USB reset pretty much the same as suspend/resume */ | ||
1216 | static int hid_pre_reset(struct usb_interface *intf) | ||
1217 | { | ||
1218 | struct hid_device *hid = usb_get_intfdata(intf); | ||
1219 | struct usbhid_device *usbhid = hid->driver_data; | ||
1220 | |||
1221 | spin_lock_irq(&usbhid->lock); | ||
1222 | set_bit(HID_RESET_PENDING, &usbhid->iofl); | ||
1223 | spin_unlock_irq(&usbhid->lock); | ||
1224 | cancel_work_sync(&usbhid->restart_work); | ||
1225 | hid_cease_io(usbhid); | ||
1226 | |||
1227 | return 0; | ||
1228 | } | ||
1229 | |||
1230 | /* Same routine used for post_reset and reset_resume */ | ||
1231 | static int hid_post_reset(struct usb_interface *intf) | ||
1232 | { | ||
1233 | struct usb_device *dev = interface_to_usbdev (intf); | ||
1234 | struct hid_device *hid = usb_get_intfdata(intf); | ||
1235 | struct usbhid_device *usbhid = hid->driver_data; | ||
1236 | int status; | ||
1237 | |||
1238 | spin_lock_irq(&usbhid->lock); | ||
1239 | clear_bit(HID_RESET_PENDING, &usbhid->iofl); | ||
1240 | spin_unlock_irq(&usbhid->lock); | ||
1241 | hid_set_idle(dev, intf->cur_altsetting->desc.bInterfaceNumber, 0, 0); | ||
1242 | /* FIXME: Any more reinitialization needed? */ | ||
1243 | status = hid_start_in(hid); | ||
1244 | if (status < 0) | ||
1245 | hid_io_error(hid); | ||
1246 | usbhid_restart_queues(usbhid); | ||
1247 | |||
1248 | return 0; | ||
1249 | } | ||
1250 | |||
1251 | int usbhid_get_power(struct hid_device *hid) | ||
1252 | { | ||
1253 | struct usbhid_device *usbhid = hid->driver_data; | ||
1254 | |||
1255 | return usb_autopm_get_interface(usbhid->intf); | ||
1256 | } | ||
1257 | |||
1258 | void usbhid_put_power(struct hid_device *hid) | ||
1259 | { | ||
1260 | struct usbhid_device *usbhid = hid->driver_data; | ||
1261 | |||
1262 | usb_autopm_put_interface(usbhid->intf); | ||
1263 | } | ||
1264 | |||
1265 | |||
1266 | #ifdef CONFIG_PM | ||
1052 | static int hid_suspend(struct usb_interface *intf, pm_message_t message) | 1267 | static int hid_suspend(struct usb_interface *intf, pm_message_t message) |
1053 | { | 1268 | { |
1054 | struct hid_device *hid = usb_get_intfdata (intf); | 1269 | struct hid_device *hid = usb_get_intfdata(intf); |
1055 | struct usbhid_device *usbhid = hid->driver_data; | 1270 | struct usbhid_device *usbhid = hid->driver_data; |
1271 | struct usb_device *udev = interface_to_usbdev(intf); | ||
1272 | int status; | ||
1056 | 1273 | ||
1057 | if (!test_bit(HID_STARTED, &usbhid->iofl)) | 1274 | if (udev->auto_pm) { |
1058 | return 0; | 1275 | spin_lock_irq(&usbhid->lock); /* Sync with error handler */ |
1276 | if (!test_bit(HID_RESET_PENDING, &usbhid->iofl) | ||
1277 | && !test_bit(HID_CLEAR_HALT, &usbhid->iofl) | ||
1278 | && !test_bit(HID_OUT_RUNNING, &usbhid->iofl) | ||
1279 | && !test_bit(HID_CTRL_RUNNING, &usbhid->iofl) | ||
1280 | && !test_bit(HID_KEYS_PRESSED, &usbhid->iofl) | ||
1281 | && (!usbhid->ledcount || ignoreled)) | ||
1282 | { | ||
1283 | set_bit(HID_REPORTED_IDLE, &usbhid->iofl); | ||
1284 | spin_unlock_irq(&usbhid->lock); | ||
1285 | } else { | ||
1286 | usbhid_mark_busy(usbhid); | ||
1287 | spin_unlock_irq(&usbhid->lock); | ||
1288 | return -EBUSY; | ||
1289 | } | ||
1059 | 1290 | ||
1060 | spin_lock_irq(&usbhid->inlock); /* Sync with error handler */ | 1291 | } else { |
1061 | set_bit(HID_SUSPENDED, &usbhid->iofl); | 1292 | spin_lock_irq(&usbhid->lock); |
1062 | spin_unlock_irq(&usbhid->inlock); | 1293 | set_bit(HID_REPORTED_IDLE, &usbhid->iofl); |
1063 | del_timer_sync(&usbhid->io_retry); | 1294 | spin_unlock_irq(&usbhid->lock); |
1064 | usb_kill_urb(usbhid->urbin); | 1295 | if (usbhid_wait_io(hid) < 0) |
1296 | return -EIO; | ||
1297 | } | ||
1298 | |||
1299 | if (!ignoreled && udev->auto_pm) { | ||
1300 | spin_lock_irq(&usbhid->lock); | ||
1301 | if (test_bit(HID_LED_ON, &usbhid->iofl)) { | ||
1302 | spin_unlock_irq(&usbhid->lock); | ||
1303 | usbhid_mark_busy(usbhid); | ||
1304 | return -EBUSY; | ||
1305 | } | ||
1306 | spin_unlock_irq(&usbhid->lock); | ||
1307 | } | ||
1308 | |||
1309 | hid_cancel_delayed_stuff(usbhid); | ||
1310 | hid_cease_io(usbhid); | ||
1311 | |||
1312 | if (udev->auto_pm && test_bit(HID_KEYS_PRESSED, &usbhid->iofl)) { | ||
1313 | /* lost race against keypresses */ | ||
1314 | status = hid_start_in(hid); | ||
1315 | if (status < 0) | ||
1316 | hid_io_error(hid); | ||
1317 | usbhid_mark_busy(usbhid); | ||
1318 | return -EBUSY; | ||
1319 | } | ||
1065 | dev_dbg(&intf->dev, "suspend\n"); | 1320 | dev_dbg(&intf->dev, "suspend\n"); |
1066 | return 0; | 1321 | return 0; |
1067 | } | 1322 | } |
@@ -1075,32 +1330,33 @@ static int hid_resume(struct usb_interface *intf) | |||
1075 | if (!test_bit(HID_STARTED, &usbhid->iofl)) | 1330 | if (!test_bit(HID_STARTED, &usbhid->iofl)) |
1076 | return 0; | 1331 | return 0; |
1077 | 1332 | ||
1078 | clear_bit(HID_SUSPENDED, &usbhid->iofl); | 1333 | clear_bit(HID_REPORTED_IDLE, &usbhid->iofl); |
1334 | usbhid_mark_busy(usbhid); | ||
1335 | |||
1336 | if (test_bit(HID_CLEAR_HALT, &usbhid->iofl) || | ||
1337 | test_bit(HID_RESET_PENDING, &usbhid->iofl)) | ||
1338 | schedule_work(&usbhid->reset_work); | ||
1079 | usbhid->retry_delay = 0; | 1339 | usbhid->retry_delay = 0; |
1080 | status = hid_start_in(hid); | 1340 | status = hid_start_in(hid); |
1081 | dev_dbg(&intf->dev, "resume status %d\n", status); | 1341 | if (status < 0) |
1082 | return status; | 1342 | hid_io_error(hid); |
1083 | } | 1343 | usbhid_restart_queues(usbhid); |
1084 | 1344 | ||
1085 | /* Treat USB reset pretty much the same as suspend/resume */ | 1345 | dev_dbg(&intf->dev, "resume status %d\n", status); |
1086 | static int hid_pre_reset(struct usb_interface *intf) | ||
1087 | { | ||
1088 | /* FIXME: What if the interface is already suspended? */ | ||
1089 | hid_suspend(intf, PMSG_ON); | ||
1090 | return 0; | 1346 | return 0; |
1091 | } | 1347 | } |
1092 | 1348 | ||
1093 | /* Same routine used for post_reset and reset_resume */ | 1349 | static int hid_reset_resume(struct usb_interface *intf) |
1094 | static int hid_post_reset(struct usb_interface *intf) | ||
1095 | { | 1350 | { |
1096 | struct usb_device *dev = interface_to_usbdev (intf); | 1351 | struct hid_device *hid = usb_get_intfdata(intf); |
1097 | 1352 | struct usbhid_device *usbhid = hid->driver_data; | |
1098 | hid_set_idle(dev, intf->cur_altsetting->desc.bInterfaceNumber, 0, 0); | ||
1099 | /* FIXME: Any more reinitialization needed? */ | ||
1100 | 1353 | ||
1101 | return hid_resume(intf); | 1354 | clear_bit(HID_REPORTED_IDLE, &usbhid->iofl); |
1355 | return hid_post_reset(intf); | ||
1102 | } | 1356 | } |
1103 | 1357 | ||
1358 | #endif /* CONFIG_PM */ | ||
1359 | |||
1104 | static struct usb_device_id hid_usb_ids [] = { | 1360 | static struct usb_device_id hid_usb_ids [] = { |
1105 | { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS, | 1361 | { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS, |
1106 | .bInterfaceClass = USB_INTERFACE_CLASS_HID }, | 1362 | .bInterfaceClass = USB_INTERFACE_CLASS_HID }, |
@@ -1113,9 +1369,11 @@ static struct usb_driver hid_driver = { | |||
1113 | .name = "usbhid", | 1369 | .name = "usbhid", |
1114 | .probe = hid_probe, | 1370 | .probe = hid_probe, |
1115 | .disconnect = hid_disconnect, | 1371 | .disconnect = hid_disconnect, |
1372 | #ifdef CONFIG_PM | ||
1116 | .suspend = hid_suspend, | 1373 | .suspend = hid_suspend, |
1117 | .resume = hid_resume, | 1374 | .resume = hid_resume, |
1118 | .reset_resume = hid_post_reset, | 1375 | .reset_resume = hid_reset_resume, |
1376 | #endif | ||
1119 | .pre_reset = hid_pre_reset, | 1377 | .pre_reset = hid_pre_reset, |
1120 | .post_reset = hid_post_reset, | 1378 | .post_reset = hid_post_reset, |
1121 | .id_table = hid_usb_ids, | 1379 | .id_table = hid_usb_ids, |
@@ -1134,7 +1392,11 @@ static struct hid_driver hid_usb_driver = { | |||
1134 | 1392 | ||
1135 | static int __init hid_init(void) | 1393 | static int __init hid_init(void) |
1136 | { | 1394 | { |
1137 | int retval; | 1395 | int retval = -ENOMEM; |
1396 | |||
1397 | resumption_waker = create_freezeable_workqueue("usbhid_resumer"); | ||
1398 | if (!resumption_waker) | ||
1399 | goto no_queue; | ||
1138 | retval = hid_register_driver(&hid_usb_driver); | 1400 | retval = hid_register_driver(&hid_usb_driver); |
1139 | if (retval) | 1401 | if (retval) |
1140 | goto hid_register_fail; | 1402 | goto hid_register_fail; |
@@ -1158,6 +1420,8 @@ hiddev_init_fail: | |||
1158 | usbhid_quirks_init_fail: | 1420 | usbhid_quirks_init_fail: |
1159 | hid_unregister_driver(&hid_usb_driver); | 1421 | hid_unregister_driver(&hid_usb_driver); |
1160 | hid_register_fail: | 1422 | hid_register_fail: |
1423 | destroy_workqueue(resumption_waker); | ||
1424 | no_queue: | ||
1161 | return retval; | 1425 | return retval; |
1162 | } | 1426 | } |
1163 | 1427 | ||
@@ -1167,6 +1431,7 @@ static void __exit hid_exit(void) | |||
1167 | hiddev_exit(); | 1431 | hiddev_exit(); |
1168 | usbhid_quirks_exit(); | 1432 | usbhid_quirks_exit(); |
1169 | hid_unregister_driver(&hid_usb_driver); | 1433 | hid_unregister_driver(&hid_usb_driver); |
1434 | destroy_workqueue(resumption_waker); | ||
1170 | } | 1435 | } |
1171 | 1436 | ||
1172 | module_init(hid_init); | 1437 | module_init(hid_init); |
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index aa214170baf4..e9b436d2d944 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c | |||
@@ -246,10 +246,12 @@ static int hiddev_release(struct inode * inode, struct file * file) | |||
246 | spin_unlock_irqrestore(&list->hiddev->list_lock, flags); | 246 | spin_unlock_irqrestore(&list->hiddev->list_lock, flags); |
247 | 247 | ||
248 | if (!--list->hiddev->open) { | 248 | if (!--list->hiddev->open) { |
249 | if (list->hiddev->exist) | 249 | if (list->hiddev->exist) { |
250 | usbhid_close(list->hiddev->hid); | 250 | usbhid_close(list->hiddev->hid); |
251 | else | 251 | usbhid_put_power(list->hiddev->hid); |
252 | } else { | ||
252 | kfree(list->hiddev); | 253 | kfree(list->hiddev); |
254 | } | ||
253 | } | 255 | } |
254 | 256 | ||
255 | kfree(list); | 257 | kfree(list); |
@@ -300,6 +302,17 @@ static int hiddev_open(struct inode *inode, struct file *file) | |||
300 | list_add_tail(&list->node, &hiddev_table[i]->list); | 302 | list_add_tail(&list->node, &hiddev_table[i]->list); |
301 | spin_unlock_irq(&list->hiddev->list_lock); | 303 | spin_unlock_irq(&list->hiddev->list_lock); |
302 | 304 | ||
305 | if (!list->hiddev->open++) | ||
306 | if (list->hiddev->exist) { | ||
307 | struct hid_device *hid = hiddev_table[i]->hid; | ||
308 | res = usbhid_get_power(hid); | ||
309 | if (res < 0) { | ||
310 | res = -EIO; | ||
311 | goto bail; | ||
312 | } | ||
313 | usbhid_open(hid); | ||
314 | } | ||
315 | |||
303 | return 0; | 316 | return 0; |
304 | bail: | 317 | bail: |
305 | file->private_data = NULL; | 318 | file->private_data = NULL; |
@@ -875,16 +888,21 @@ int hiddev_connect(struct hid_device *hid, unsigned int force) | |||
875 | hiddev->hid = hid; | 888 | hiddev->hid = hid; |
876 | hiddev->exist = 1; | 889 | hiddev->exist = 1; |
877 | 890 | ||
891 | /* when lock_kernel() usage is fixed in usb_open(), | ||
892 | * we could also fix it here */ | ||
893 | lock_kernel(); | ||
878 | retval = usb_register_dev(usbhid->intf, &hiddev_class); | 894 | retval = usb_register_dev(usbhid->intf, &hiddev_class); |
879 | if (retval) { | 895 | if (retval) { |
880 | err_hid("Not able to get a minor for this device."); | 896 | err_hid("Not able to get a minor for this device."); |
881 | hid->hiddev = NULL; | 897 | hid->hiddev = NULL; |
898 | unlock_kernel(); | ||
882 | kfree(hiddev); | 899 | kfree(hiddev); |
883 | return -1; | 900 | return -1; |
884 | } else { | 901 | } else { |
885 | hid->minor = usbhid->intf->minor; | 902 | hid->minor = usbhid->intf->minor; |
886 | hiddev_table[usbhid->intf->minor - HIDDEV_MINOR_BASE] = hiddev; | 903 | hiddev_table[usbhid->intf->minor - HIDDEV_MINOR_BASE] = hiddev; |
887 | } | 904 | } |
905 | unlock_kernel(); | ||
888 | 906 | ||
889 | return 0; | 907 | return 0; |
890 | } | 908 | } |
diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h index 9eb30564be9c..08f505ca2e3d 100644 --- a/drivers/hid/usbhid/usbhid.h +++ b/drivers/hid/usbhid/usbhid.h | |||
@@ -38,7 +38,10 @@ int usbhid_wait_io(struct hid_device* hid); | |||
38 | void usbhid_close(struct hid_device *hid); | 38 | void usbhid_close(struct hid_device *hid); |
39 | int usbhid_open(struct hid_device *hid); | 39 | 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 |
42 | (struct hid_device *hid, struct hid_report *report, unsigned char dir); | ||
43 | int usbhid_get_power(struct hid_device *hid); | ||
44 | void usbhid_put_power(struct hid_device *hid); | ||
42 | 45 | ||
43 | /* iofl flags */ | 46 | /* iofl flags */ |
44 | #define HID_CTRL_RUNNING 1 | 47 | #define HID_CTRL_RUNNING 1 |
@@ -49,6 +52,9 @@ void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, uns | |||
49 | #define HID_CLEAR_HALT 6 | 52 | #define HID_CLEAR_HALT 6 |
50 | #define HID_DISCONNECTED 7 | 53 | #define HID_DISCONNECTED 7 |
51 | #define HID_STARTED 8 | 54 | #define HID_STARTED 8 |
55 | #define HID_REPORTED_IDLE 9 | ||
56 | #define HID_KEYS_PRESSED 10 | ||
57 | #define HID_LED_ON 11 | ||
52 | 58 | ||
53 | /* | 59 | /* |
54 | * USB-specific HID struct, to be pointed to | 60 | * USB-specific HID struct, to be pointed to |
@@ -66,7 +72,6 @@ struct usbhid_device { | |||
66 | struct urb *urbin; /* Input URB */ | 72 | struct urb *urbin; /* Input URB */ |
67 | char *inbuf; /* Input buffer */ | 73 | char *inbuf; /* Input buffer */ |
68 | dma_addr_t inbuf_dma; /* Input buffer dma */ | 74 | dma_addr_t inbuf_dma; /* Input buffer dma */ |
69 | spinlock_t inlock; /* Input fifo spinlock */ | ||
70 | 75 | ||
71 | struct urb *urbctrl; /* Control URB */ | 76 | struct urb *urbctrl; /* Control URB */ |
72 | struct usb_ctrlrequest *cr; /* Control request struct */ | 77 | struct usb_ctrlrequest *cr; /* Control request struct */ |
@@ -75,21 +80,22 @@ struct usbhid_device { | |||
75 | unsigned char ctrlhead, ctrltail; /* Control fifo head & tail */ | 80 | unsigned char ctrlhead, ctrltail; /* Control fifo head & tail */ |
76 | char *ctrlbuf; /* Control buffer */ | 81 | char *ctrlbuf; /* Control buffer */ |
77 | dma_addr_t ctrlbuf_dma; /* Control buffer dma */ | 82 | dma_addr_t ctrlbuf_dma; /* Control buffer dma */ |
78 | spinlock_t ctrllock; /* Control fifo spinlock */ | ||
79 | 83 | ||
80 | struct urb *urbout; /* Output URB */ | 84 | struct urb *urbout; /* Output URB */ |
81 | struct hid_output_fifo out[HID_CONTROL_FIFO_SIZE]; /* Output pipe fifo */ | 85 | struct hid_output_fifo out[HID_CONTROL_FIFO_SIZE]; /* Output pipe fifo */ |
82 | unsigned char outhead, outtail; /* Output pipe fifo head & tail */ | 86 | unsigned char outhead, outtail; /* Output pipe fifo head & tail */ |
83 | char *outbuf; /* Output buffer */ | 87 | char *outbuf; /* Output buffer */ |
84 | dma_addr_t outbuf_dma; /* Output buffer dma */ | 88 | dma_addr_t outbuf_dma; /* Output buffer dma */ |
85 | spinlock_t outlock; /* Output fifo spinlock */ | ||
86 | 89 | ||
90 | spinlock_t lock; /* fifo spinlock */ | ||
87 | unsigned long iofl; /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */ | 91 | unsigned long iofl; /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */ |
88 | struct timer_list io_retry; /* Retry timer */ | 92 | struct timer_list io_retry; /* Retry timer */ |
89 | unsigned long stop_retry; /* Time to give up, in jiffies */ | 93 | unsigned long stop_retry; /* Time to give up, in jiffies */ |
90 | unsigned int retry_delay; /* Delay length in ms */ | 94 | unsigned int retry_delay; /* Delay length in ms */ |
91 | struct work_struct reset_work; /* Task context for resets */ | 95 | struct work_struct reset_work; /* Task context for resets */ |
96 | struct work_struct restart_work; /* waking up for output to be done in a task */ | ||
92 | wait_queue_head_t wait; /* For sleeping */ | 97 | wait_queue_head_t wait; /* For sleeping */ |
98 | int ledcount; /* counting the number of active leds */ | ||
93 | }; | 99 | }; |
94 | 100 | ||
95 | #define hid_to_usb_dev(hid_dev) \ | 101 | #define hid_to_usb_dev(hid_dev) \ |