Commit 5fba0925fd6b67d94181055b7222e3d934b4efee
Exists in
master
and in
7 other branches
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
Showing 35 changed files Side-by-side Diff
- Documentation/feature-removal-schedule.txt
- drivers/hid/Kconfig
- drivers/hid/Makefile
- drivers/hid/hid-a4tech.c
- drivers/hid/hid-apple.c
- drivers/hid/hid-belkin.c
- drivers/hid/hid-cherry.c
- drivers/hid/hid-chicony.c
- drivers/hid/hid-core.c
- drivers/hid/hid-cypress.c
- drivers/hid/hid-drff.c
- drivers/hid/hid-dummy.c
- drivers/hid/hid-ezkey.c
- drivers/hid/hid-gaff.c
- drivers/hid/hid-gyration.c
- drivers/hid/hid-ids.h
- drivers/hid/hid-kensington.c
- drivers/hid/hid-kye.c
- drivers/hid/hid-lg.c
- drivers/hid/hid-microsoft.c
- drivers/hid/hid-monterey.c
- drivers/hid/hid-ntrig.c
- drivers/hid/hid-petalynx.c
- drivers/hid/hid-pl.c
- drivers/hid/hid-samsung.c
- drivers/hid/hid-sony.c
- drivers/hid/hid-sunplus.c
- drivers/hid/hid-tmff.c
- drivers/hid/hid-topseed.c
- drivers/hid/hid-zpff.c
- drivers/hid/hidraw.c
- drivers/hid/usbhid/hid-core.c
- drivers/hid/usbhid/hiddev.c
- drivers/hid/usbhid/usbhid.h
- include/linux/hid.h
Documentation/feature-removal-schedule.txt
... | ... | @@ -283,13 +283,6 @@ |
283 | 283 | |
284 | 284 | --------------------------- |
285 | 285 | |
286 | -What: remove HID compat support | |
287 | -When: 2.6.29 | |
288 | -Why: needed only as a temporary solution until distros fix themselves up | |
289 | -Who: Jiri Slaby <jirislaby@gmail.com> | |
290 | - | |
291 | ---------------------------- | |
292 | - | |
293 | 286 | What: print_fn_descriptor_symbol() |
294 | 287 | When: October 2009 |
295 | 288 | Why: The %pF vsprintf format provides the same functionality in a |
drivers/hid/Kconfig
... | ... | @@ -29,11 +29,11 @@ |
29 | 29 | |
30 | 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 | 34 | config HID_DEBUG |
35 | 35 | bool "HID debugging support" |
36 | - default y if !EMBEDDED | |
36 | + default y | |
37 | 37 | depends on HID |
38 | 38 | ---help--- |
39 | 39 | This option lets the HID layer output diagnostics about its internal |
... | ... | @@ -44,7 +44,7 @@ |
44 | 44 | This feature is useful for those who are either debugging the HID parser |
45 | 45 | or any HID hardware device. |
46 | 46 | |
47 | - If unsure, say N | |
47 | + If unsure, say Y. | |
48 | 48 | |
49 | 49 | config HIDRAW |
50 | 50 | bool "/dev/hidraw raw HID device support" |
... | ... | @@ -70,18 +70,6 @@ |
70 | 70 | menu "Special HID drivers" |
71 | 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 | 73 | config HID_A4TECH |
86 | 74 | tristate "A4 tech" if EMBEDDED |
87 | 75 | depends on USB_HID |
... | ... | @@ -128,6 +116,14 @@ |
128 | 116 | ---help--- |
129 | 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 | 127 | config HID_EZKEY |
132 | 128 | tristate "Ezkey" if EMBEDDED |
133 | 129 | depends on USB_HID |
134 | 130 | |
... | ... | @@ -135,12 +131,26 @@ |
135 | 131 | ---help--- |
136 | 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 | 141 | config HID_GYRATION |
139 | 142 | tristate "Gyration" if EMBEDDED |
140 | 143 | depends on USB_HID |
141 | 144 | default !EMBEDDED |
142 | 145 | ---help--- |
143 | 146 | Support for Gyration remote control. |
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. | |
144 | 154 | |
145 | 155 | config HID_LOGITECH |
146 | 156 | tristate "Logitech" if EMBEDDED |
drivers/hid/Makefile
... | ... | @@ -8,10 +8,6 @@ |
8 | 8 | hid-$(CONFIG_HID_DEBUG) += hid-debug.o |
9 | 9 | hid-$(CONFIG_HIDRAW) += hidraw.o |
10 | 10 | |
11 | -ifdef CONFIG_HID_COMPAT | |
12 | -obj-m += hid-dummy.o | |
13 | -endif | |
14 | - | |
15 | 11 | hid-logitech-objs := hid-lg.o |
16 | 12 | ifdef CONFIG_LOGITECH_FF |
17 | 13 | hid-logitech-objs += hid-lgff.o |
18 | 14 | |
... | ... | @@ -26,8 +22,11 @@ |
26 | 22 | obj-$(CONFIG_HID_CHERRY) += hid-cherry.o |
27 | 23 | obj-$(CONFIG_HID_CHICONY) += hid-chicony.o |
28 | 24 | obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o |
25 | +obj-$(CONFIG_DRAGONRISE_FF) += hid-drff.o | |
29 | 26 | obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o |
30 | 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 | 30 | obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o |
32 | 31 | obj-$(CONFIG_HID_MICROSOFT) += hid-microsoft.o |
33 | 32 | obj-$(CONFIG_HID_MONTEREY) += hid-monterey.o |
drivers/hid/hid-a4tech.c
drivers/hid/hid-apple.c
... | ... | @@ -53,7 +53,7 @@ |
53 | 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 | 57 | { KEY_BACKSPACE, KEY_DELETE }, |
58 | 58 | { KEY_ENTER, KEY_INSERT }, |
59 | 59 | { KEY_F1, KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY }, |
... | ... | @@ -75,7 +75,7 @@ |
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 | 79 | { KEY_BACKSPACE, KEY_DELETE }, |
80 | 80 | { KEY_F1, KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY }, |
81 | 81 | { KEY_F2, KEY_BRIGHTNESSUP, APPLE_FLAG_FKEY }, |
... | ... | @@ -94,7 +94,7 @@ |
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 | 98 | { KEY_J, KEY_KP1 }, |
99 | 99 | { KEY_K, KEY_KP2 }, |
100 | 100 | { KEY_L, KEY_KP3 }, |
101 | 101 | |
102 | 102 | |
... | ... | @@ -117,16 +117,16 @@ |
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 | 121 | { KEY_GRAVE, KEY_102ND }, |
122 | 122 | { KEY_102ND, KEY_GRAVE }, |
123 | 123 | { } |
124 | 124 | }; |
125 | 125 | |
126 | -static struct apple_key_translation *apple_find_translation( | |
127 | - struct apple_key_translation *table, u16 from) | |
126 | +static const struct apple_key_translation *apple_find_translation( | |
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 | 131 | /* Look for the translation */ |
132 | 132 | for (trans = table; trans->from; trans++) |
... | ... | @@ -140,7 +140,7 @@ |
140 | 140 | struct hid_usage *usage, __s32 value) |
141 | 141 | { |
142 | 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 | 145 | if (usage->code == KEY_FN) { |
146 | 146 | asc->fn_on = !!value; |
... | ... | @@ -253,7 +253,7 @@ |
253 | 253 | |
254 | 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 | 258 | set_bit(KEY_NUMLOCK, input->keybit); |
259 | 259 | |
... | ... | @@ -387,6 +387,12 @@ |
387 | 387 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS), |
388 | 388 | .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN | |
389 | 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 | 396 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ANSI), |
391 | 397 | .driver_data = APPLE_HAS_FN }, |
392 | 398 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ISO), |
... | ... | @@ -468,6 +474,4 @@ |
468 | 474 | module_init(apple_init); |
469 | 475 | module_exit(apple_exit); |
470 | 476 | MODULE_LICENSE("GPL"); |
471 | - | |
472 | -HID_COMPAT_LOAD_DRIVER(apple); |
drivers/hid/hid-belkin.c
drivers/hid/hid-cherry.c
drivers/hid/hid-chicony.c
drivers/hid/hid-core.c
... | ... | @@ -1236,6 +1236,9 @@ |
1236 | 1236 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI) }, |
1237 | 1237 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO) }, |
1238 | 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 | 1242 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ANSI) }, |
1240 | 1243 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ISO) }, |
1241 | 1244 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_JIS) }, |
... | ... | @@ -1262,6 +1265,7 @@ |
1262 | 1265 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) }, |
1263 | 1266 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) }, |
1264 | 1267 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE) }, |
1268 | + { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) }, | |
1265 | 1269 | { HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) }, |
1266 | 1270 | { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) }, |
1267 | 1271 | { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR) }, |
... | ... | @@ -1269,6 +1273,8 @@ |
1269 | 1273 | { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0012) }, |
1270 | 1274 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) }, |
1271 | 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 | 1278 | { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) }, |
1273 | 1279 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) }, |
1274 | 1280 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) }, |
1275 | 1281 | |
1276 | 1282 | |
1277 | 1283 | |
... | ... | @@ -1813,15 +1819,22 @@ |
1813 | 1819 | } |
1814 | 1820 | EXPORT_SYMBOL_GPL(hid_unregister_driver); |
1815 | 1821 | |
1816 | -#ifdef CONFIG_HID_COMPAT | |
1817 | -static void hid_compat_load(struct work_struct *ws) | |
1822 | +int hid_check_keys_pressed(struct hid_device *hid) | |
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); | |
1822 | -static struct workqueue_struct *hid_compat_wq; | |
1823 | -#endif | |
1824 | 1835 | |
1836 | +EXPORT_SYMBOL_GPL(hid_check_keys_pressed); | |
1837 | + | |
1825 | 1838 | static int __init hid_init(void) |
1826 | 1839 | { |
1827 | 1840 | int ret; |
... | ... | @@ -1836,15 +1849,6 @@ |
1836 | 1849 | if (ret) |
1837 | 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 | 1852 | return 0; |
1849 | 1853 | err_bus: |
1850 | 1854 | bus_unregister(&hid_bus_type); |
... | ... | @@ -1854,9 +1858,6 @@ |
1854 | 1858 | |
1855 | 1859 | static void __exit hid_exit(void) |
1856 | 1860 | { |
1857 | -#ifdef CONFIG_HID_COMPAT | |
1858 | - destroy_workqueue(hid_compat_wq); | |
1859 | -#endif | |
1860 | 1861 | hidraw_exit(); |
1861 | 1862 | bus_unregister(&hid_bus_type); |
1862 | 1863 | } |
drivers/hid/hid-cypress.c
drivers/hid/hid-drff.c
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"); |
drivers/hid/hid-dummy.c
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"); |
drivers/hid/hid-ezkey.c
drivers/hid/hid-gaff.c
drivers/hid/hid-gyration.c
drivers/hid/hid-ids.h
... | ... | @@ -67,6 +67,9 @@ |
67 | 67 | #define USB_DEVICE_ID_APPLE_GEYSER4_ANSI 0x021a |
68 | 68 | #define USB_DEVICE_ID_APPLE_GEYSER4_ISO 0x021b |
69 | 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 | 73 | #define USB_DEVICE_ID_APPLE_ALU_ANSI 0x0220 |
71 | 74 | #define USB_DEVICE_ID_APPLE_ALU_ISO 0x0221 |
72 | 75 | #define USB_DEVICE_ID_APPLE_ALU_JIS 0x0222 |
... | ... | @@ -148,6 +151,8 @@ |
148 | 151 | #define USB_VENDOR_ID_DMI 0x0c0b |
149 | 152 | #define USB_DEVICE_ID_DMI_ENC 0x5fab |
150 | 153 | |
154 | +#define USB_VENDOR_ID_DRAGONRISE 0x0079 | |
155 | + | |
151 | 156 | #define USB_VENDOR_ID_ELO 0x04E7 |
152 | 157 | #define USB_DEVICE_ID_ELO_TS2700 0x0020 |
153 | 158 | |
... | ... | @@ -272,6 +277,9 @@ |
272 | 277 | #define USB_DEVICE_ID_LD_POWERCONTROL 0x2030 |
273 | 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 | 283 | #define USB_VENDOR_ID_LOGITECH 0x046d |
276 | 284 | #define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101 |
277 | 285 | #define USB_DEVICE_ID_LOGITECH_HARMONY_FIRST 0xc110 |
278 | 286 | |
... | ... | @@ -418,7 +426,9 @@ |
418 | 426 | #define USB_VENDOR_ID_ZEROPLUS 0x0c12 |
419 | 427 | |
420 | 428 | #define USB_VENDOR_ID_KYE 0x0458 |
429 | +#define USB_DEVICE_ID_KYE_ERGO_525V 0x0087 | |
421 | 430 | #define USB_DEVICE_ID_KYE_GPEN_560 0x5003 |
431 | + | |
422 | 432 | |
423 | 433 | #endif |
drivers/hid/hid-kensington.c
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"); |
drivers/hid/hid-kye.c
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"); |
drivers/hid/hid-lg.c
drivers/hid/hid-microsoft.c
drivers/hid/hid-monterey.c
drivers/hid/hid-ntrig.c
drivers/hid/hid-petalynx.c
drivers/hid/hid-pl.c
... | ... | @@ -9,9 +9,12 @@ |
9 | 9 | * - contains two reports, one for each port (HID_QUIRK_MULTI_INPUT) |
10 | 10 | * |
11 | 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 | 50 | struct plff_device { |
48 | 51 | struct hid_report *report; |
52 | + s32 *strong; | |
53 | + s32 *weak; | |
49 | 54 | }; |
50 | 55 | |
51 | 56 | static int hid_plff_play(struct input_dev *dev, void *data, |
... | ... | @@ -62,8 +67,8 @@ |
62 | 67 | left = left * 0x7f / 0xffff; |
63 | 68 | right = right * 0x7f / 0xffff; |
64 | 69 | |
65 | - plff->report->field[0]->value[2] = left; | |
66 | - plff->report->field[0]->value[3] = right; | |
70 | + *plff->strong = left; | |
71 | + *plff->weak = right; | |
67 | 72 | debug("running with 0x%02x 0x%02x", left, right); |
68 | 73 | usbhid_submit_report(hid, plff->report, USB_DIR_OUT); |
69 | 74 | |
... | ... | @@ -80,6 +85,8 @@ |
80 | 85 | struct list_head *report_ptr = report_list; |
81 | 86 | struct input_dev *dev; |
82 | 87 | int error; |
88 | + s32 *strong; | |
89 | + s32 *weak; | |
83 | 90 | |
84 | 91 | /* The device contains one output report per physical device, all |
85 | 92 | containing 1 field, which contains 4 ff00.0002 usages and 4 16bit |
... | ... | @@ -87,7 +94,12 @@ |
87 | 94 | |
88 | 95 | The input reports also contain a field which contains |
89 | 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 | 104 | if (list_empty(report_list)) { |
93 | 105 | dev_err(&hid->dev, "no output reports found\n"); |
... | ... | @@ -110,8 +122,21 @@ |
110 | 122 | return -ENODEV; |
111 | 123 | } |
112 | 124 | |
113 | - if (report->field[0]->report_count < 4) { | |
114 | - dev_err(&hid->dev, "not enough values in the field\n"); | |
125 | + if (report->field[0]->report_count >= 4) { | |
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 | 140 | return -ENODEV; |
116 | 141 | } |
117 | 142 | |
... | ... | @@ -130,10 +155,11 @@ |
130 | 155 | } |
131 | 156 | |
132 | 157 | plff->report = report; |
133 | - plff->report->field[0]->value[0] = 0x00; | |
134 | - plff->report->field[0]->value[1] = 0x00; | |
135 | - plff->report->field[0]->value[2] = 0x00; | |
136 | - plff->report->field[0]->value[3] = 0x00; | |
158 | + plff->strong = strong; | |
159 | + plff->weak = weak; | |
160 | + | |
161 | + *strong = 0x00; | |
162 | + *weak = 0x00; | |
137 | 163 | usbhid_submit_report(hid, plff->report, USB_DIR_OUT); |
138 | 164 | } |
139 | 165 | |
... | ... | @@ -180,7 +206,7 @@ |
180 | 206 | .driver_data = 1 }, /* Twin USB Joystick */ |
181 | 207 | { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR), |
182 | 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 | 212 | MODULE_DEVICE_TABLE(hid, pl_devices); |
... | ... | @@ -204,6 +230,4 @@ |
204 | 230 | module_init(pl_init); |
205 | 231 | module_exit(pl_exit); |
206 | 232 | MODULE_LICENSE("GPL"); |
207 | - | |
208 | -HID_COMPAT_LOAD_DRIVER(pantherlord); |
drivers/hid/hid-samsung.c
drivers/hid/hid-sony.c
drivers/hid/hid-sunplus.c
drivers/hid/hid-tmff.c
drivers/hid/hid-topseed.c
drivers/hid/hid-zpff.c
drivers/hid/hidraw.c
... | ... | @@ -181,9 +181,17 @@ |
181 | 181 | |
182 | 182 | dev = hidraw_table[minor]; |
183 | 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 | 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 | 193 | dev->open--; |
194 | + } | |
187 | 195 | } |
188 | 196 | |
189 | 197 | out_unlock: |
190 | 198 | |
191 | 199 | |
... | ... | @@ -209,10 +217,13 @@ |
209 | 217 | list_del(&list->node); |
210 | 218 | dev = hidraw_table[minor]; |
211 | 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 | 223 | dev->hid->ll_driver->close(dev->hid); |
214 | - else | |
224 | + } else { | |
215 | 225 | kfree(list->hidraw); |
226 | + } | |
216 | 227 | } |
217 | 228 | |
218 | 229 | kfree(list); |
drivers/hid/usbhid/hid-core.c
... | ... | @@ -5,6 +5,7 @@ |
5 | 5 | * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> |
6 | 6 | * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc |
7 | 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 | 28 | #include <asm/byteorder.h> |
28 | 29 | #include <linux/input.h> |
29 | 30 | #include <linux/wait.h> |
31 | +#include <linux/workqueue.h> | |
30 | 32 | |
31 | 33 | #include <linux/usb.h> |
32 | 34 | |
... | ... | @@ -53,6 +55,10 @@ |
53 | 55 | module_param_named(mousepoll, hid_mousepoll_interval, uint, 0644); |
54 | 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 | 62 | /* Quirks specified at module load time */ |
57 | 63 | static char *quirks_param[MAX_USBHID_BOOT_QUIRKS] = { [ 0 ... (MAX_USBHID_BOOT_QUIRKS - 1) ] = NULL }; |
58 | 64 | module_param_array_named(quirks, quirks_param, charp, NULL, 0444); |
59 | 65 | |
... | ... | @@ -63,8 +69,13 @@ |
63 | 69 | /* |
64 | 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 | 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 | 80 | /* Start up the input URB */ |
70 | 81 | static int hid_start_in(struct hid_device *hid) |
71 | 82 | |
72 | 83 | |
... | ... | @@ -73,15 +84,16 @@ |
73 | 84 | int rc = 0; |
74 | 85 | struct usbhid_device *usbhid = hid->driver_data; |
75 | 86 | |
76 | - spin_lock_irqsave(&usbhid->inlock, flags); | |
77 | - if (hid->open > 0 && !test_bit(HID_SUSPENDED, &usbhid->iofl) && | |
87 | + spin_lock_irqsave(&usbhid->lock, flags); | |
88 | + if (hid->open > 0 && | |
78 | 89 | !test_bit(HID_DISCONNECTED, &usbhid->iofl) && |
90 | + !test_bit(HID_REPORTED_IDLE, &usbhid->iofl) && | |
79 | 91 | !test_and_set_bit(HID_IN_RUNNING, &usbhid->iofl)) { |
80 | 92 | rc = usb_submit_urb(usbhid->urbin, GFP_ATOMIC); |
81 | 93 | if (rc != 0) |
82 | 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 | 97 | return rc; |
86 | 98 | } |
87 | 99 | |
... | ... | @@ -145,7 +157,7 @@ |
145 | 157 | unsigned long flags; |
146 | 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 | 162 | /* Stop when disconnected */ |
151 | 163 | if (test_bit(HID_DISCONNECTED, &usbhid->iofl)) |
152 | 164 | |
... | ... | @@ -175,9 +187,53 @@ |
175 | 187 | mod_timer(&usbhid->io_retry, |
176 | 188 | jiffies + msecs_to_jiffies(usbhid->retry_delay)); |
177 | 189 | done: |
178 | - spin_unlock_irqrestore(&usbhid->inlock, flags); | |
190 | + spin_unlock_irqrestore(&usbhid->lock, flags); | |
179 | 191 | } |
180 | 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; | |
235 | +} | |
236 | + | |
181 | 237 | /* |
182 | 238 | * Input interrupt completion handler. |
183 | 239 | */ |
184 | 240 | |
185 | 241 | |
... | ... | @@ -190,12 +246,23 @@ |
190 | 246 | |
191 | 247 | switch (urb->status) { |
192 | 248 | case 0: /* success */ |
249 | + usbhid_mark_busy(usbhid); | |
193 | 250 | usbhid->retry_delay = 0; |
194 | 251 | hid_input_report(urb->context, HID_INPUT_REPORT, |
195 | 252 | urb->transfer_buffer, |
196 | 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 | 263 | break; |
198 | 264 | case -EPIPE: /* stall */ |
265 | + usbhid_mark_busy(usbhid); | |
199 | 266 | clear_bit(HID_IN_RUNNING, &usbhid->iofl); |
200 | 267 | set_bit(HID_CLEAR_HALT, &usbhid->iofl); |
201 | 268 | schedule_work(&usbhid->reset_work); |
... | ... | @@ -209,6 +276,7 @@ |
209 | 276 | case -EPROTO: /* protocol error or unplug */ |
210 | 277 | case -ETIME: /* protocol error or unplug */ |
211 | 278 | case -ETIMEDOUT: /* Should never happen, but... */ |
279 | + usbhid_mark_busy(usbhid); | |
212 | 280 | clear_bit(HID_IN_RUNNING, &usbhid->iofl); |
213 | 281 | hid_io_error(hid); |
214 | 282 | return; |
215 | 283 | |
216 | 284 | |
... | ... | @@ -239,16 +307,25 @@ |
239 | 307 | report = usbhid->out[usbhid->outtail].report; |
240 | 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); | |
243 | - usbhid->urbout->dev = hid_to_usb_dev(hid); | |
244 | - memcpy(usbhid->outbuf, raw_report, usbhid->urbout->transfer_buffer_length); | |
245 | - kfree(raw_report); | |
310 | + if (!test_bit(HID_REPORTED_IDLE, &usbhid->iofl)) { | |
311 | + usbhid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + (report->id > 0); | |
312 | + usbhid->urbout->dev = hid_to_usb_dev(hid); | |
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)) { | |
250 | - err_hid("usb_submit_urb(out) failed"); | |
251 | - return -1; | |
318 | + if (usb_submit_urb(usbhid->urbout, GFP_ATOMIC)) { | |
319 | + err_hid("usb_submit_urb(out) failed"); | |
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 | 331 | return 0; |
255 | 332 | |
256 | 333 | |
257 | 334 | |
258 | 335 | |
... | ... | @@ -266,41 +343,50 @@ |
266 | 343 | raw_report = usbhid->ctrl[usbhid->ctrltail].raw_report; |
267 | 344 | dir = usbhid->ctrl[usbhid->ctrltail].dir; |
268 | 345 | |
269 | - len = ((report->size - 1) >> 3) + 1 + (report->id > 0); | |
270 | - if (dir == USB_DIR_OUT) { | |
271 | - usbhid->urbctrl->pipe = usb_sndctrlpipe(hid_to_usb_dev(hid), 0); | |
272 | - usbhid->urbctrl->transfer_buffer_length = len; | |
273 | - memcpy(usbhid->ctrlbuf, raw_report, len); | |
274 | - kfree(raw_report); | |
275 | - } else { | |
276 | - int maxpacket, padlen; | |
346 | + if (!test_bit(HID_REPORTED_IDLE, &usbhid->iofl)) { | |
347 | + len = ((report->size - 1) >> 3) + 1 + (report->id > 0); | |
348 | + if (dir == USB_DIR_OUT) { | |
349 | + usbhid->urbctrl->pipe = usb_sndctrlpipe(hid_to_usb_dev(hid), 0); | |
350 | + usbhid->urbctrl->transfer_buffer_length = len; | |
351 | + memcpy(usbhid->ctrlbuf, raw_report, len); | |
352 | + kfree(raw_report); | |
353 | + } else { | |
354 | + int maxpacket, padlen; | |
277 | 355 | |
278 | - usbhid->urbctrl->pipe = usb_rcvctrlpipe(hid_to_usb_dev(hid), 0); | |
279 | - maxpacket = usb_maxpacket(hid_to_usb_dev(hid), usbhid->urbctrl->pipe, 0); | |
280 | - if (maxpacket > 0) { | |
281 | - padlen = DIV_ROUND_UP(len, maxpacket); | |
282 | - padlen *= maxpacket; | |
283 | - if (padlen > usbhid->bufsize) | |
284 | - padlen = usbhid->bufsize; | |
285 | - } else | |
286 | - padlen = 0; | |
287 | - usbhid->urbctrl->transfer_buffer_length = padlen; | |
288 | - } | |
289 | - usbhid->urbctrl->dev = hid_to_usb_dev(hid); | |
356 | + usbhid->urbctrl->pipe = usb_rcvctrlpipe(hid_to_usb_dev(hid), 0); | |
357 | + maxpacket = usb_maxpacket(hid_to_usb_dev(hid), usbhid->urbctrl->pipe, 0); | |
358 | + if (maxpacket > 0) { | |
359 | + padlen = DIV_ROUND_UP(len, maxpacket); | |
360 | + padlen *= maxpacket; | |
361 | + if (padlen > usbhid->bufsize) | |
362 | + padlen = usbhid->bufsize; | |
363 | + } else | |
364 | + padlen = 0; | |
365 | + usbhid->urbctrl->transfer_buffer_length = padlen; | |
366 | + } | |
367 | + usbhid->urbctrl->dev = hid_to_usb_dev(hid); | |
290 | 368 | |
291 | - 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; | |
293 | - usbhid->cr->wValue = cpu_to_le16(((report->type + 1) << 8) | report->id); | |
294 | - usbhid->cr->wIndex = cpu_to_le16(usbhid->ifnum); | |
295 | - usbhid->cr->wLength = cpu_to_le16(len); | |
369 | + usbhid->cr->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE | dir; | |
370 | + usbhid->cr->bRequest = (dir == USB_DIR_OUT) ? HID_REQ_SET_REPORT : HID_REQ_GET_REPORT; | |
371 | + usbhid->cr->wValue = cpu_to_le16(((report->type + 1) << 8) | report->id); | |
372 | + usbhid->cr->wIndex = cpu_to_le16(usbhid->ifnum); | |
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", | |
298 | - usbhid->cr->bRequest == HID_REQ_SET_REPORT ? "Set_Report" : "Get_Report", | |
299 | - usbhid->cr->wValue, usbhid->cr->wIndex, usbhid->cr->wLength); | |
375 | + dbg_hid("submitting ctrl urb: %s wValue=0x%04x wIndex=0x%04x wLength=%u\n", | |
376 | + usbhid->cr->bRequest == HID_REQ_SET_REPORT ? "Set_Report" : "Get_Report", | |
377 | + usbhid->cr->wValue, usbhid->cr->wIndex, usbhid->cr->wLength); | |
300 | 378 | |
301 | - if (usb_submit_urb(usbhid->urbctrl, GFP_ATOMIC)) { | |
302 | - err_hid("usb_submit_urb(ctrl) failed"); | |
303 | - return -1; | |
379 | + if (usb_submit_urb(usbhid->urbctrl, GFP_ATOMIC)) { | |
380 | + err_hid("usb_submit_urb(ctrl) failed"); | |
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 | 392 | return 0; |
... | ... | @@ -332,7 +418,7 @@ |
332 | 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 | 423 | if (unplug) |
338 | 424 | usbhid->outtail = usbhid->outhead; |
339 | 425 | |
... | ... | @@ -344,12 +430,12 @@ |
344 | 430 | clear_bit(HID_OUT_RUNNING, &usbhid->iofl); |
345 | 431 | wake_up(&usbhid->wait); |
346 | 432 | } |
347 | - spin_unlock_irqrestore(&usbhid->outlock, flags); | |
433 | + spin_unlock_irqrestore(&usbhid->lock, flags); | |
348 | 434 | return; |
349 | 435 | } |
350 | 436 | |
351 | 437 | clear_bit(HID_OUT_RUNNING, &usbhid->iofl); |
352 | - spin_unlock_irqrestore(&usbhid->outlock, flags); | |
438 | + spin_unlock_irqrestore(&usbhid->lock, flags); | |
353 | 439 | wake_up(&usbhid->wait); |
354 | 440 | } |
355 | 441 | |
356 | 442 | |
357 | 443 | |
... | ... | @@ -361,12 +447,11 @@ |
361 | 447 | { |
362 | 448 | struct hid_device *hid = urb->context; |
363 | 449 | struct usbhid_device *usbhid = hid->driver_data; |
364 | - unsigned long flags; | |
365 | - int unplug = 0; | |
450 | + int unplug = 0, status = urb->status; | |
366 | 451 | |
367 | - spin_lock_irqsave(&usbhid->ctrllock, flags); | |
452 | + spin_lock(&usbhid->lock); | |
368 | 453 | |
369 | - switch (urb->status) { | |
454 | + switch (status) { | |
370 | 455 | case 0: /* success */ |
371 | 456 | if (usbhid->ctrl[usbhid->ctrltail].dir == USB_DIR_IN) |
372 | 457 | hid_input_report(urb->context, |
... | ... | @@ -383,7 +468,7 @@ |
383 | 468 | break; |
384 | 469 | default: /* error */ |
385 | 470 | dev_warn(&urb->dev->dev, "ctrl urb status %d " |
386 | - "received\n", urb->status); | |
471 | + "received\n", status); | |
387 | 472 | } |
388 | 473 | |
389 | 474 | if (unplug) |
390 | 475 | |
391 | 476 | |
392 | 477 | |
... | ... | @@ -396,19 +481,18 @@ |
396 | 481 | clear_bit(HID_CTRL_RUNNING, &usbhid->iofl); |
397 | 482 | wake_up(&usbhid->wait); |
398 | 483 | } |
399 | - spin_unlock_irqrestore(&usbhid->ctrllock, flags); | |
484 | + spin_unlock(&usbhid->lock); | |
400 | 485 | return; |
401 | 486 | } |
402 | 487 | |
403 | 488 | clear_bit(HID_CTRL_RUNNING, &usbhid->iofl); |
404 | - spin_unlock_irqrestore(&usbhid->ctrllock, flags); | |
489 | + spin_unlock(&usbhid->lock); | |
405 | 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 | 495 | int head; |
411 | - unsigned long flags; | |
412 | 496 | struct usbhid_device *usbhid = hid->driver_data; |
413 | 497 | int len = ((report->size - 1) >> 3) + 1 + (report->id > 0); |
414 | 498 | |
415 | 499 | |
416 | 500 | |
... | ... | @@ -416,18 +500,13 @@ |
416 | 500 | return; |
417 | 501 | |
418 | 502 | if (usbhid->urbout && dir == USB_DIR_OUT && report->type == HID_OUTPUT_REPORT) { |
419 | - | |
420 | - spin_lock_irqsave(&usbhid->outlock, flags); | |
421 | - | |
422 | 503 | if ((head = (usbhid->outhead + 1) & (HID_OUTPUT_FIFO_SIZE - 1)) == usbhid->outtail) { |
423 | - spin_unlock_irqrestore(&usbhid->outlock, flags); | |
424 | 504 | dev_warn(&hid->dev, "output queue full\n"); |
425 | 505 | return; |
426 | 506 | } |
427 | 507 | |
428 | 508 | usbhid->out[usbhid->outhead].raw_report = kmalloc(len, GFP_ATOMIC); |
429 | 509 | if (!usbhid->out[usbhid->outhead].raw_report) { |
430 | - spin_unlock_irqrestore(&usbhid->outlock, flags); | |
431 | 510 | dev_warn(&hid->dev, "output queueing failed\n"); |
432 | 511 | return; |
433 | 512 | } |
434 | 513 | |
435 | 514 | |
... | ... | @@ -438,15 +517,10 @@ |
438 | 517 | if (!test_and_set_bit(HID_OUT_RUNNING, &usbhid->iofl)) |
439 | 518 | if (hid_submit_out(hid)) |
440 | 519 | clear_bit(HID_OUT_RUNNING, &usbhid->iofl); |
441 | - | |
442 | - spin_unlock_irqrestore(&usbhid->outlock, flags); | |
443 | 520 | return; |
444 | 521 | } |
445 | 522 | |
446 | - spin_lock_irqsave(&usbhid->ctrllock, flags); | |
447 | - | |
448 | 523 | if ((head = (usbhid->ctrlhead + 1) & (HID_CONTROL_FIFO_SIZE - 1)) == usbhid->ctrltail) { |
449 | - spin_unlock_irqrestore(&usbhid->ctrllock, flags); | |
450 | 524 | dev_warn(&hid->dev, "control queue full\n"); |
451 | 525 | return; |
452 | 526 | } |
... | ... | @@ -454,7 +528,6 @@ |
454 | 528 | if (dir == USB_DIR_OUT) { |
455 | 529 | usbhid->ctrl[usbhid->ctrlhead].raw_report = kmalloc(len, GFP_ATOMIC); |
456 | 530 | if (!usbhid->ctrl[usbhid->ctrlhead].raw_report) { |
457 | - spin_unlock_irqrestore(&usbhid->ctrllock, flags); | |
458 | 531 | dev_warn(&hid->dev, "control queueing failed\n"); |
459 | 532 | return; |
460 | 533 | } |
461 | 534 | |
462 | 535 | |
463 | 536 | |
... | ... | @@ -467,15 +540,25 @@ |
467 | 540 | if (!test_and_set_bit(HID_CTRL_RUNNING, &usbhid->iofl)) |
468 | 541 | if (hid_submit_ctrl(hid)) |
469 | 542 | clear_bit(HID_CTRL_RUNNING, &usbhid->iofl); |
543 | +} | |
470 | 544 | |
471 | - spin_unlock_irqrestore(&usbhid->ctrllock, flags); | |
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; | |
549 | + | |
550 | + spin_lock_irqsave(&usbhid->lock, flags); | |
551 | + __usbhid_submit_report(hid, report, dir); | |
552 | + spin_unlock_irqrestore(&usbhid->lock, flags); | |
472 | 553 | } |
473 | 554 | EXPORT_SYMBOL_GPL(usbhid_submit_report); |
474 | 555 | |
475 | 556 | static int usb_hidinput_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) |
476 | 557 | { |
477 | 558 | struct hid_device *hid = input_get_drvdata(dev); |
559 | + struct usbhid_device *usbhid = hid->driver_data; | |
478 | 560 | struct hid_field *field; |
561 | + unsigned long flags; | |
479 | 562 | int offset; |
480 | 563 | |
481 | 564 | if (type == EV_FF) |
... | ... | @@ -490,6 +573,15 @@ |
490 | 573 | } |
491 | 574 | |
492 | 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 | 585 | usbhid_submit_report(hid, field->report, USB_DIR_OUT); |
494 | 586 | |
495 | 587 | return 0; |
496 | 588 | |
497 | 589 | |
498 | 590 | |
499 | 591 | |
... | ... | @@ -538,15 +630,22 @@ |
538 | 630 | struct usbhid_device *usbhid = hid->driver_data; |
539 | 631 | int res; |
540 | 632 | |
633 | + mutex_lock(&hid_open_mut); | |
541 | 634 | if (!hid->open++) { |
542 | 635 | res = usb_autopm_get_interface(usbhid->intf); |
636 | + /* the device must be awake to reliable request remote wakeup */ | |
543 | 637 | if (res < 0) { |
544 | 638 | hid->open--; |
639 | + mutex_unlock(&hid_open_mut); | |
545 | 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)) | |
549 | - hid_io_error(hid); | |
648 | + mutex_unlock(&hid_open_mut); | |
550 | 649 | return 0; |
551 | 650 | } |
552 | 651 | |
553 | 652 | |
554 | 653 | |
555 | 654 | |
... | ... | @@ -554,10 +653,22 @@ |
554 | 653 | { |
555 | 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 | 663 | if (!--hid->open) { |
664 | + spin_unlock_irq(&usbhid->lock); | |
558 | 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 @@ |
687 | 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 | 820 | static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid) |
691 | 821 | { |
692 | 822 | struct usbhid_device *usbhid = hid->driver_data; |
... | ... | @@ -711,6 +841,9 @@ |
711 | 841 | quirks = usbhid_lookup_quirk(le16_to_cpu(dev->descriptor.idVendor), |
712 | 842 | le16_to_cpu(dev->descriptor.idProduct)); |
713 | 843 | |
844 | + if (quirks & HID_QUIRK_IGNORE) | |
845 | + return -ENODEV; | |
846 | + | |
714 | 847 | /* Many keyboards and mice don't like to be polled for reports, |
715 | 848 | * so we will always set the HID_QUIRK_NOGET flag for them. */ |
716 | 849 | if (interface->desc.bInterfaceSubClass == USB_INTERFACE_SUBCLASS_BOOT) { |
717 | 850 | |
... | ... | @@ -850,11 +983,11 @@ |
850 | 983 | |
851 | 984 | init_waitqueue_head(&usbhid->wait); |
852 | 985 | INIT_WORK(&usbhid->reset_work, hid_reset); |
986 | + INIT_WORK(&usbhid->restart_work, __usbhid_restart_queues); | |
853 | 987 | setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid); |
854 | 988 | |
855 | - spin_lock_init(&usbhid->inlock); | |
856 | - spin_lock_init(&usbhid->outlock); | |
857 | - spin_lock_init(&usbhid->ctrllock); | |
989 | + spin_lock_init(&usbhid->lock); | |
990 | + spin_lock_init(&usbhid->lock); | |
858 | 991 | |
859 | 992 | usbhid->intf = intf; |
860 | 993 | usbhid->ifnum = interface->desc.bInterfaceNumber; |
861 | 994 | |
862 | 995 | |
... | ... | @@ -906,15 +1039,14 @@ |
906 | 1039 | return; |
907 | 1040 | |
908 | 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 | 1043 | set_bit(HID_DISCONNECTED, &usbhid->iofl); |
911 | - spin_unlock_irq(&usbhid->inlock); | |
1044 | + spin_unlock_irq(&usbhid->lock); | |
912 | 1045 | usb_kill_urb(usbhid->urbin); |
913 | 1046 | usb_kill_urb(usbhid->urbout); |
914 | 1047 | usb_kill_urb(usbhid->urbctrl); |
915 | 1048 | |
916 | - del_timer_sync(&usbhid->io_retry); | |
917 | - cancel_work_sync(&usbhid->reset_work); | |
1049 | + hid_cancel_delayed_stuff(usbhid); | |
918 | 1050 | |
919 | 1051 | if (hid->claimed & HID_CLAIMED_INPUT) |
920 | 1052 | hidinput_disconnect(hid); |
921 | 1053 | |
... | ... | @@ -935,12 +1067,28 @@ |
935 | 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 | 1085 | static struct hid_ll_driver usb_hid_driver = { |
939 | 1086 | .parse = usbhid_parse, |
940 | 1087 | .start = usbhid_start, |
941 | 1088 | .stop = usbhid_stop, |
942 | 1089 | .open = usbhid_open, |
943 | 1090 | .close = usbhid_close, |
1091 | + .power = usbhid_power, | |
944 | 1092 | .hidinput_input_event = usb_hidinput_input_event, |
945 | 1093 | }; |
946 | 1094 | |
947 | 1095 | |
948 | 1096 | |
949 | 1097 | |
950 | 1098 | |
... | ... | @@ -1049,19 +1197,126 @@ |
1049 | 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 | 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 | 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)) | |
1058 | - return 0; | |
1274 | + if (udev->auto_pm) { | |
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 */ | |
1061 | - set_bit(HID_SUSPENDED, &usbhid->iofl); | |
1062 | - spin_unlock_irq(&usbhid->inlock); | |
1063 | - del_timer_sync(&usbhid->io_retry); | |
1064 | - usb_kill_urb(usbhid->urbin); | |
1291 | + } else { | |
1292 | + spin_lock_irq(&usbhid->lock); | |
1293 | + set_bit(HID_REPORTED_IDLE, &usbhid->iofl); | |
1294 | + spin_unlock_irq(&usbhid->lock); | |
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 | 1320 | dev_dbg(&intf->dev, "suspend\n"); |
1066 | 1321 | return 0; |
1067 | 1322 | } |
1068 | 1323 | |
1069 | 1324 | |
1070 | 1325 | |
1071 | 1326 | |
1072 | 1327 | |
1073 | 1328 | |
... | ... | @@ -1075,32 +1330,33 @@ |
1075 | 1330 | if (!test_bit(HID_STARTED, &usbhid->iofl)) |
1076 | 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 | 1339 | usbhid->retry_delay = 0; |
1080 | 1340 | status = hid_start_in(hid); |
1081 | - dev_dbg(&intf->dev, "resume status %d\n", status); | |
1082 | - return status; | |
1083 | -} | |
1341 | + if (status < 0) | |
1342 | + hid_io_error(hid); | |
1343 | + usbhid_restart_queues(usbhid); | |
1084 | 1344 | |
1085 | -/* Treat USB reset pretty much the same as suspend/resume */ | |
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); | |
1345 | + dev_dbg(&intf->dev, "resume status %d\n", status); | |
1090 | 1346 | return 0; |
1091 | 1347 | } |
1092 | 1348 | |
1093 | -/* Same routine used for post_reset and reset_resume */ | |
1094 | -static int hid_post_reset(struct usb_interface *intf) | |
1349 | +static int hid_reset_resume(struct usb_interface *intf) | |
1095 | 1350 | { |
1096 | - struct usb_device *dev = interface_to_usbdev (intf); | |
1351 | + struct hid_device *hid = usb_get_intfdata(intf); | |
1352 | + struct usbhid_device *usbhid = hid->driver_data; | |
1097 | 1353 | |
1098 | - hid_set_idle(dev, intf->cur_altsetting->desc.bInterfaceNumber, 0, 0); | |
1099 | - /* FIXME: Any more reinitialization needed? */ | |
1100 | - | |
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 | 1360 | static struct usb_device_id hid_usb_ids [] = { |
1105 | 1361 | { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS, |
1106 | 1362 | .bInterfaceClass = USB_INTERFACE_CLASS_HID }, |
1107 | 1363 | |
... | ... | @@ -1113,9 +1369,11 @@ |
1113 | 1369 | .name = "usbhid", |
1114 | 1370 | .probe = hid_probe, |
1115 | 1371 | .disconnect = hid_disconnect, |
1372 | +#ifdef CONFIG_PM | |
1116 | 1373 | .suspend = hid_suspend, |
1117 | 1374 | .resume = hid_resume, |
1118 | - .reset_resume = hid_post_reset, | |
1375 | + .reset_resume = hid_reset_resume, | |
1376 | +#endif | |
1119 | 1377 | .pre_reset = hid_pre_reset, |
1120 | 1378 | .post_reset = hid_post_reset, |
1121 | 1379 | .id_table = hid_usb_ids, |
... | ... | @@ -1134,7 +1392,11 @@ |
1134 | 1392 | |
1135 | 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 | 1400 | retval = hid_register_driver(&hid_usb_driver); |
1139 | 1401 | if (retval) |
1140 | 1402 | goto hid_register_fail; |
... | ... | @@ -1158,6 +1420,8 @@ |
1158 | 1420 | usbhid_quirks_init_fail: |
1159 | 1421 | hid_unregister_driver(&hid_usb_driver); |
1160 | 1422 | hid_register_fail: |
1423 | + destroy_workqueue(resumption_waker); | |
1424 | +no_queue: | |
1161 | 1425 | return retval; |
1162 | 1426 | } |
1163 | 1427 | |
... | ... | @@ -1167,6 +1431,7 @@ |
1167 | 1431 | hiddev_exit(); |
1168 | 1432 | usbhid_quirks_exit(); |
1169 | 1433 | hid_unregister_driver(&hid_usb_driver); |
1434 | + destroy_workqueue(resumption_waker); | |
1170 | 1435 | } |
1171 | 1436 | |
1172 | 1437 | module_init(hid_init); |
drivers/hid/usbhid/hiddev.c
... | ... | @@ -246,10 +246,12 @@ |
246 | 246 | spin_unlock_irqrestore(&list->hiddev->list_lock, flags); |
247 | 247 | |
248 | 248 | if (!--list->hiddev->open) { |
249 | - if (list->hiddev->exist) | |
249 | + if (list->hiddev->exist) { | |
250 | 250 | usbhid_close(list->hiddev->hid); |
251 | - else | |
251 | + usbhid_put_power(list->hiddev->hid); | |
252 | + } else { | |
252 | 253 | kfree(list->hiddev); |
254 | + } | |
253 | 255 | } |
254 | 256 | |
255 | 257 | kfree(list); |
... | ... | @@ -300,6 +302,17 @@ |
300 | 302 | list_add_tail(&list->node, &hiddev_table[i]->list); |
301 | 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 | 316 | return 0; |
304 | 317 | bail: |
305 | 318 | file->private_data = NULL; |
306 | 319 | |
307 | 320 | |
... | ... | @@ -875,16 +888,21 @@ |
875 | 888 | hiddev->hid = hid; |
876 | 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 | 894 | retval = usb_register_dev(usbhid->intf, &hiddev_class); |
879 | 895 | if (retval) { |
880 | 896 | err_hid("Not able to get a minor for this device."); |
881 | 897 | hid->hiddev = NULL; |
898 | + unlock_kernel(); | |
882 | 899 | kfree(hiddev); |
883 | 900 | return -1; |
884 | 901 | } else { |
885 | 902 | hid->minor = usbhid->intf->minor; |
886 | 903 | hiddev_table[usbhid->intf->minor - HIDDEV_MINOR_BASE] = hiddev; |
887 | 904 | } |
905 | + unlock_kernel(); | |
888 | 906 | |
889 | 907 | return 0; |
890 | 908 | } |
drivers/hid/usbhid/usbhid.h
... | ... | @@ -38,7 +38,10 @@ |
38 | 38 | void usbhid_close(struct hid_device *hid); |
39 | 39 | int usbhid_open(struct hid_device *hid); |
40 | 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 | 46 | /* iofl flags */ |
44 | 47 | #define HID_CTRL_RUNNING 1 |
... | ... | @@ -49,6 +52,9 @@ |
49 | 52 | #define HID_CLEAR_HALT 6 |
50 | 53 | #define HID_DISCONNECTED 7 |
51 | 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 | 60 | * USB-specific HID struct, to be pointed to |
... | ... | @@ -66,7 +72,6 @@ |
66 | 72 | struct urb *urbin; /* Input URB */ |
67 | 73 | char *inbuf; /* Input buffer */ |
68 | 74 | dma_addr_t inbuf_dma; /* Input buffer dma */ |
69 | - spinlock_t inlock; /* Input fifo spinlock */ | |
70 | 75 | |
71 | 76 | struct urb *urbctrl; /* Control URB */ |
72 | 77 | struct usb_ctrlrequest *cr; /* Control request struct */ |
73 | 78 | |
74 | 79 | |
75 | 80 | |
76 | 81 | |
... | ... | @@ -75,21 +80,22 @@ |
75 | 80 | unsigned char ctrlhead, ctrltail; /* Control fifo head & tail */ |
76 | 81 | char *ctrlbuf; /* Control buffer */ |
77 | 82 | dma_addr_t ctrlbuf_dma; /* Control buffer dma */ |
78 | - spinlock_t ctrllock; /* Control fifo spinlock */ | |
79 | 83 | |
80 | 84 | struct urb *urbout; /* Output URB */ |
81 | 85 | struct hid_output_fifo out[HID_CONTROL_FIFO_SIZE]; /* Output pipe fifo */ |
82 | 86 | unsigned char outhead, outtail; /* Output pipe fifo head & tail */ |
83 | 87 | char *outbuf; /* Output buffer */ |
84 | 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 | 91 | unsigned long iofl; /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */ |
88 | 92 | struct timer_list io_retry; /* Retry timer */ |
89 | 93 | unsigned long stop_retry; /* Time to give up, in jiffies */ |
90 | 94 | unsigned int retry_delay; /* Delay length in ms */ |
91 | 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 | 97 | wait_queue_head_t wait; /* For sleeping */ |
98 | + int ledcount; /* counting the number of active leds */ | |
93 | 99 | }; |
94 | 100 | |
95 | 101 | #define hid_to_usb_dev(hid_dev) \ |
include/linux/hid.h
... | ... | @@ -270,6 +270,7 @@ |
270 | 270 | |
271 | 271 | #define HID_QUIRK_INVERT 0x00000001 |
272 | 272 | #define HID_QUIRK_NOTOUCH 0x00000002 |
273 | +#define HID_QUIRK_IGNORE 0x00000004 | |
273 | 274 | #define HID_QUIRK_NOGET 0x00000008 |
274 | 275 | #define HID_QUIRK_BADPAD 0x00000020 |
275 | 276 | #define HID_QUIRK_MULTI_INPUT 0x00000040 |
276 | 277 | |
... | ... | @@ -603,12 +604,17 @@ |
603 | 604 | int (*open)(struct hid_device *hdev); |
604 | 605 | void (*close)(struct hid_device *hdev); |
605 | 606 | |
607 | + int (*power)(struct hid_device *hdev, int level); | |
608 | + | |
606 | 609 | int (*hidinput_input_event) (struct input_dev *idev, unsigned int type, |
607 | 610 | unsigned int code, int value); |
608 | 611 | |
609 | 612 | int (*parse)(struct hid_device *hdev); |
610 | 613 | }; |
611 | 614 | |
615 | +#define PM_HINT_FULLON 1<<5 | |
616 | +#define PM_HINT_NORMAL 1<<1 | |
617 | + | |
612 | 618 | /* Applications from HID Usage Tables 4/8/99 Version 1.1 */ |
613 | 619 | /* We ignore a few input applications that are not widely used */ |
614 | 620 | #define IS_INPUT_APPLICATION(a) (((a >= 0x00010000) && (a <= 0x00010008)) || (a == 0x00010080) || (a == 0x000c0001) || (a == 0x000d0002)) |
... | ... | @@ -641,6 +647,7 @@ |
641 | 647 | void hid_output_report(struct hid_report *report, __u8 *data); |
642 | 648 | struct hid_device *hid_allocate_device(void); |
643 | 649 | int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size); |
650 | +int hid_check_keys_pressed(struct hid_device *hid); | |
644 | 651 | int hid_connect(struct hid_device *hid, unsigned int connect_mask); |
645 | 652 | |
646 | 653 | /** |
... | ... | @@ -790,22 +797,6 @@ |
790 | 797 | #define err_hid(format, arg...) printk(KERN_ERR "%s: " format "\n" , \ |
791 | 798 | __FILE__ , ## arg) |
792 | 799 | #endif /* HID_FF */ |
793 | - | |
794 | -#ifdef __KERNEL__ | |
795 | -#ifdef CONFIG_HID_COMPAT | |
796 | -#define HID_COMPAT_LOAD_DRIVER(name) \ | |
797 | -/* prototype to avoid sparse warning */ \ | |
798 | -extern void hid_compat_##name(void); \ | |
799 | -void hid_compat_##name(void) { } \ | |
800 | -EXPORT_SYMBOL(hid_compat_##name) | |
801 | -#else | |
802 | -#define HID_COMPAT_LOAD_DRIVER(name) | |
803 | -#endif /* HID_COMPAT */ | |
804 | -#define HID_COMPAT_CALL_DRIVER(name) do { \ | |
805 | - extern void hid_compat_##name(void); \ | |
806 | - hid_compat_##name(); \ | |
807 | -} while (0) | |
808 | -#endif /* __KERNEL__ */ | |
809 | 800 | |
810 | 801 | #endif |