diff options
Diffstat (limited to 'drivers/hid')
35 files changed, 730 insertions, 224 deletions
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 7831a0318d3c..24d90ea246ce 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig | |||
@@ -31,21 +31,6 @@ config HID | |||
31 | 31 | ||
32 | If unsure, say Y. | 32 | If unsure, say Y. |
33 | 33 | ||
34 | config HID_DEBUG | ||
35 | bool "HID debugging support" | ||
36 | default y | ||
37 | depends on HID | ||
38 | ---help--- | ||
39 | This option lets the HID layer output diagnostics about its internal | ||
40 | state, resolve HID usages, dump HID fields, etc. Individual HID drivers | ||
41 | use this debugging facility to output information about individual HID | ||
42 | devices, etc. | ||
43 | |||
44 | This feature is useful for those who are either debugging the HID parser | ||
45 | or any HID hardware device. | ||
46 | |||
47 | If unsure, say Y. | ||
48 | |||
49 | config HIDRAW | 34 | config HIDRAW |
50 | bool "/dev/hidraw raw HID device support" | 35 | bool "/dev/hidraw raw HID device support" |
51 | depends on HID | 36 | depends on HID |
@@ -152,6 +137,13 @@ config HID_GYRATION | |||
152 | ---help--- | 137 | ---help--- |
153 | Support for Gyration remote control. | 138 | Support for Gyration remote control. |
154 | 139 | ||
140 | config HID_TWINHAN | ||
141 | tristate "Twinhan" if EMBEDDED | ||
142 | depends on USB_HID | ||
143 | default !EMBEDDED | ||
144 | ---help--- | ||
145 | Support for Twinhan IR remote control. | ||
146 | |||
155 | config HID_KENSINGTON | 147 | config HID_KENSINGTON |
156 | tristate "Kensington" if EMBEDDED | 148 | tristate "Kensington" if EMBEDDED |
157 | depends on USB_HID | 149 | depends on USB_HID |
@@ -176,6 +168,7 @@ config LOGITECH_FF | |||
176 | - Logitech WingMan Cordless RumblePad 2 | 168 | - Logitech WingMan Cordless RumblePad 2 |
177 | - Logitech WingMan Force 3D | 169 | - Logitech WingMan Force 3D |
178 | - Logitech Formula Force EX | 170 | - Logitech Formula Force EX |
171 | - Logitech WingMan Formula Force GP | ||
179 | - Logitech MOMO Force wheel | 172 | - Logitech MOMO Force wheel |
180 | 173 | ||
181 | and if you want to enable force feedback for them. | 174 | and if you want to enable force feedback for them. |
@@ -212,13 +205,6 @@ config HID_NTRIG | |||
212 | Support for N-Trig touch screen. | 205 | Support for N-Trig touch screen. |
213 | 206 | ||
214 | config HID_PANTHERLORD | 207 | config HID_PANTHERLORD |
215 | tristate "Pantherlord devices support" if EMBEDDED | ||
216 | depends on USB_HID | ||
217 | default !EMBEDDED | ||
218 | ---help--- | ||
219 | Support for PantherLord/GreenAsia based device support. | ||
220 | |||
221 | config HID_PANTHERLORD | ||
222 | tristate "Pantherlord support" if EMBEDDED | 208 | tristate "Pantherlord support" if EMBEDDED |
223 | depends on USB_HID | 209 | depends on USB_HID |
224 | default !EMBEDDED | 210 | default !EMBEDDED |
@@ -314,9 +300,9 @@ config THRUSTMASTER_FF | |||
314 | depends on HID_THRUSTMASTER | 300 | depends on HID_THRUSTMASTER |
315 | select INPUT_FF_MEMLESS | 301 | select INPUT_FF_MEMLESS |
316 | ---help--- | 302 | ---help--- |
317 | Say Y here if you have a THRUSTMASTER FireStore Dual Power 2 or | 303 | Say Y here if you have a THRUSTMASTER FireStore Dual Power 2 or 3, |
318 | a THRUSTMASTER Ferrari GT Rumble Force or Force Feedback Wheel and | 304 | a THRUSTMASTER Dual Trigger 3-in-1 or a THRUSTMASTER Ferrari GT |
319 | want to enable force feedback support for it. | 305 | Rumble Force or Force Feedback Wheel. |
320 | 306 | ||
321 | config HID_WACOM | 307 | config HID_WACOM |
322 | tristate "Wacom Bluetooth devices support" if EMBEDDED | 308 | tristate "Wacom Bluetooth devices support" if EMBEDDED |
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index db35151673b1..0de2dff5542c 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile | |||
@@ -3,9 +3,12 @@ | |||
3 | # | 3 | # |
4 | hid-objs := hid-core.o hid-input.o | 4 | hid-objs := hid-core.o hid-input.o |
5 | 5 | ||
6 | ifdef CONFIG_DEBUG_FS | ||
7 | hid-objs += hid-debug.o | ||
8 | endif | ||
9 | |||
6 | obj-$(CONFIG_HID) += hid.o | 10 | obj-$(CONFIG_HID) += hid.o |
7 | 11 | ||
8 | hid-$(CONFIG_HID_DEBUG) += hid-debug.o | ||
9 | hid-$(CONFIG_HIDRAW) += hidraw.o | 12 | hid-$(CONFIG_HIDRAW) += hidraw.o |
10 | 13 | ||
11 | hid-logitech-objs := hid-lg.o | 14 | hid-logitech-objs := hid-lg.o |
@@ -40,6 +43,7 @@ obj-$(CONFIG_HID_SUNPLUS) += hid-sunplus.o | |||
40 | obj-$(CONFIG_HID_GREENASIA) += hid-gaff.o | 43 | obj-$(CONFIG_HID_GREENASIA) += hid-gaff.o |
41 | obj-$(CONFIG_HID_THRUSTMASTER) += hid-tmff.o | 44 | obj-$(CONFIG_HID_THRUSTMASTER) += hid-tmff.o |
42 | obj-$(CONFIG_HID_TOPSEED) += hid-topseed.o | 45 | obj-$(CONFIG_HID_TOPSEED) += hid-topseed.o |
46 | obj-$(CONFIG_HID_TWINHAN) += hid-twinhan.o | ||
43 | obj-$(CONFIG_HID_ZEROPLUS) += hid-zpff.o | 47 | obj-$(CONFIG_HID_ZEROPLUS) += hid-zpff.o |
44 | obj-$(CONFIG_HID_WACOM) += hid-wacom.o | 48 | obj-$(CONFIG_HID_WACOM) += hid-wacom.o |
45 | 49 | ||
diff --git a/drivers/hid/hid-a4tech.c b/drivers/hid/hid-a4tech.c index 42ea359e94cf..df474c699fb8 100644 --- a/drivers/hid/hid-a4tech.c +++ b/drivers/hid/hid-a4tech.c | |||
@@ -145,12 +145,12 @@ static struct hid_driver a4_driver = { | |||
145 | .remove = a4_remove, | 145 | .remove = a4_remove, |
146 | }; | 146 | }; |
147 | 147 | ||
148 | static int a4_init(void) | 148 | static int __init a4_init(void) |
149 | { | 149 | { |
150 | return hid_register_driver(&a4_driver); | 150 | return hid_register_driver(&a4_driver); |
151 | } | 151 | } |
152 | 152 | ||
153 | static void a4_exit(void) | 153 | static void __exit a4_exit(void) |
154 | { | 154 | { |
155 | hid_unregister_driver(&a4_driver); | 155 | hid_unregister_driver(&a4_driver); |
156 | } | 156 | } |
diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index 303ccce05bb3..4b96e7a898cf 100644 --- a/drivers/hid/hid-apple.c +++ b/drivers/hid/hid-apple.c | |||
@@ -451,7 +451,7 @@ static struct hid_driver apple_driver = { | |||
451 | .input_mapped = apple_input_mapped, | 451 | .input_mapped = apple_input_mapped, |
452 | }; | 452 | }; |
453 | 453 | ||
454 | static int apple_init(void) | 454 | static int __init apple_init(void) |
455 | { | 455 | { |
456 | int ret; | 456 | int ret; |
457 | 457 | ||
@@ -462,7 +462,7 @@ static int apple_init(void) | |||
462 | return ret; | 462 | return ret; |
463 | } | 463 | } |
464 | 464 | ||
465 | static void apple_exit(void) | 465 | static void __exit apple_exit(void) |
466 | { | 466 | { |
467 | hid_unregister_driver(&apple_driver); | 467 | hid_unregister_driver(&apple_driver); |
468 | } | 468 | } |
diff --git a/drivers/hid/hid-belkin.c b/drivers/hid/hid-belkin.c index 2f6723133a4b..4ce7aa3a519f 100644 --- a/drivers/hid/hid-belkin.c +++ b/drivers/hid/hid-belkin.c | |||
@@ -88,12 +88,12 @@ static struct hid_driver belkin_driver = { | |||
88 | .probe = belkin_probe, | 88 | .probe = belkin_probe, |
89 | }; | 89 | }; |
90 | 90 | ||
91 | static int belkin_init(void) | 91 | static int __init belkin_init(void) |
92 | { | 92 | { |
93 | return hid_register_driver(&belkin_driver); | 93 | return hid_register_driver(&belkin_driver); |
94 | } | 94 | } |
95 | 95 | ||
96 | static void belkin_exit(void) | 96 | static void __exit belkin_exit(void) |
97 | { | 97 | { |
98 | hid_unregister_driver(&belkin_driver); | 98 | hid_unregister_driver(&belkin_driver); |
99 | } | 99 | } |
diff --git a/drivers/hid/hid-cherry.c b/drivers/hid/hid-cherry.c index ab8209e7e45c..7e597d7f770f 100644 --- a/drivers/hid/hid-cherry.c +++ b/drivers/hid/hid-cherry.c | |||
@@ -70,12 +70,12 @@ static struct hid_driver ch_driver = { | |||
70 | .input_mapping = ch_input_mapping, | 70 | .input_mapping = ch_input_mapping, |
71 | }; | 71 | }; |
72 | 72 | ||
73 | static int ch_init(void) | 73 | static int __init ch_init(void) |
74 | { | 74 | { |
75 | return hid_register_driver(&ch_driver); | 75 | return hid_register_driver(&ch_driver); |
76 | } | 76 | } |
77 | 77 | ||
78 | static void ch_exit(void) | 78 | static void __exit ch_exit(void) |
79 | { | 79 | { |
80 | hid_unregister_driver(&ch_driver); | 80 | hid_unregister_driver(&ch_driver); |
81 | } | 81 | } |
diff --git a/drivers/hid/hid-chicony.c b/drivers/hid/hid-chicony.c index 7f91076d8493..8965ad93d510 100644 --- a/drivers/hid/hid-chicony.c +++ b/drivers/hid/hid-chicony.c | |||
@@ -63,12 +63,12 @@ static struct hid_driver ch_driver = { | |||
63 | .input_mapping = ch_input_mapping, | 63 | .input_mapping = ch_input_mapping, |
64 | }; | 64 | }; |
65 | 65 | ||
66 | static int ch_init(void) | 66 | static int __init ch_init(void) |
67 | { | 67 | { |
68 | return hid_register_driver(&ch_driver); | 68 | return hid_register_driver(&ch_driver); |
69 | } | 69 | } |
70 | 70 | ||
71 | static void ch_exit(void) | 71 | static void __exit ch_exit(void) |
72 | { | 72 | { |
73 | hid_unregister_driver(&ch_driver); | 73 | hid_unregister_driver(&ch_driver); |
74 | } | 74 | } |
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 5eb10c2ce665..be34d32906bd 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
@@ -44,12 +44,10 @@ | |||
44 | #define DRIVER_DESC "HID core driver" | 44 | #define DRIVER_DESC "HID core driver" |
45 | #define DRIVER_LICENSE "GPL" | 45 | #define DRIVER_LICENSE "GPL" |
46 | 46 | ||
47 | #ifdef CONFIG_HID_DEBUG | ||
48 | int hid_debug = 0; | 47 | int hid_debug = 0; |
49 | module_param_named(debug, hid_debug, int, 0600); | 48 | module_param_named(debug, hid_debug, int, 0600); |
50 | MODULE_PARM_DESC(debug, "HID debugging (0=off, 1=probing info, 2=continuous data dumping)"); | 49 | MODULE_PARM_DESC(debug, "toggle HID debugging messages"); |
51 | EXPORT_SYMBOL_GPL(hid_debug); | 50 | EXPORT_SYMBOL_GPL(hid_debug); |
52 | #endif | ||
53 | 51 | ||
54 | /* | 52 | /* |
55 | * Register a new report for a device. | 53 | * Register a new report for a device. |
@@ -861,7 +859,7 @@ static void hid_process_event(struct hid_device *hid, struct hid_field *field, | |||
861 | struct hid_driver *hdrv = hid->driver; | 859 | struct hid_driver *hdrv = hid->driver; |
862 | int ret; | 860 | int ret; |
863 | 861 | ||
864 | hid_dump_input(usage, value); | 862 | hid_dump_input(hid, usage, value); |
865 | 863 | ||
866 | if (hdrv && hdrv->event && hid_match_usage(hid, usage)) { | 864 | if (hdrv && hdrv->event && hid_match_usage(hid, usage)) { |
867 | ret = hdrv->event(hid, field, usage, value); | 865 | ret = hdrv->event(hid, field, usage, value); |
@@ -983,11 +981,10 @@ int hid_set_field(struct hid_field *field, unsigned offset, __s32 value) | |||
983 | { | 981 | { |
984 | unsigned size = field->report_size; | 982 | unsigned size = field->report_size; |
985 | 983 | ||
986 | hid_dump_input(field->usage + offset, value); | 984 | hid_dump_input(field->report->device, field->usage + offset, value); |
987 | 985 | ||
988 | if (offset >= field->report_count) { | 986 | if (offset >= field->report_count) { |
989 | dbg_hid("offset (%d) exceeds report_count (%d)\n", offset, field->report_count); | 987 | dbg_hid("offset (%d) exceeds report_count (%d)\n", offset, field->report_count); |
990 | hid_dump_field(field, 8); | ||
991 | return -1; | 988 | return -1; |
992 | } | 989 | } |
993 | if (field->logical_minimum < 0) { | 990 | if (field->logical_minimum < 0) { |
@@ -1078,6 +1075,7 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i | |||
1078 | struct hid_report_enum *report_enum; | 1075 | struct hid_report_enum *report_enum; |
1079 | struct hid_driver *hdrv; | 1076 | struct hid_driver *hdrv; |
1080 | struct hid_report *report; | 1077 | struct hid_report *report; |
1078 | char *buf; | ||
1081 | unsigned int i; | 1079 | unsigned int i; |
1082 | int ret; | 1080 | int ret; |
1083 | 1081 | ||
@@ -1091,18 +1089,37 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i | |||
1091 | return -1; | 1089 | return -1; |
1092 | } | 1090 | } |
1093 | 1091 | ||
1094 | dbg_hid("report (size %u) (%snumbered)\n", size, report_enum->numbered ? "" : "un"); | 1092 | buf = kmalloc(sizeof(char) * HID_DEBUG_BUFSIZE, GFP_ATOMIC); |
1093 | |||
1094 | if (!buf) { | ||
1095 | report = hid_get_report(report_enum, data); | ||
1096 | goto nomem; | ||
1097 | } | ||
1098 | |||
1099 | snprintf(buf, HID_DEBUG_BUFSIZE - 1, | ||
1100 | "\nreport (size %u) (%snumbered)\n", size, report_enum->numbered ? "" : "un"); | ||
1101 | hid_debug_event(hid, buf); | ||
1095 | 1102 | ||
1096 | report = hid_get_report(report_enum, data); | 1103 | report = hid_get_report(report_enum, data); |
1097 | if (!report) | 1104 | if (!report) { |
1105 | kfree(buf); | ||
1098 | return -1; | 1106 | return -1; |
1107 | } | ||
1099 | 1108 | ||
1100 | /* dump the report */ | 1109 | /* dump the report */ |
1101 | dbg_hid("report %d (size %u) = ", report->id, size); | 1110 | snprintf(buf, HID_DEBUG_BUFSIZE - 1, |
1102 | for (i = 0; i < size; i++) | 1111 | "report %d (size %u) = ", report->id, size); |
1103 | dbg_hid_line(" %02x", data[i]); | 1112 | hid_debug_event(hid, buf); |
1104 | dbg_hid_line("\n"); | 1113 | for (i = 0; i < size; i++) { |
1114 | snprintf(buf, HID_DEBUG_BUFSIZE - 1, | ||
1115 | " %02x", data[i]); | ||
1116 | hid_debug_event(hid, buf); | ||
1117 | } | ||
1118 | hid_debug_event(hid, "\n"); | ||
1119 | |||
1120 | kfree(buf); | ||
1105 | 1121 | ||
1122 | nomem: | ||
1106 | if (hdrv && hdrv->raw_event && hid_match_report(hid, report)) { | 1123 | if (hdrv && hdrv->raw_event && hid_match_report(hid, report)) { |
1107 | ret = hdrv->raw_event(hid, report, data, size); | 1124 | ret = hdrv->raw_event(hid, report, data, size); |
1108 | if (ret != 0) | 1125 | if (ret != 0) |
@@ -1220,6 +1237,17 @@ int hid_connect(struct hid_device *hdev, unsigned int connect_mask) | |||
1220 | } | 1237 | } |
1221 | EXPORT_SYMBOL_GPL(hid_connect); | 1238 | EXPORT_SYMBOL_GPL(hid_connect); |
1222 | 1239 | ||
1240 | void hid_disconnect(struct hid_device *hdev) | ||
1241 | { | ||
1242 | if (hdev->claimed & HID_CLAIMED_INPUT) | ||
1243 | hidinput_disconnect(hdev); | ||
1244 | if (hdev->claimed & HID_CLAIMED_HIDDEV) | ||
1245 | hdev->hiddev_disconnect(hdev); | ||
1246 | if (hdev->claimed & HID_CLAIMED_HIDRAW) | ||
1247 | hidraw_disconnect(hdev); | ||
1248 | } | ||
1249 | EXPORT_SYMBOL_GPL(hid_disconnect); | ||
1250 | |||
1223 | /* a list of devices for which there is a specialized driver on HID bus */ | 1251 | /* a list of devices for which there is a specialized driver on HID bus */ |
1224 | static const struct hid_device_id hid_blacklist[] = { | 1252 | static const struct hid_device_id hid_blacklist[] = { |
1225 | { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU) }, | 1253 | { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU) }, |
@@ -1292,6 +1320,7 @@ static const struct hid_device_id hid_blacklist[] = { | |||
1292 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD) }, | 1320 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD) }, |
1293 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2) }, | 1321 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2) }, |
1294 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_F3D) }, | 1322 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_F3D) }, |
1323 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ) }, | ||
1295 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FORCE3D_PRO) }, | 1324 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FORCE3D_PRO) }, |
1296 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL) }, | 1325 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL) }, |
1297 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2) }, | 1326 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2) }, |
@@ -1311,15 +1340,17 @@ static const struct hid_device_id hid_blacklist[] = { | |||
1311 | { HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) }, | 1340 | { HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) }, |
1312 | { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300) }, | 1341 | { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300) }, |
1313 | { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304) }, | 1342 | { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304) }, |
1343 | { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb323) }, | ||
1344 | { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb324) }, | ||
1314 | { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb651) }, | 1345 | { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb651) }, |
1315 | { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb654) }, | 1346 | { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb654) }, |
1316 | { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) }, | 1347 | { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) }, |
1348 | { HID_USB_DEVICE(USB_VENDOR_ID_TWINHAN, USB_DEVICE_ID_TWINHAN_IR_REMOTE) }, | ||
1317 | { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) }, | 1349 | { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) }, |
1318 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) }, | 1350 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) }, |
1319 | { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) }, | 1351 | { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) }, |
1320 | { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) }, | 1352 | { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) }, |
1321 | 1353 | ||
1322 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, 0x030c) }, | ||
1323 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT) }, | 1354 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT) }, |
1324 | { } | 1355 | { } |
1325 | }; | 1356 | }; |
@@ -1622,12 +1653,8 @@ static const struct hid_device_id hid_ignore_list[] = { | |||
1622 | { HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0002) }, | 1653 | { HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0002) }, |
1623 | { HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0003) }, | 1654 | { HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0003) }, |
1624 | { HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0004) }, | 1655 | { HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0004) }, |
1656 | { HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS, USB_DEVICE_ID_PHILIPS_IEEE802154_DONGLE) }, | ||
1625 | { HID_USB_DEVICE(USB_VENDOR_ID_POWERCOM, USB_DEVICE_ID_POWERCOM_UPS) }, | 1657 | { HID_USB_DEVICE(USB_VENDOR_ID_POWERCOM, USB_DEVICE_ID_POWERCOM_UPS) }, |
1626 | { HID_USB_DEVICE(USB_VENDOR_ID_SOUNDGRAPH, USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD) }, | ||
1627 | { HID_USB_DEVICE(USB_VENDOR_ID_SOUNDGRAPH, USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD2) }, | ||
1628 | { HID_USB_DEVICE(USB_VENDOR_ID_SOUNDGRAPH, USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD3) }, | ||
1629 | { HID_USB_DEVICE(USB_VENDOR_ID_SOUNDGRAPH, USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD4) }, | ||
1630 | { HID_USB_DEVICE(USB_VENDOR_ID_SOUNDGRAPH, USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD5) }, | ||
1631 | { HID_USB_DEVICE(USB_VENDOR_ID_TENX, USB_DEVICE_ID_TENX_IBUDDY1) }, | 1658 | { HID_USB_DEVICE(USB_VENDOR_ID_TENX, USB_DEVICE_ID_TENX_IBUDDY1) }, |
1632 | { HID_USB_DEVICE(USB_VENDOR_ID_TENX, USB_DEVICE_ID_TENX_IBUDDY2) }, | 1659 | { HID_USB_DEVICE(USB_VENDOR_ID_TENX, USB_DEVICE_ID_TENX_IBUDDY2) }, |
1633 | { HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LABPRO) }, | 1660 | { HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LABPRO) }, |
@@ -1694,6 +1721,11 @@ static bool hid_ignore(struct hid_device *hdev) | |||
1694 | hdev->product <= USB_DEVICE_ID_LOGITECH_HARMONY_LAST) | 1721 | hdev->product <= USB_DEVICE_ID_LOGITECH_HARMONY_LAST) |
1695 | return true; | 1722 | return true; |
1696 | break; | 1723 | break; |
1724 | case USB_VENDOR_ID_SOUNDGRAPH: | ||
1725 | if (hdev->product >= USB_DEVICE_ID_SOUNDGRAPH_IMON_FIRST && | ||
1726 | hdev->product <= USB_DEVICE_ID_SOUNDGRAPH_IMON_LAST) | ||
1727 | return true; | ||
1728 | break; | ||
1697 | } | 1729 | } |
1698 | 1730 | ||
1699 | if (hdev->type == HID_TYPE_USBMOUSE && | 1731 | if (hdev->type == HID_TYPE_USBMOUSE && |
@@ -1725,6 +1757,8 @@ int hid_add_device(struct hid_device *hdev) | |||
1725 | if (!ret) | 1757 | if (!ret) |
1726 | hdev->status |= HID_STAT_ADDED; | 1758 | hdev->status |= HID_STAT_ADDED; |
1727 | 1759 | ||
1760 | hid_debug_register(hdev, dev_name(&hdev->dev)); | ||
1761 | |||
1728 | return ret; | 1762 | return ret; |
1729 | } | 1763 | } |
1730 | EXPORT_SYMBOL_GPL(hid_add_device); | 1764 | EXPORT_SYMBOL_GPL(hid_add_device); |
@@ -1761,6 +1795,9 @@ struct hid_device *hid_allocate_device(void) | |||
1761 | for (i = 0; i < HID_REPORT_TYPES; i++) | 1795 | for (i = 0; i < HID_REPORT_TYPES; i++) |
1762 | INIT_LIST_HEAD(&hdev->report_enum[i].report_list); | 1796 | INIT_LIST_HEAD(&hdev->report_enum[i].report_list); |
1763 | 1797 | ||
1798 | init_waitqueue_head(&hdev->debug_wait); | ||
1799 | INIT_LIST_HEAD(&hdev->debug_list); | ||
1800 | |||
1764 | return hdev; | 1801 | return hdev; |
1765 | err: | 1802 | err: |
1766 | put_device(&hdev->dev); | 1803 | put_device(&hdev->dev); |
@@ -1772,6 +1809,7 @@ static void hid_remove_device(struct hid_device *hdev) | |||
1772 | { | 1809 | { |
1773 | if (hdev->status & HID_STAT_ADDED) { | 1810 | if (hdev->status & HID_STAT_ADDED) { |
1774 | device_del(&hdev->dev); | 1811 | device_del(&hdev->dev); |
1812 | hid_debug_unregister(hdev); | ||
1775 | hdev->status &= ~HID_STAT_ADDED; | 1813 | hdev->status &= ~HID_STAT_ADDED; |
1776 | } | 1814 | } |
1777 | } | 1815 | } |
@@ -1847,6 +1885,10 @@ static int __init hid_init(void) | |||
1847 | { | 1885 | { |
1848 | int ret; | 1886 | int ret; |
1849 | 1887 | ||
1888 | if (hid_debug) | ||
1889 | printk(KERN_WARNING "HID: hid_debug is now used solely for parser and driver debugging.\n" | ||
1890 | "HID: debugfs is now used for inspecting the device (report descriptor, reports)\n"); | ||
1891 | |||
1850 | ret = bus_register(&hid_bus_type); | 1892 | ret = bus_register(&hid_bus_type); |
1851 | if (ret) { | 1893 | if (ret) { |
1852 | printk(KERN_ERR "HID: can't register hid bus\n"); | 1894 | printk(KERN_ERR "HID: can't register hid bus\n"); |
@@ -1857,6 +1899,8 @@ static int __init hid_init(void) | |||
1857 | if (ret) | 1899 | if (ret) |
1858 | goto err_bus; | 1900 | goto err_bus; |
1859 | 1901 | ||
1902 | hid_debug_init(); | ||
1903 | |||
1860 | return 0; | 1904 | return 0; |
1861 | err_bus: | 1905 | err_bus: |
1862 | bus_unregister(&hid_bus_type); | 1906 | bus_unregister(&hid_bus_type); |
@@ -1866,6 +1910,7 @@ err: | |||
1866 | 1910 | ||
1867 | static void __exit hid_exit(void) | 1911 | static void __exit hid_exit(void) |
1868 | { | 1912 | { |
1913 | hid_debug_exit(); | ||
1869 | hidraw_exit(); | 1914 | hidraw_exit(); |
1870 | bus_unregister(&hid_bus_type); | 1915 | bus_unregister(&hid_bus_type); |
1871 | } | 1916 | } |
diff --git a/drivers/hid/hid-cypress.c b/drivers/hid/hid-cypress.c index 9d6d3b91773b..62e9cb10e88c 100644 --- a/drivers/hid/hid-cypress.c +++ b/drivers/hid/hid-cypress.c | |||
@@ -141,12 +141,12 @@ static struct hid_driver cp_driver = { | |||
141 | .probe = cp_probe, | 141 | .probe = cp_probe, |
142 | }; | 142 | }; |
143 | 143 | ||
144 | static int cp_init(void) | 144 | static int __init cp_init(void) |
145 | { | 145 | { |
146 | return hid_register_driver(&cp_driver); | 146 | return hid_register_driver(&cp_driver); |
147 | } | 147 | } |
148 | 148 | ||
149 | static void cp_exit(void) | 149 | static void __exit cp_exit(void) |
150 | { | 150 | { |
151 | hid_unregister_driver(&cp_driver); | 151 | hid_unregister_driver(&cp_driver); |
152 | } | 152 | } |
diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c index 04359ed64b87..6abd0369aedb 100644 --- a/drivers/hid/hid-debug.c +++ b/drivers/hid/hid-debug.c | |||
@@ -1,9 +1,9 @@ | |||
1 | /* | 1 | /* |
2 | * (c) 1999 Andreas Gal <gal@cs.uni-magdeburg.de> | 2 | * (c) 1999 Andreas Gal <gal@cs.uni-magdeburg.de> |
3 | * (c) 2000-2001 Vojtech Pavlik <vojtech@ucw.cz> | 3 | * (c) 2000-2001 Vojtech Pavlik <vojtech@ucw.cz> |
4 | * (c) 2007 Jiri Kosina | 4 | * (c) 2007-2009 Jiri Kosina |
5 | * | 5 | * |
6 | * Some debug stuff for the HID parser. | 6 | * HID debugging support |
7 | */ | 7 | */ |
8 | 8 | ||
9 | /* | 9 | /* |
@@ -26,9 +26,17 @@ | |||
26 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic | 26 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic |
27 | */ | 27 | */ |
28 | 28 | ||
29 | #include <linux/debugfs.h> | ||
30 | #include <linux/seq_file.h> | ||
31 | #include <linux/sched.h> | ||
32 | #include <linux/uaccess.h> | ||
33 | #include <linux/poll.h> | ||
34 | |||
29 | #include <linux/hid.h> | 35 | #include <linux/hid.h> |
30 | #include <linux/hid-debug.h> | 36 | #include <linux/hid-debug.h> |
31 | 37 | ||
38 | static struct dentry *hid_debug_root; | ||
39 | |||
32 | struct hid_usage_entry { | 40 | struct hid_usage_entry { |
33 | unsigned page; | 41 | unsigned page; |
34 | unsigned usage; | 42 | unsigned usage; |
@@ -339,72 +347,120 @@ static const struct hid_usage_entry hid_usage_table[] = { | |||
339 | { 0, 0, NULL } | 347 | { 0, 0, NULL } |
340 | }; | 348 | }; |
341 | 349 | ||
342 | static void resolv_usage_page(unsigned page) { | 350 | /* Either output directly into simple seq_file, or (if f == NULL) |
351 | * allocate a separate buffer that will then be passed to the 'events' | ||
352 | * ringbuffer. | ||
353 | * | ||
354 | * This is because these functions can be called both for "one-shot" | ||
355 | * "rdesc" while resolving, or for blocking "events". | ||
356 | * | ||
357 | * This holds both for resolv_usage_page() and hid_resolv_usage(). | ||
358 | */ | ||
359 | static char *resolv_usage_page(unsigned page, struct seq_file *f) { | ||
343 | const struct hid_usage_entry *p; | 360 | const struct hid_usage_entry *p; |
361 | char *buf = NULL; | ||
362 | |||
363 | if (!f) { | ||
364 | buf = kzalloc(sizeof(char) * HID_DEBUG_BUFSIZE, GFP_ATOMIC); | ||
365 | if (!buf) | ||
366 | return ERR_PTR(-ENOMEM); | ||
367 | } | ||
344 | 368 | ||
345 | for (p = hid_usage_table; p->description; p++) | 369 | for (p = hid_usage_table; p->description; p++) |
346 | if (p->page == page) { | 370 | if (p->page == page) { |
347 | printk("%s", p->description); | 371 | if (!f) { |
348 | return; | 372 | snprintf(buf, HID_DEBUG_BUFSIZE, "%s", |
373 | p->description); | ||
374 | return buf; | ||
375 | } | ||
376 | else { | ||
377 | seq_printf(f, "%s", p->description); | ||
378 | return NULL; | ||
379 | } | ||
349 | } | 380 | } |
350 | printk("%04x", page); | 381 | if (!f) |
382 | snprintf(buf, HID_DEBUG_BUFSIZE, "%04x", page); | ||
383 | else | ||
384 | seq_printf(f, "%04x", page); | ||
385 | return buf; | ||
351 | } | 386 | } |
352 | 387 | ||
353 | void hid_resolv_usage(unsigned usage) { | 388 | char *hid_resolv_usage(unsigned usage, struct seq_file *f) { |
354 | const struct hid_usage_entry *p; | 389 | const struct hid_usage_entry *p; |
390 | char *buf = NULL; | ||
391 | int len = 0; | ||
392 | |||
393 | buf = resolv_usage_page(usage >> 16, f); | ||
394 | if (IS_ERR(buf)) { | ||
395 | printk(KERN_ERR "error allocating HID debug buffer\n"); | ||
396 | return NULL; | ||
397 | } | ||
355 | 398 | ||
356 | if (!hid_debug) | ||
357 | return; | ||
358 | 399 | ||
359 | resolv_usage_page(usage >> 16); | 400 | if (!f) { |
360 | printk("."); | 401 | len = strlen(buf); |
402 | snprintf(buf+len, max(0, HID_DEBUG_BUFSIZE - len), "."); | ||
403 | len++; | ||
404 | } | ||
405 | else { | ||
406 | seq_printf(f, "."); | ||
407 | } | ||
361 | for (p = hid_usage_table; p->description; p++) | 408 | for (p = hid_usage_table; p->description; p++) |
362 | if (p->page == (usage >> 16)) { | 409 | if (p->page == (usage >> 16)) { |
363 | for(++p; p->description && p->usage != 0; p++) | 410 | for(++p; p->description && p->usage != 0; p++) |
364 | if (p->usage == (usage & 0xffff)) { | 411 | if (p->usage == (usage & 0xffff)) { |
365 | printk("%s", p->description); | 412 | if (!f) |
366 | return; | 413 | snprintf(buf + len, |
414 | max(0,HID_DEBUG_BUFSIZE - len - 1), | ||
415 | "%s", p->description); | ||
416 | else | ||
417 | seq_printf(f, | ||
418 | "%s", | ||
419 | p->description); | ||
420 | return buf; | ||
367 | } | 421 | } |
368 | break; | 422 | break; |
369 | } | 423 | } |
370 | printk("%04x", usage & 0xffff); | 424 | if (!f) |
425 | snprintf(buf + len, max(0, HID_DEBUG_BUFSIZE - len - 1), | ||
426 | "%04x", usage & 0xffff); | ||
427 | else | ||
428 | seq_printf(f, "%04x", usage & 0xffff); | ||
429 | return buf; | ||
371 | } | 430 | } |
372 | EXPORT_SYMBOL_GPL(hid_resolv_usage); | 431 | EXPORT_SYMBOL_GPL(hid_resolv_usage); |
373 | 432 | ||
374 | static void tab(int n) { | 433 | static void tab(int n, struct seq_file *f) { |
375 | printk(KERN_DEBUG "%*s", n, ""); | 434 | seq_printf(f, "%*s", n, ""); |
376 | } | 435 | } |
377 | 436 | ||
378 | void hid_dump_field(struct hid_field *field, int n) { | 437 | void hid_dump_field(struct hid_field *field, int n, struct seq_file *f) { |
379 | int j; | 438 | int j; |
380 | 439 | ||
381 | if (!hid_debug) | ||
382 | return; | ||
383 | |||
384 | if (field->physical) { | 440 | if (field->physical) { |
385 | tab(n); | 441 | tab(n, f); |
386 | printk("Physical("); | 442 | seq_printf(f, "Physical("); |
387 | hid_resolv_usage(field->physical); printk(")\n"); | 443 | hid_resolv_usage(field->physical, f); seq_printf(f, ")\n"); |
388 | } | 444 | } |
389 | if (field->logical) { | 445 | if (field->logical) { |
390 | tab(n); | 446 | tab(n, f); |
391 | printk("Logical("); | 447 | seq_printf(f, "Logical("); |
392 | hid_resolv_usage(field->logical); printk(")\n"); | 448 | hid_resolv_usage(field->logical, f); seq_printf(f, ")\n"); |
393 | } | 449 | } |
394 | tab(n); printk("Usage(%d)\n", field->maxusage); | 450 | tab(n, f); seq_printf(f, "Usage(%d)\n", field->maxusage); |
395 | for (j = 0; j < field->maxusage; j++) { | 451 | for (j = 0; j < field->maxusage; j++) { |
396 | tab(n+2); hid_resolv_usage(field->usage[j].hid); printk("\n"); | 452 | tab(n+2, f); hid_resolv_usage(field->usage[j].hid, f); seq_printf(f, "\n"); |
397 | } | 453 | } |
398 | if (field->logical_minimum != field->logical_maximum) { | 454 | if (field->logical_minimum != field->logical_maximum) { |
399 | tab(n); printk("Logical Minimum(%d)\n", field->logical_minimum); | 455 | tab(n, f); seq_printf(f, "Logical Minimum(%d)\n", field->logical_minimum); |
400 | tab(n); printk("Logical Maximum(%d)\n", field->logical_maximum); | 456 | tab(n, f); seq_printf(f, "Logical Maximum(%d)\n", field->logical_maximum); |
401 | } | 457 | } |
402 | if (field->physical_minimum != field->physical_maximum) { | 458 | if (field->physical_minimum != field->physical_maximum) { |
403 | tab(n); printk("Physical Minimum(%d)\n", field->physical_minimum); | 459 | tab(n, f); seq_printf(f, "Physical Minimum(%d)\n", field->physical_minimum); |
404 | tab(n); printk("Physical Maximum(%d)\n", field->physical_maximum); | 460 | tab(n, f); seq_printf(f, "Physical Maximum(%d)\n", field->physical_maximum); |
405 | } | 461 | } |
406 | if (field->unit_exponent) { | 462 | if (field->unit_exponent) { |
407 | tab(n); printk("Unit Exponent(%d)\n", field->unit_exponent); | 463 | tab(n, f); seq_printf(f, "Unit Exponent(%d)\n", field->unit_exponent); |
408 | } | 464 | } |
409 | if (field->unit) { | 465 | if (field->unit) { |
410 | static const char *systems[5] = { "None", "SI Linear", "SI Rotation", "English Linear", "English Rotation" }; | 466 | static const char *systems[5] = { "None", "SI Linear", "SI Rotation", "English Linear", "English Rotation" }; |
@@ -425,77 +481,75 @@ void hid_dump_field(struct hid_field *field, int n) { | |||
425 | data >>= 4; | 481 | data >>= 4; |
426 | 482 | ||
427 | if(sys > 4) { | 483 | if(sys > 4) { |
428 | tab(n); printk("Unit(Invalid)\n"); | 484 | tab(n, f); seq_printf(f, "Unit(Invalid)\n"); |
429 | } | 485 | } |
430 | else { | 486 | else { |
431 | int earlier_unit = 0; | 487 | int earlier_unit = 0; |
432 | 488 | ||
433 | tab(n); printk("Unit(%s : ", systems[sys]); | 489 | tab(n, f); seq_printf(f, "Unit(%s : ", systems[sys]); |
434 | 490 | ||
435 | for (i=1 ; i<sizeof(__u32)*2 ; i++) { | 491 | for (i=1 ; i<sizeof(__u32)*2 ; i++) { |
436 | char nibble = data & 0xf; | 492 | char nibble = data & 0xf; |
437 | data >>= 4; | 493 | data >>= 4; |
438 | if (nibble != 0) { | 494 | if (nibble != 0) { |
439 | if(earlier_unit++ > 0) | 495 | if(earlier_unit++ > 0) |
440 | printk("*"); | 496 | seq_printf(f, "*"); |
441 | printk("%s", units[sys][i]); | 497 | seq_printf(f, "%s", units[sys][i]); |
442 | if(nibble != 1) { | 498 | if(nibble != 1) { |
443 | /* This is a _signed_ nibble(!) */ | 499 | /* This is a _signed_ nibble(!) */ |
444 | 500 | ||
445 | int val = nibble & 0x7; | 501 | int val = nibble & 0x7; |
446 | if(nibble & 0x08) | 502 | if(nibble & 0x08) |
447 | val = -((0x7 & ~val) +1); | 503 | val = -((0x7 & ~val) +1); |
448 | printk("^%d", val); | 504 | seq_printf(f, "^%d", val); |
449 | } | 505 | } |
450 | } | 506 | } |
451 | } | 507 | } |
452 | printk(")\n"); | 508 | seq_printf(f, ")\n"); |
453 | } | 509 | } |
454 | } | 510 | } |
455 | tab(n); printk("Report Size(%u)\n", field->report_size); | 511 | tab(n, f); seq_printf(f, "Report Size(%u)\n", field->report_size); |
456 | tab(n); printk("Report Count(%u)\n", field->report_count); | 512 | tab(n, f); seq_printf(f, "Report Count(%u)\n", field->report_count); |
457 | tab(n); printk("Report Offset(%u)\n", field->report_offset); | 513 | tab(n, f); seq_printf(f, "Report Offset(%u)\n", field->report_offset); |
458 | 514 | ||
459 | tab(n); printk("Flags( "); | 515 | tab(n, f); seq_printf(f, "Flags( "); |
460 | j = field->flags; | 516 | j = field->flags; |
461 | printk("%s", HID_MAIN_ITEM_CONSTANT & j ? "Constant " : ""); | 517 | seq_printf(f, "%s", HID_MAIN_ITEM_CONSTANT & j ? "Constant " : ""); |
462 | printk("%s", HID_MAIN_ITEM_VARIABLE & j ? "Variable " : "Array "); | 518 | seq_printf(f, "%s", HID_MAIN_ITEM_VARIABLE & j ? "Variable " : "Array "); |
463 | printk("%s", HID_MAIN_ITEM_RELATIVE & j ? "Relative " : "Absolute "); | 519 | seq_printf(f, "%s", HID_MAIN_ITEM_RELATIVE & j ? "Relative " : "Absolute "); |
464 | printk("%s", HID_MAIN_ITEM_WRAP & j ? "Wrap " : ""); | 520 | seq_printf(f, "%s", HID_MAIN_ITEM_WRAP & j ? "Wrap " : ""); |
465 | printk("%s", HID_MAIN_ITEM_NONLINEAR & j ? "NonLinear " : ""); | 521 | seq_printf(f, "%s", HID_MAIN_ITEM_NONLINEAR & j ? "NonLinear " : ""); |
466 | printk("%s", HID_MAIN_ITEM_NO_PREFERRED & j ? "NoPreferredState " : ""); | 522 | seq_printf(f, "%s", HID_MAIN_ITEM_NO_PREFERRED & j ? "NoPreferredState " : ""); |
467 | printk("%s", HID_MAIN_ITEM_NULL_STATE & j ? "NullState " : ""); | 523 | seq_printf(f, "%s", HID_MAIN_ITEM_NULL_STATE & j ? "NullState " : ""); |
468 | printk("%s", HID_MAIN_ITEM_VOLATILE & j ? "Volatile " : ""); | 524 | seq_printf(f, "%s", HID_MAIN_ITEM_VOLATILE & j ? "Volatile " : ""); |
469 | printk("%s", HID_MAIN_ITEM_BUFFERED_BYTE & j ? "BufferedByte " : ""); | 525 | seq_printf(f, "%s", HID_MAIN_ITEM_BUFFERED_BYTE & j ? "BufferedByte " : ""); |
470 | printk(")\n"); | 526 | seq_printf(f, ")\n"); |
471 | } | 527 | } |
472 | EXPORT_SYMBOL_GPL(hid_dump_field); | 528 | EXPORT_SYMBOL_GPL(hid_dump_field); |
473 | 529 | ||
474 | void hid_dump_device(struct hid_device *device) { | 530 | void hid_dump_device(struct hid_device *device, struct seq_file *f) |
531 | { | ||
475 | struct hid_report_enum *report_enum; | 532 | struct hid_report_enum *report_enum; |
476 | struct hid_report *report; | 533 | struct hid_report *report; |
477 | struct list_head *list; | 534 | struct list_head *list; |
478 | unsigned i,k; | 535 | unsigned i,k; |
479 | static const char *table[] = {"INPUT", "OUTPUT", "FEATURE"}; | 536 | static const char *table[] = {"INPUT", "OUTPUT", "FEATURE"}; |
480 | 537 | ||
481 | if (!hid_debug) | ||
482 | return; | ||
483 | |||
484 | for (i = 0; i < HID_REPORT_TYPES; i++) { | 538 | for (i = 0; i < HID_REPORT_TYPES; i++) { |
485 | report_enum = device->report_enum + i; | 539 | report_enum = device->report_enum + i; |
486 | list = report_enum->report_list.next; | 540 | list = report_enum->report_list.next; |
487 | while (list != &report_enum->report_list) { | 541 | while (list != &report_enum->report_list) { |
488 | report = (struct hid_report *) list; | 542 | report = (struct hid_report *) list; |
489 | tab(2); | 543 | tab(2, f); |
490 | printk("%s", table[i]); | 544 | seq_printf(f, "%s", table[i]); |
491 | if (report->id) | 545 | if (report->id) |
492 | printk("(%d)", report->id); | 546 | seq_printf(f, "(%d)", report->id); |
493 | printk("[%s]", table[report->type]); | 547 | seq_printf(f, "[%s]", table[report->type]); |
494 | printk("\n"); | 548 | seq_printf(f, "\n"); |
495 | for (k = 0; k < report->maxfield; k++) { | 549 | for (k = 0; k < report->maxfield; k++) { |
496 | tab(4); | 550 | tab(4, f); |
497 | printk("Field(%d)\n", k); | 551 | seq_printf(f, "Field(%d)\n", k); |
498 | hid_dump_field(report->field[k], 6); | 552 | hid_dump_field(report->field[k], 6, f); |
499 | } | 553 | } |
500 | list = list->next; | 554 | list = list->next; |
501 | } | 555 | } |
@@ -503,13 +557,37 @@ void hid_dump_device(struct hid_device *device) { | |||
503 | } | 557 | } |
504 | EXPORT_SYMBOL_GPL(hid_dump_device); | 558 | EXPORT_SYMBOL_GPL(hid_dump_device); |
505 | 559 | ||
506 | void hid_dump_input(struct hid_usage *usage, __s32 value) { | 560 | /* enqueue string to 'events' ring buffer */ |
507 | if (hid_debug < 2) | 561 | void hid_debug_event(struct hid_device *hdev, char *buf) |
562 | { | ||
563 | int i; | ||
564 | struct hid_debug_list *list; | ||
565 | |||
566 | list_for_each_entry(list, &hdev->debug_list, node) { | ||
567 | for (i = 0; i <= strlen(buf); i++) | ||
568 | list->hid_debug_buf[(list->tail + i) % (HID_DEBUG_BUFSIZE - 1)] = | ||
569 | buf[i]; | ||
570 | list->tail = (list->tail + i) % (HID_DEBUG_BUFSIZE - 1); | ||
571 | } | ||
572 | } | ||
573 | EXPORT_SYMBOL_GPL(hid_debug_event); | ||
574 | |||
575 | void hid_dump_input(struct hid_device *hdev, struct hid_usage *usage, __s32 value) | ||
576 | { | ||
577 | char *buf; | ||
578 | int len; | ||
579 | |||
580 | buf = hid_resolv_usage(usage->hid, NULL); | ||
581 | if (!buf) | ||
508 | return; | 582 | return; |
583 | len = strlen(buf); | ||
584 | snprintf(buf + len, HID_DEBUG_BUFSIZE - len - 1, " = %d\n", value); | ||
585 | |||
586 | hid_debug_event(hdev, buf); | ||
587 | |||
588 | kfree(buf); | ||
589 | wake_up_interruptible(&hdev->debug_wait); | ||
509 | 590 | ||
510 | printk(KERN_DEBUG "hid-debug: input "); | ||
511 | hid_resolv_usage(usage->hid); | ||
512 | printk(" = %d\n", value); | ||
513 | } | 591 | } |
514 | EXPORT_SYMBOL_GPL(hid_dump_input); | 592 | EXPORT_SYMBOL_GPL(hid_dump_input); |
515 | 593 | ||
@@ -786,12 +864,221 @@ static const char **names[EV_MAX + 1] = { | |||
786 | [EV_SND] = sounds, [EV_REP] = repeats, | 864 | [EV_SND] = sounds, [EV_REP] = repeats, |
787 | }; | 865 | }; |
788 | 866 | ||
789 | void hid_resolv_event(__u8 type, __u16 code) { | 867 | void hid_resolv_event(__u8 type, __u16 code, struct seq_file *f) { |
790 | 868 | ||
791 | if (!hid_debug) | 869 | seq_printf(f, "%s.%s", events[type] ? events[type] : "?", |
792 | return; | ||
793 | |||
794 | printk("%s.%s", events[type] ? events[type] : "?", | ||
795 | names[type] ? (names[type][code] ? names[type][code] : "?") : "?"); | 870 | names[type] ? (names[type][code] ? names[type][code] : "?") : "?"); |
796 | } | 871 | } |
797 | EXPORT_SYMBOL_GPL(hid_resolv_event); | 872 | |
873 | void hid_dump_input_mapping(struct hid_device *hid, struct seq_file *f) | ||
874 | { | ||
875 | int i, j, k; | ||
876 | struct hid_report *report; | ||
877 | struct hid_usage *usage; | ||
878 | |||
879 | for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) { | ||
880 | list_for_each_entry(report, &hid->report_enum[k].report_list, list) { | ||
881 | for (i = 0; i < report->maxfield; i++) { | ||
882 | for ( j = 0; j < report->field[i]->maxusage; j++) { | ||
883 | usage = report->field[i]->usage + j; | ||
884 | hid_resolv_usage(usage->hid, f); | ||
885 | seq_printf(f, " ---> "); | ||
886 | hid_resolv_event(usage->type, usage->code, f); | ||
887 | seq_printf(f, "\n"); | ||
888 | } | ||
889 | } | ||
890 | } | ||
891 | } | ||
892 | |||
893 | } | ||
894 | |||
895 | |||
896 | static int hid_debug_rdesc_show(struct seq_file *f, void *p) | ||
897 | { | ||
898 | struct hid_device *hdev = f->private; | ||
899 | int i; | ||
900 | |||
901 | /* dump HID report descriptor */ | ||
902 | for (i = 0; i < hdev->rsize; i++) | ||
903 | seq_printf(f, "%02x ", hdev->rdesc[i]); | ||
904 | seq_printf(f, "\n\n"); | ||
905 | |||
906 | /* dump parsed data and input mappings */ | ||
907 | hid_dump_device(hdev, f); | ||
908 | seq_printf(f, "\n"); | ||
909 | hid_dump_input_mapping(hdev, f); | ||
910 | |||
911 | return 0; | ||
912 | } | ||
913 | |||
914 | static int hid_debug_rdesc_open(struct inode *inode, struct file *file) | ||
915 | { | ||
916 | return single_open(file, hid_debug_rdesc_show, inode->i_private); | ||
917 | } | ||
918 | |||
919 | static int hid_debug_events_open(struct inode *inode, struct file *file) | ||
920 | { | ||
921 | int err = 0; | ||
922 | struct hid_debug_list *list; | ||
923 | |||
924 | if (!(list = kzalloc(sizeof(struct hid_debug_list), GFP_KERNEL))) { | ||
925 | err = -ENOMEM; | ||
926 | goto out; | ||
927 | } | ||
928 | |||
929 | if (!(list->hid_debug_buf = kzalloc(sizeof(char) * HID_DEBUG_BUFSIZE, GFP_KERNEL))) { | ||
930 | err = -ENOMEM; | ||
931 | kfree(list); | ||
932 | goto out; | ||
933 | } | ||
934 | list->hdev = (struct hid_device *) inode->i_private; | ||
935 | file->private_data = list; | ||
936 | mutex_init(&list->read_mutex); | ||
937 | |||
938 | list_add_tail(&list->node, &list->hdev->debug_list); | ||
939 | |||
940 | out: | ||
941 | return err; | ||
942 | } | ||
943 | |||
944 | static ssize_t hid_debug_events_read(struct file *file, char __user *buffer, | ||
945 | size_t count, loff_t *ppos) | ||
946 | { | ||
947 | struct hid_debug_list *list = file->private_data; | ||
948 | int ret = 0, len; | ||
949 | DECLARE_WAITQUEUE(wait, current); | ||
950 | |||
951 | while (ret == 0) { | ||
952 | mutex_lock(&list->read_mutex); | ||
953 | if (list->head == list->tail) { | ||
954 | add_wait_queue(&list->hdev->debug_wait, &wait); | ||
955 | set_current_state(TASK_INTERRUPTIBLE); | ||
956 | |||
957 | while (list->head == list->tail) { | ||
958 | if (file->f_flags & O_NONBLOCK) { | ||
959 | ret = -EAGAIN; | ||
960 | break; | ||
961 | } | ||
962 | if (signal_pending(current)) { | ||
963 | ret = -ERESTARTSYS; | ||
964 | break; | ||
965 | } | ||
966 | |||
967 | if (!list->hdev || !list->hdev->debug) { | ||
968 | ret = -EIO; | ||
969 | break; | ||
970 | } | ||
971 | |||
972 | /* allow O_NONBLOCK from other threads */ | ||
973 | mutex_unlock(&list->read_mutex); | ||
974 | schedule(); | ||
975 | mutex_lock(&list->read_mutex); | ||
976 | set_current_state(TASK_INTERRUPTIBLE); | ||
977 | } | ||
978 | |||
979 | set_current_state(TASK_RUNNING); | ||
980 | remove_wait_queue(&list->hdev->debug_wait, &wait); | ||
981 | } | ||
982 | |||
983 | if (ret) | ||
984 | goto out; | ||
985 | |||
986 | /* pass the ringbuffer contents to userspace */ | ||
987 | copy_rest: | ||
988 | if (list->tail == list->head) | ||
989 | goto out; | ||
990 | if (list->tail > list->head) { | ||
991 | len = list->tail - list->head; | ||
992 | |||
993 | if (copy_to_user(buffer + ret, &list->hid_debug_buf[list->head], len)) { | ||
994 | ret = -EFAULT; | ||
995 | goto out; | ||
996 | } | ||
997 | ret += len; | ||
998 | list->head += len; | ||
999 | } else { | ||
1000 | len = HID_DEBUG_BUFSIZE - list->head; | ||
1001 | |||
1002 | if (copy_to_user(buffer, &list->hid_debug_buf[list->head], len)) { | ||
1003 | ret = -EFAULT; | ||
1004 | goto out; | ||
1005 | } | ||
1006 | list->head = 0; | ||
1007 | ret += len; | ||
1008 | goto copy_rest; | ||
1009 | } | ||
1010 | |||
1011 | } | ||
1012 | out: | ||
1013 | mutex_unlock(&list->read_mutex); | ||
1014 | return ret; | ||
1015 | } | ||
1016 | |||
1017 | static unsigned int hid_debug_events_poll(struct file *file, poll_table *wait) | ||
1018 | { | ||
1019 | struct hid_debug_list *list = file->private_data; | ||
1020 | |||
1021 | poll_wait(file, &list->hdev->debug_wait, wait); | ||
1022 | if (list->head != list->tail) | ||
1023 | return POLLIN | POLLRDNORM; | ||
1024 | if (!list->hdev->debug) | ||
1025 | return POLLERR | POLLHUP; | ||
1026 | return 0; | ||
1027 | } | ||
1028 | |||
1029 | static int hid_debug_events_release(struct inode *inode, struct file *file) | ||
1030 | { | ||
1031 | struct hid_debug_list *list = file->private_data; | ||
1032 | |||
1033 | list_del(&list->node); | ||
1034 | kfree(list->hid_debug_buf); | ||
1035 | kfree(list); | ||
1036 | |||
1037 | return 0; | ||
1038 | } | ||
1039 | |||
1040 | static const struct file_operations hid_debug_rdesc_fops = { | ||
1041 | .open = hid_debug_rdesc_open, | ||
1042 | .read = seq_read, | ||
1043 | .llseek = seq_lseek, | ||
1044 | .release = single_release, | ||
1045 | }; | ||
1046 | |||
1047 | static const struct file_operations hid_debug_events_fops = { | ||
1048 | .owner = THIS_MODULE, | ||
1049 | .open = hid_debug_events_open, | ||
1050 | .read = hid_debug_events_read, | ||
1051 | .poll = hid_debug_events_poll, | ||
1052 | .release = hid_debug_events_release, | ||
1053 | }; | ||
1054 | |||
1055 | |||
1056 | void hid_debug_register(struct hid_device *hdev, const char *name) | ||
1057 | { | ||
1058 | hdev->debug_dir = debugfs_create_dir(name, hid_debug_root); | ||
1059 | hdev->debug_rdesc = debugfs_create_file("rdesc", 0400, | ||
1060 | hdev->debug_dir, hdev, &hid_debug_rdesc_fops); | ||
1061 | hdev->debug_events = debugfs_create_file("events", 0400, | ||
1062 | hdev->debug_dir, hdev, &hid_debug_events_fops); | ||
1063 | hdev->debug = 1; | ||
1064 | } | ||
1065 | |||
1066 | void hid_debug_unregister(struct hid_device *hdev) | ||
1067 | { | ||
1068 | hdev->debug = 0; | ||
1069 | wake_up_interruptible(&hdev->debug_wait); | ||
1070 | debugfs_remove(hdev->debug_rdesc); | ||
1071 | debugfs_remove(hdev->debug_events); | ||
1072 | debugfs_remove(hdev->debug_dir); | ||
1073 | } | ||
1074 | |||
1075 | void hid_debug_init(void) | ||
1076 | { | ||
1077 | hid_debug_root = debugfs_create_dir("hid", NULL); | ||
1078 | } | ||
1079 | |||
1080 | void hid_debug_exit(void) | ||
1081 | { | ||
1082 | debugfs_remove_recursive(hid_debug_root); | ||
1083 | } | ||
1084 | |||
diff --git a/drivers/hid/hid-ezkey.c b/drivers/hid/hid-ezkey.c index 0a1fe054799b..ca1163e9d42d 100644 --- a/drivers/hid/hid-ezkey.c +++ b/drivers/hid/hid-ezkey.c | |||
@@ -78,12 +78,12 @@ static struct hid_driver ez_driver = { | |||
78 | .event = ez_event, | 78 | .event = ez_event, |
79 | }; | 79 | }; |
80 | 80 | ||
81 | static int ez_init(void) | 81 | static int __init ez_init(void) |
82 | { | 82 | { |
83 | return hid_register_driver(&ez_driver); | 83 | return hid_register_driver(&ez_driver); |
84 | } | 84 | } |
85 | 85 | ||
86 | static void ez_exit(void) | 86 | static void __exit ez_exit(void) |
87 | { | 87 | { |
88 | hid_unregister_driver(&ez_driver); | 88 | hid_unregister_driver(&ez_driver); |
89 | } | 89 | } |
diff --git a/drivers/hid/hid-gyration.c b/drivers/hid/hid-gyration.c index d42d222097a8..cab13e8c7d29 100644 --- a/drivers/hid/hid-gyration.c +++ b/drivers/hid/hid-gyration.c | |||
@@ -81,12 +81,12 @@ static struct hid_driver gyration_driver = { | |||
81 | .event = gyration_event, | 81 | .event = gyration_event, |
82 | }; | 82 | }; |
83 | 83 | ||
84 | static int gyration_init(void) | 84 | static int __init gyration_init(void) |
85 | { | 85 | { |
86 | return hid_register_driver(&gyration_driver); | 86 | return hid_register_driver(&gyration_driver); |
87 | } | 87 | } |
88 | 88 | ||
89 | static void gyration_exit(void) | 89 | static void __exit gyration_exit(void) |
90 | { | 90 | { |
91 | hid_unregister_driver(&gyration_driver); | 91 | hid_unregister_driver(&gyration_driver); |
92 | } | 92 | } |
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 630101037921..adbef5d069c4 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h | |||
@@ -296,6 +296,7 @@ | |||
296 | #define USB_DEVICE_ID_LOGITECH_WINGMAN_F3D 0xc283 | 296 | #define USB_DEVICE_ID_LOGITECH_WINGMAN_F3D 0xc283 |
297 | #define USB_DEVICE_ID_LOGITECH_FORCE3D_PRO 0xc286 | 297 | #define USB_DEVICE_ID_LOGITECH_FORCE3D_PRO 0xc286 |
298 | #define USB_DEVICE_ID_LOGITECH_WHEEL 0xc294 | 298 | #define USB_DEVICE_ID_LOGITECH_WHEEL 0xc294 |
299 | #define USB_DEVICE_ID_LOGITECH_WINGMAN_FFG 0xc293 | ||
299 | #define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL 0xc295 | 300 | #define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL 0xc295 |
300 | #define USB_DEVICE_ID_LOGITECH_G25_WHEEL 0xc299 | 301 | #define USB_DEVICE_ID_LOGITECH_G25_WHEEL 0xc299 |
301 | #define USB_DEVICE_ID_LOGITECH_ELITE_KBD 0xc30a | 302 | #define USB_DEVICE_ID_LOGITECH_ELITE_KBD 0xc30a |
@@ -359,6 +360,9 @@ | |||
359 | #define USB_VENDOR_ID_PETALYNX 0x18b1 | 360 | #define USB_VENDOR_ID_PETALYNX 0x18b1 |
360 | #define USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE 0x0037 | 361 | #define USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE 0x0037 |
361 | 362 | ||
363 | #define USB_VENDOR_ID_PHILIPS 0x0471 | ||
364 | #define USB_DEVICE_ID_PHILIPS_IEEE802154_DONGLE 0x0617 | ||
365 | |||
362 | #define USB_VENDOR_ID_PLAYDOTCOM 0x0b43 | 366 | #define USB_VENDOR_ID_PLAYDOTCOM 0x0b43 |
363 | #define USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII 0x0003 | 367 | #define USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII 0x0003 |
364 | 368 | ||
@@ -376,11 +380,8 @@ | |||
376 | #define USB_DEVICE_ID_SONY_PS3_CONTROLLER 0x0268 | 380 | #define USB_DEVICE_ID_SONY_PS3_CONTROLLER 0x0268 |
377 | 381 | ||
378 | #define USB_VENDOR_ID_SOUNDGRAPH 0x15c2 | 382 | #define USB_VENDOR_ID_SOUNDGRAPH 0x15c2 |
379 | #define USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD 0x0038 | 383 | #define USB_DEVICE_ID_SOUNDGRAPH_IMON_FIRST 0x0034 |
380 | #define USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD2 0x0036 | 384 | #define USB_DEVICE_ID_SOUNDGRAPH_IMON_LAST 0x0046 |
381 | #define USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD3 0x0034 | ||
382 | #define USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD4 0x0044 | ||
383 | #define USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD5 0x0045 | ||
384 | 385 | ||
385 | #define USB_VENDOR_ID_SUN 0x0430 | 386 | #define USB_VENDOR_ID_SUN 0x0430 |
386 | #define USB_DEVICE_ID_RARITAN_KVM_DONGLE 0xcdab | 387 | #define USB_DEVICE_ID_RARITAN_KVM_DONGLE 0xcdab |
@@ -403,6 +404,9 @@ | |||
403 | #define USB_VENDOR_ID_TURBOX 0x062a | 404 | #define USB_VENDOR_ID_TURBOX 0x062a |
404 | #define USB_DEVICE_ID_TURBOX_KEYBOARD 0x0201 | 405 | #define USB_DEVICE_ID_TURBOX_KEYBOARD 0x0201 |
405 | 406 | ||
407 | #define USB_VENDOR_ID_TWINHAN 0x6253 | ||
408 | #define USB_DEVICE_ID_TWINHAN_IR_REMOTE 0x0100 | ||
409 | |||
406 | #define USB_VENDOR_ID_UCLOGIC 0x5543 | 410 | #define USB_VENDOR_ID_UCLOGIC 0x5543 |
407 | #define USB_DEVICE_ID_UCLOGIC_TABLET_PF1209 0x0042 | 411 | #define USB_DEVICE_ID_UCLOGIC_TABLET_PF1209 0x0042 |
408 | 412 | ||
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 7f183b7147e1..5862b0f3b55d 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c | |||
@@ -159,17 +159,12 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
159 | 159 | ||
160 | field->hidinput = hidinput; | 160 | field->hidinput = hidinput; |
161 | 161 | ||
162 | dbg_hid("Mapping: "); | ||
163 | hid_resolv_usage(usage->hid); | ||
164 | dbg_hid_line(" ---> "); | ||
165 | |||
166 | if (field->flags & HID_MAIN_ITEM_CONSTANT) | 162 | if (field->flags & HID_MAIN_ITEM_CONSTANT) |
167 | goto ignore; | 163 | goto ignore; |
168 | 164 | ||
169 | /* only LED usages are supported in output fields */ | 165 | /* only LED usages are supported in output fields */ |
170 | if (field->report_type == HID_OUTPUT_REPORT && | 166 | if (field->report_type == HID_OUTPUT_REPORT && |
171 | (usage->hid & HID_USAGE_PAGE) != HID_UP_LED) { | 167 | (usage->hid & HID_USAGE_PAGE) != HID_UP_LED) { |
172 | dbg_hid_line(" [non-LED output field] "); | ||
173 | goto ignore; | 168 | goto ignore; |
174 | } | 169 | } |
175 | 170 | ||
@@ -561,15 +556,9 @@ mapped: | |||
561 | set_bit(MSC_SCAN, input->mscbit); | 556 | set_bit(MSC_SCAN, input->mscbit); |
562 | } | 557 | } |
563 | 558 | ||
564 | hid_resolv_event(usage->type, usage->code); | ||
565 | |||
566 | dbg_hid_line("\n"); | ||
567 | |||
568 | return; | ||
569 | |||
570 | ignore: | 559 | ignore: |
571 | dbg_hid_line("IGNORED\n"); | ||
572 | return; | 560 | return; |
561 | |||
573 | } | 562 | } |
574 | 563 | ||
575 | void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value) | 564 | void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value) |
diff --git a/drivers/hid/hid-kensington.c b/drivers/hid/hid-kensington.c index 7353bd79cbe9..a5b4016e9bd7 100644 --- a/drivers/hid/hid-kensington.c +++ b/drivers/hid/hid-kensington.c | |||
@@ -48,12 +48,12 @@ static struct hid_driver ks_driver = { | |||
48 | .input_mapping = ks_input_mapping, | 48 | .input_mapping = ks_input_mapping, |
49 | }; | 49 | }; |
50 | 50 | ||
51 | static int ks_init(void) | 51 | static int __init ks_init(void) |
52 | { | 52 | { |
53 | return hid_register_driver(&ks_driver); | 53 | return hid_register_driver(&ks_driver); |
54 | } | 54 | } |
55 | 55 | ||
56 | static void ks_exit(void) | 56 | static void __exit ks_exit(void) |
57 | { | 57 | { |
58 | hid_unregister_driver(&ks_driver); | 58 | hid_unregister_driver(&ks_driver); |
59 | } | 59 | } |
diff --git a/drivers/hid/hid-kye.c b/drivers/hid/hid-kye.c index 72ee3fec56d9..f8871712b7b5 100644 --- a/drivers/hid/hid-kye.c +++ b/drivers/hid/hid-kye.c | |||
@@ -54,12 +54,12 @@ static struct hid_driver kye_driver = { | |||
54 | .report_fixup = kye_report_fixup, | 54 | .report_fixup = kye_report_fixup, |
55 | }; | 55 | }; |
56 | 56 | ||
57 | static int kye_init(void) | 57 | static int __init kye_init(void) |
58 | { | 58 | { |
59 | return hid_register_driver(&kye_driver); | 59 | return hid_register_driver(&kye_driver); |
60 | } | 60 | } |
61 | 61 | ||
62 | static void kye_exit(void) | 62 | static void __exit kye_exit(void) |
63 | { | 63 | { |
64 | hid_unregister_driver(&kye_driver); | 64 | hid_unregister_driver(&kye_driver); |
65 | } | 65 | } |
diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c index 7afbaa0efd18..0f870a3243ed 100644 --- a/drivers/hid/hid-lg.c +++ b/drivers/hid/hid-lg.c | |||
@@ -299,6 +299,8 @@ static const struct hid_device_id lg_devices[] = { | |||
299 | .driver_data = LG_FF }, | 299 | .driver_data = LG_FF }, |
300 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL), | 300 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL), |
301 | .driver_data = LG_FF }, | 301 | .driver_data = LG_FF }, |
302 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ), | ||
303 | .driver_data = LG_FF }, | ||
302 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2), | 304 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2), |
303 | .driver_data = LG_FF2 }, | 305 | .driver_data = LG_FF2 }, |
304 | { } | 306 | { } |
@@ -315,12 +317,12 @@ static struct hid_driver lg_driver = { | |||
315 | .probe = lg_probe, | 317 | .probe = lg_probe, |
316 | }; | 318 | }; |
317 | 319 | ||
318 | static int lg_init(void) | 320 | static int __init lg_init(void) |
319 | { | 321 | { |
320 | return hid_register_driver(&lg_driver); | 322 | return hid_register_driver(&lg_driver); |
321 | } | 323 | } |
322 | 324 | ||
323 | static void lg_exit(void) | 325 | static void __exit lg_exit(void) |
324 | { | 326 | { |
325 | hid_unregister_driver(&lg_driver); | 327 | hid_unregister_driver(&lg_driver); |
326 | } | 328 | } |
diff --git a/drivers/hid/hid-lgff.c b/drivers/hid/hid-lgff.c index 56099709581c..987abebe0829 100644 --- a/drivers/hid/hid-lgff.c +++ b/drivers/hid/hid-lgff.c | |||
@@ -67,6 +67,7 @@ static const struct dev_type devices[] = { | |||
67 | { 0x046d, 0xc219, ff_rumble }, | 67 | { 0x046d, 0xc219, ff_rumble }, |
68 | { 0x046d, 0xc283, ff_joystick }, | 68 | { 0x046d, 0xc283, ff_joystick }, |
69 | { 0x046d, 0xc286, ff_joystick_ac }, | 69 | { 0x046d, 0xc286, ff_joystick_ac }, |
70 | { 0x046d, 0xc293, ff_joystick }, | ||
70 | { 0x046d, 0xc294, ff_wheel }, | 71 | { 0x046d, 0xc294, ff_wheel }, |
71 | { 0x046d, 0xc295, ff_joystick }, | 72 | { 0x046d, 0xc295, ff_joystick }, |
72 | { 0x046d, 0xca03, ff_wheel }, | 73 | { 0x046d, 0xca03, ff_wheel }, |
@@ -150,11 +151,6 @@ int lgff_init(struct hid_device* hid) | |||
150 | 151 | ||
151 | /* Check that the report looks ok */ | 152 | /* Check that the report looks ok */ |
152 | report = list_entry(report_list->next, struct hid_report, list); | 153 | report = list_entry(report_list->next, struct hid_report, list); |
153 | if (!report) { | ||
154 | err_hid("NULL output report"); | ||
155 | return -1; | ||
156 | } | ||
157 | |||
158 | field = report->field[0]; | 154 | field = report->field[0]; |
159 | if (!field) { | 155 | if (!field) { |
160 | err_hid("NULL field"); | 156 | err_hid("NULL field"); |
diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c index 5e9e37a0506d..359cc447c6c6 100644 --- a/drivers/hid/hid-microsoft.c +++ b/drivers/hid/hid-microsoft.c | |||
@@ -197,12 +197,12 @@ static struct hid_driver ms_driver = { | |||
197 | .probe = ms_probe, | 197 | .probe = ms_probe, |
198 | }; | 198 | }; |
199 | 199 | ||
200 | static int ms_init(void) | 200 | static int __init ms_init(void) |
201 | { | 201 | { |
202 | return hid_register_driver(&ms_driver); | 202 | return hid_register_driver(&ms_driver); |
203 | } | 203 | } |
204 | 204 | ||
205 | static void ms_exit(void) | 205 | static void __exit ms_exit(void) |
206 | { | 206 | { |
207 | hid_unregister_driver(&ms_driver); | 207 | hid_unregister_driver(&ms_driver); |
208 | } | 208 | } |
diff --git a/drivers/hid/hid-monterey.c b/drivers/hid/hid-monterey.c index 240f87618be6..2cd05aa244b9 100644 --- a/drivers/hid/hid-monterey.c +++ b/drivers/hid/hid-monterey.c | |||
@@ -65,12 +65,12 @@ static struct hid_driver mr_driver = { | |||
65 | .input_mapping = mr_input_mapping, | 65 | .input_mapping = mr_input_mapping, |
66 | }; | 66 | }; |
67 | 67 | ||
68 | static int mr_init(void) | 68 | static int __init mr_init(void) |
69 | { | 69 | { |
70 | return hid_register_driver(&mr_driver); | 70 | return hid_register_driver(&mr_driver); |
71 | } | 71 | } |
72 | 72 | ||
73 | static void mr_exit(void) | 73 | static void __exit mr_exit(void) |
74 | { | 74 | { |
75 | hid_unregister_driver(&mr_driver); | 75 | hid_unregister_driver(&mr_driver); |
76 | } | 76 | } |
diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c index 75ed9d2c1a36..49ce69d7bba7 100644 --- a/drivers/hid/hid-ntrig.c +++ b/drivers/hid/hid-ntrig.c | |||
@@ -27,6 +27,9 @@ | |||
27 | struct ntrig_data { | 27 | struct ntrig_data { |
28 | __s32 x, y, id, w, h; | 28 | __s32 x, y, id, w, h; |
29 | char reading_a_point, found_contact_id; | 29 | char reading_a_point, found_contact_id; |
30 | char pen_active; | ||
31 | char finger_active; | ||
32 | char inverted; | ||
30 | }; | 33 | }; |
31 | 34 | ||
32 | /* | 35 | /* |
@@ -63,10 +66,7 @@ static int ntrig_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
63 | case HID_UP_DIGITIZER: | 66 | case HID_UP_DIGITIZER: |
64 | switch (usage->hid) { | 67 | switch (usage->hid) { |
65 | /* we do not want to map these for now */ | 68 | /* we do not want to map these for now */ |
66 | case HID_DG_INVERT: /* value is always 0 */ | ||
67 | case HID_DG_ERASER: /* value is always 0 */ | ||
68 | case HID_DG_CONTACTID: /* value is useless */ | 69 | case HID_DG_CONTACTID: /* value is useless */ |
69 | case HID_DG_BARRELSWITCH: /* doubtful */ | ||
70 | case HID_DG_INPUTMODE: | 70 | case HID_DG_INPUTMODE: |
71 | case HID_DG_DEVICEINDEX: | 71 | case HID_DG_DEVICEINDEX: |
72 | case HID_DG_CONTACTCOUNT: | 72 | case HID_DG_CONTACTCOUNT: |
@@ -125,6 +125,18 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field, | |||
125 | 125 | ||
126 | if (hid->claimed & HID_CLAIMED_INPUT) { | 126 | if (hid->claimed & HID_CLAIMED_INPUT) { |
127 | switch (usage->hid) { | 127 | switch (usage->hid) { |
128 | |||
129 | case HID_DG_INRANGE: | ||
130 | if (field->application & 0x3) | ||
131 | nd->pen_active = (value != 0); | ||
132 | else | ||
133 | nd->finger_active = (value != 0); | ||
134 | return 0; | ||
135 | |||
136 | case HID_DG_INVERT: | ||
137 | nd->inverted = value; | ||
138 | return 0; | ||
139 | |||
128 | case HID_GD_X: | 140 | case HID_GD_X: |
129 | nd->x = value; | 141 | nd->x = value; |
130 | nd->reading_a_point = 1; | 142 | nd->reading_a_point = 1; |
@@ -147,7 +159,11 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field, | |||
147 | * report received in a finger event. We want | 159 | * report received in a finger event. We want |
148 | * to emit a normal (X, Y) position | 160 | * to emit a normal (X, Y) position |
149 | */ | 161 | */ |
150 | if (! nd->found_contact_id) { | 162 | if (!nd->found_contact_id) { |
163 | if (nd->pen_active && nd->finger_active) { | ||
164 | input_report_key(input, BTN_TOOL_DOUBLETAP, 0); | ||
165 | input_report_key(input, BTN_TOOL_DOUBLETAP, 1); | ||
166 | } | ||
151 | input_event(input, EV_ABS, ABS_X, nd->x); | 167 | input_event(input, EV_ABS, ABS_X, nd->x); |
152 | input_event(input, EV_ABS, ABS_Y, nd->y); | 168 | input_event(input, EV_ABS, ABS_Y, nd->y); |
153 | } | 169 | } |
@@ -159,6 +175,14 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field, | |||
159 | * to emit a normal (X, Y) position | 175 | * to emit a normal (X, Y) position |
160 | */ | 176 | */ |
161 | if (! nd->found_contact_id) { | 177 | if (! nd->found_contact_id) { |
178 | if (nd->pen_active && nd->finger_active) { | ||
179 | input_report_key(input, | ||
180 | nd->inverted ? BTN_TOOL_RUBBER : BTN_TOOL_PEN | ||
181 | , 0); | ||
182 | input_report_key(input, | ||
183 | nd->inverted ? BTN_TOOL_RUBBER : BTN_TOOL_PEN | ||
184 | , 1); | ||
185 | } | ||
162 | input_event(input, EV_ABS, ABS_X, nd->x); | 186 | input_event(input, EV_ABS, ABS_X, nd->x); |
163 | input_event(input, EV_ABS, ABS_Y, nd->y); | 187 | input_event(input, EV_ABS, ABS_Y, nd->y); |
164 | input_event(input, EV_ABS, ABS_PRESSURE, value); | 188 | input_event(input, EV_ABS, ABS_PRESSURE, value); |
@@ -233,6 +257,7 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
233 | 257 | ||
234 | if (ret) | 258 | if (ret) |
235 | kfree (nd); | 259 | kfree (nd); |
260 | |||
236 | return ret; | 261 | return ret; |
237 | } | 262 | } |
238 | 263 | ||
@@ -265,12 +290,12 @@ static struct hid_driver ntrig_driver = { | |||
265 | .event = ntrig_event, | 290 | .event = ntrig_event, |
266 | }; | 291 | }; |
267 | 292 | ||
268 | static int ntrig_init(void) | 293 | static int __init ntrig_init(void) |
269 | { | 294 | { |
270 | return hid_register_driver(&ntrig_driver); | 295 | return hid_register_driver(&ntrig_driver); |
271 | } | 296 | } |
272 | 297 | ||
273 | static void ntrig_exit(void) | 298 | static void __exit ntrig_exit(void) |
274 | { | 299 | { |
275 | hid_unregister_driver(&ntrig_driver); | 300 | hid_unregister_driver(&ntrig_driver); |
276 | } | 301 | } |
diff --git a/drivers/hid/hid-petalynx.c b/drivers/hid/hid-petalynx.c index 2e83e8ff891a..500fbd0652dc 100644 --- a/drivers/hid/hid-petalynx.c +++ b/drivers/hid/hid-petalynx.c | |||
@@ -105,12 +105,12 @@ static struct hid_driver pl_driver = { | |||
105 | .probe = pl_probe, | 105 | .probe = pl_probe, |
106 | }; | 106 | }; |
107 | 107 | ||
108 | static int pl_init(void) | 108 | static int __init pl_init(void) |
109 | { | 109 | { |
110 | return hid_register_driver(&pl_driver); | 110 | return hid_register_driver(&pl_driver); |
111 | } | 111 | } |
112 | 112 | ||
113 | static void pl_exit(void) | 113 | static void __exit pl_exit(void) |
114 | { | 114 | { |
115 | hid_unregister_driver(&pl_driver); | 115 | hid_unregister_driver(&pl_driver); |
116 | } | 116 | } |
diff --git a/drivers/hid/hid-pl.c b/drivers/hid/hid-pl.c index 4db9a3483760..c6d7dbc935b1 100644 --- a/drivers/hid/hid-pl.c +++ b/drivers/hid/hid-pl.c | |||
@@ -217,12 +217,12 @@ static struct hid_driver pl_driver = { | |||
217 | .probe = pl_probe, | 217 | .probe = pl_probe, |
218 | }; | 218 | }; |
219 | 219 | ||
220 | static int pl_init(void) | 220 | static int __init pl_init(void) |
221 | { | 221 | { |
222 | return hid_register_driver(&pl_driver); | 222 | return hid_register_driver(&pl_driver); |
223 | } | 223 | } |
224 | 224 | ||
225 | static void pl_exit(void) | 225 | static void __exit pl_exit(void) |
226 | { | 226 | { |
227 | hid_unregister_driver(&pl_driver); | 227 | hid_unregister_driver(&pl_driver); |
228 | } | 228 | } |
diff --git a/drivers/hid/hid-samsung.c b/drivers/hid/hid-samsung.c index 07083aa6c19a..5b222eed0692 100644 --- a/drivers/hid/hid-samsung.c +++ b/drivers/hid/hid-samsung.c | |||
@@ -25,25 +25,48 @@ | |||
25 | /* | 25 | /* |
26 | * Samsung IrDA remote controller (reports as Cypress USB Mouse). | 26 | * Samsung IrDA remote controller (reports as Cypress USB Mouse). |
27 | * | 27 | * |
28 | * There are several variants for 0419:0001: | ||
29 | * | ||
30 | * 1. 184 byte report descriptor | ||
28 | * Vendor specific report #4 has a size of 48 bit, | 31 | * Vendor specific report #4 has a size of 48 bit, |
29 | * and therefore is not accepted when inspecting the descriptors. | 32 | * and therefore is not accepted when inspecting the descriptors. |
30 | * As a workaround we reinterpret the report as: | 33 | * As a workaround we reinterpret the report as: |
31 | * Variable type, count 6, size 8 bit, log. maximum 255 | 34 | * Variable type, count 6, size 8 bit, log. maximum 255 |
32 | * The burden to reconstruct the data is moved into user space. | 35 | * The burden to reconstruct the data is moved into user space. |
36 | * | ||
37 | * 2. 203 byte report descriptor | ||
38 | * Report #4 has an array field with logical range 0..18 instead of 1..15. | ||
39 | * | ||
40 | * 3. 135 byte report descriptor | ||
41 | * Report #4 has an array field with logical range 0..17 instead of 1..14. | ||
33 | */ | 42 | */ |
34 | static void samsung_report_fixup(struct hid_device *hdev, __u8 *rdesc, | 43 | static void samsung_report_fixup(struct hid_device *hdev, __u8 *rdesc, |
35 | unsigned int rsize) | 44 | unsigned int rsize) |
36 | { | 45 | { |
37 | if (rsize >= 182 && rdesc[175] == 0x25 && rdesc[176] == 0x40 && | 46 | if (rsize == 184 && rdesc[175] == 0x25 && rdesc[176] == 0x40 && |
38 | rdesc[177] == 0x75 && rdesc[178] == 0x30 && | 47 | rdesc[177] == 0x75 && rdesc[178] == 0x30 && |
39 | rdesc[179] == 0x95 && rdesc[180] == 0x01 && | 48 | rdesc[179] == 0x95 && rdesc[180] == 0x01 && |
40 | rdesc[182] == 0x40) { | 49 | rdesc[182] == 0x40) { |
41 | dev_info(&hdev->dev, "fixing up Samsung IrDA report " | 50 | dev_info(&hdev->dev, "fixing up Samsung IrDA %d byte report " |
42 | "descriptor\n"); | 51 | "descriptor\n", 184); |
43 | rdesc[176] = 0xff; | 52 | rdesc[176] = 0xff; |
44 | rdesc[178] = 0x08; | 53 | rdesc[178] = 0x08; |
45 | rdesc[180] = 0x06; | 54 | rdesc[180] = 0x06; |
46 | rdesc[182] = 0x42; | 55 | rdesc[182] = 0x42; |
56 | } else | ||
57 | if (rsize == 203 && rdesc[192] == 0x15 && rdesc[193] == 0x0 && | ||
58 | rdesc[194] == 0x25 && rdesc[195] == 0x12) { | ||
59 | dev_info(&hdev->dev, "fixing up Samsung IrDA %d byte report " | ||
60 | "descriptor\n", 203); | ||
61 | rdesc[193] = 0x1; | ||
62 | rdesc[195] = 0xf; | ||
63 | } else | ||
64 | if (rsize == 135 && rdesc[124] == 0x15 && rdesc[125] == 0x0 && | ||
65 | rdesc[126] == 0x25 && rdesc[127] == 0x11) { | ||
66 | dev_info(&hdev->dev, "fixing up Samsung IrDA %d byte report " | ||
67 | "descriptor\n", 135); | ||
68 | rdesc[125] = 0x1; | ||
69 | rdesc[127] = 0xe; | ||
47 | } | 70 | } |
48 | } | 71 | } |
49 | 72 | ||
@@ -51,6 +74,7 @@ static int samsung_probe(struct hid_device *hdev, | |||
51 | const struct hid_device_id *id) | 74 | const struct hid_device_id *id) |
52 | { | 75 | { |
53 | int ret; | 76 | int ret; |
77 | unsigned int cmask = HID_CONNECT_DEFAULT; | ||
54 | 78 | ||
55 | ret = hid_parse(hdev); | 79 | ret = hid_parse(hdev); |
56 | if (ret) { | 80 | if (ret) { |
@@ -58,8 +82,13 @@ static int samsung_probe(struct hid_device *hdev, | |||
58 | goto err_free; | 82 | goto err_free; |
59 | } | 83 | } |
60 | 84 | ||
61 | ret = hid_hw_start(hdev, (HID_CONNECT_DEFAULT & ~HID_CONNECT_HIDINPUT) | | 85 | if (hdev->rsize == 184) { |
62 | HID_CONNECT_HIDDEV_FORCE); | 86 | /* disable hidinput, force hiddev */ |
87 | cmask = (cmask & ~HID_CONNECT_HIDINPUT) | | ||
88 | HID_CONNECT_HIDDEV_FORCE; | ||
89 | } | ||
90 | |||
91 | ret = hid_hw_start(hdev, cmask); | ||
63 | if (ret) { | 92 | if (ret) { |
64 | dev_err(&hdev->dev, "hw start failed\n"); | 93 | dev_err(&hdev->dev, "hw start failed\n"); |
65 | goto err_free; | 94 | goto err_free; |
@@ -83,12 +112,12 @@ static struct hid_driver samsung_driver = { | |||
83 | .probe = samsung_probe, | 112 | .probe = samsung_probe, |
84 | }; | 113 | }; |
85 | 114 | ||
86 | static int samsung_init(void) | 115 | static int __init samsung_init(void) |
87 | { | 116 | { |
88 | return hid_register_driver(&samsung_driver); | 117 | return hid_register_driver(&samsung_driver); |
89 | } | 118 | } |
90 | 119 | ||
91 | static void samsung_exit(void) | 120 | static void __exit samsung_exit(void) |
92 | { | 121 | { |
93 | hid_unregister_driver(&samsung_driver); | 122 | hid_unregister_driver(&samsung_driver); |
94 | } | 123 | } |
diff --git a/drivers/hid/hid-sjoy.c b/drivers/hid/hid-sjoy.c index eab169e5c371..203c438b016f 100644 --- a/drivers/hid/hid-sjoy.c +++ b/drivers/hid/hid-sjoy.c | |||
@@ -163,12 +163,12 @@ static struct hid_driver sjoy_driver = { | |||
163 | .probe = sjoy_probe, | 163 | .probe = sjoy_probe, |
164 | }; | 164 | }; |
165 | 165 | ||
166 | static int sjoy_init(void) | 166 | static int __init sjoy_init(void) |
167 | { | 167 | { |
168 | return hid_register_driver(&sjoy_driver); | 168 | return hid_register_driver(&sjoy_driver); |
169 | } | 169 | } |
170 | 170 | ||
171 | static void sjoy_exit(void) | 171 | static void __exit sjoy_exit(void) |
172 | { | 172 | { |
173 | hid_unregister_driver(&sjoy_driver); | 173 | hid_unregister_driver(&sjoy_driver); |
174 | } | 174 | } |
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index c2599388a350..4e8450228a24 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c | |||
@@ -135,12 +135,12 @@ static struct hid_driver sony_driver = { | |||
135 | .report_fixup = sony_report_fixup, | 135 | .report_fixup = sony_report_fixup, |
136 | }; | 136 | }; |
137 | 137 | ||
138 | static int sony_init(void) | 138 | static int __init sony_init(void) |
139 | { | 139 | { |
140 | return hid_register_driver(&sony_driver); | 140 | return hid_register_driver(&sony_driver); |
141 | } | 141 | } |
142 | 142 | ||
143 | static void sony_exit(void) | 143 | static void __exit sony_exit(void) |
144 | { | 144 | { |
145 | hid_unregister_driver(&sony_driver); | 145 | hid_unregister_driver(&sony_driver); |
146 | } | 146 | } |
diff --git a/drivers/hid/hid-sunplus.c b/drivers/hid/hid-sunplus.c index e0a8fd36a85b..438107d9f1b2 100644 --- a/drivers/hid/hid-sunplus.c +++ b/drivers/hid/hid-sunplus.c | |||
@@ -65,12 +65,12 @@ static struct hid_driver sp_driver = { | |||
65 | .input_mapping = sp_input_mapping, | 65 | .input_mapping = sp_input_mapping, |
66 | }; | 66 | }; |
67 | 67 | ||
68 | static int sp_init(void) | 68 | static int __init sp_init(void) |
69 | { | 69 | { |
70 | return hid_register_driver(&sp_driver); | 70 | return hid_register_driver(&sp_driver); |
71 | } | 71 | } |
72 | 72 | ||
73 | static void sp_exit(void) | 73 | static void __exit sp_exit(void) |
74 | { | 74 | { |
75 | hid_unregister_driver(&sp_driver); | 75 | hid_unregister_driver(&sp_driver); |
76 | } | 76 | } |
diff --git a/drivers/hid/hid-tmff.c b/drivers/hid/hid-tmff.c index fcd6ccd02fee..167ea746fb9c 100644 --- a/drivers/hid/hid-tmff.c +++ b/drivers/hid/hid-tmff.c | |||
@@ -243,7 +243,11 @@ err: | |||
243 | static const struct hid_device_id tm_devices[] = { | 243 | static const struct hid_device_id tm_devices[] = { |
244 | { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300), | 244 | { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300), |
245 | .driver_data = (unsigned long)ff_rumble }, | 245 | .driver_data = (unsigned long)ff_rumble }, |
246 | { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304), | 246 | { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304), /* FireStorm Dual Power 2 (and 3) */ |
247 | .driver_data = (unsigned long)ff_rumble }, | ||
248 | { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb323), /* Dual Trigger 3-in-1 (PC Mode) */ | ||
249 | .driver_data = (unsigned long)ff_rumble }, | ||
250 | { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb324), /* Dual Trigger 3-in-1 (PS3 Mode) */ | ||
247 | .driver_data = (unsigned long)ff_rumble }, | 251 | .driver_data = (unsigned long)ff_rumble }, |
248 | { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb651), /* FGT Rumble Force Wheel */ | 252 | { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb651), /* FGT Rumble Force Wheel */ |
249 | .driver_data = (unsigned long)ff_rumble }, | 253 | .driver_data = (unsigned long)ff_rumble }, |
@@ -259,12 +263,12 @@ static struct hid_driver tm_driver = { | |||
259 | .probe = tm_probe, | 263 | .probe = tm_probe, |
260 | }; | 264 | }; |
261 | 265 | ||
262 | static int tm_init(void) | 266 | static int __init tm_init(void) |
263 | { | 267 | { |
264 | return hid_register_driver(&tm_driver); | 268 | return hid_register_driver(&tm_driver); |
265 | } | 269 | } |
266 | 270 | ||
267 | static void tm_exit(void) | 271 | static void __exit tm_exit(void) |
268 | { | 272 | { |
269 | hid_unregister_driver(&tm_driver); | 273 | hid_unregister_driver(&tm_driver); |
270 | } | 274 | } |
diff --git a/drivers/hid/hid-topseed.c b/drivers/hid/hid-topseed.c index 152ccfabeba5..6925eda1081a 100644 --- a/drivers/hid/hid-topseed.c +++ b/drivers/hid/hid-topseed.c | |||
@@ -60,12 +60,12 @@ static struct hid_driver ts_driver = { | |||
60 | .input_mapping = ts_input_mapping, | 60 | .input_mapping = ts_input_mapping, |
61 | }; | 61 | }; |
62 | 62 | ||
63 | static int ts_init(void) | 63 | static int __init ts_init(void) |
64 | { | 64 | { |
65 | return hid_register_driver(&ts_driver); | 65 | return hid_register_driver(&ts_driver); |
66 | } | 66 | } |
67 | 67 | ||
68 | static void ts_exit(void) | 68 | static void __exit ts_exit(void) |
69 | { | 69 | { |
70 | hid_unregister_driver(&ts_driver); | 70 | hid_unregister_driver(&ts_driver); |
71 | } | 71 | } |
diff --git a/drivers/hid/hid-twinhan.c b/drivers/hid/hid-twinhan.c new file mode 100644 index 000000000000..b05f602c051e --- /dev/null +++ b/drivers/hid/hid-twinhan.c | |||
@@ -0,0 +1,147 @@ | |||
1 | /* | ||
2 | * HID driver for TwinHan IR remote control | ||
3 | * | ||
4 | * Based on hid-gyration.c | ||
5 | * | ||
6 | * Copyright (c) 2009 Bruno Prémont <bonbons@linux-vserver.org> | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the Free | ||
12 | * Software Foundation; either version 2 of the License. | ||
13 | */ | ||
14 | |||
15 | #include <linux/device.h> | ||
16 | #include <linux/input.h> | ||
17 | #include <linux/hid.h> | ||
18 | #include <linux/module.h> | ||
19 | |||
20 | #include "hid-ids.h" | ||
21 | |||
22 | /* Remote control key layout + listing: | ||
23 | * | ||
24 | * Full Screen Power | ||
25 | * KEY_SCREEN KEY_POWER2 | ||
26 | * | ||
27 | * 1 2 3 | ||
28 | * KEY_NUMERIC_1 KEY_NUMERIC_2 KEY_NUMERIC_3 | ||
29 | * | ||
30 | * 4 5 6 | ||
31 | * KEY_NUMERIC_4 KEY_NUMERIC_5 KEY_NUMERIC_6 | ||
32 | * | ||
33 | * 7 8 9 | ||
34 | * KEY_NUMERIC_7 KEY_NUMERIC_8 KEY_NUMERIC_9 | ||
35 | * | ||
36 | * REC 0 Favorite | ||
37 | * KEY_RECORD KEY_NUMERIC_0 KEY_FAVORITES | ||
38 | * | ||
39 | * Rewind Forward | ||
40 | * KEY_REWIND CH+ KEY_FORWARD | ||
41 | * KEY_CHANNELUP | ||
42 | * | ||
43 | * VOL- > VOL+ | ||
44 | * KEY_VOLUMEDOWN KEY_PLAY KEY_VOLUMEUP | ||
45 | * | ||
46 | * CH- | ||
47 | * KEY_CHANNELDOWN | ||
48 | * Recall Stop | ||
49 | * KEY_RESTART KEY_STOP | ||
50 | * | ||
51 | * Timeshift/Pause Mute Cancel | ||
52 | * KEY_PAUSE KEY_MUTE KEY_CANCEL | ||
53 | * | ||
54 | * Capture Preview EPG | ||
55 | * KEY_PRINT KEY_PROGRAM KEY_EPG | ||
56 | * | ||
57 | * Record List Tab Teletext | ||
58 | * KEY_LIST KEY_TAB KEY_TEXT | ||
59 | */ | ||
60 | |||
61 | #define th_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ | ||
62 | EV_KEY, (c)) | ||
63 | static int twinhan_input_mapping(struct hid_device *hdev, struct hid_input *hi, | ||
64 | struct hid_field *field, struct hid_usage *usage, | ||
65 | unsigned long **bit, int *max) | ||
66 | { | ||
67 | if ((usage->hid & HID_USAGE_PAGE) != HID_UP_KEYBOARD) | ||
68 | return 0; | ||
69 | |||
70 | switch (usage->hid & HID_USAGE) { | ||
71 | /* Map all keys from Twinhan Remote */ | ||
72 | case 0x004: th_map_key_clear(KEY_TEXT); break; | ||
73 | case 0x006: th_map_key_clear(KEY_RESTART); break; | ||
74 | case 0x008: th_map_key_clear(KEY_EPG); break; | ||
75 | case 0x00c: th_map_key_clear(KEY_REWIND); break; | ||
76 | case 0x00e: th_map_key_clear(KEY_PROGRAM); break; | ||
77 | case 0x00f: th_map_key_clear(KEY_LIST); break; | ||
78 | case 0x010: th_map_key_clear(KEY_MUTE); break; | ||
79 | case 0x011: th_map_key_clear(KEY_FORWARD); break; | ||
80 | case 0x013: th_map_key_clear(KEY_PRINT); break; | ||
81 | case 0x017: th_map_key_clear(KEY_PAUSE); break; | ||
82 | case 0x019: th_map_key_clear(KEY_FAVORITES); break; | ||
83 | case 0x01d: th_map_key_clear(KEY_SCREEN); break; | ||
84 | case 0x01e: th_map_key_clear(KEY_NUMERIC_1); break; | ||
85 | case 0x01f: th_map_key_clear(KEY_NUMERIC_2); break; | ||
86 | case 0x020: th_map_key_clear(KEY_NUMERIC_3); break; | ||
87 | case 0x021: th_map_key_clear(KEY_NUMERIC_4); break; | ||
88 | case 0x022: th_map_key_clear(KEY_NUMERIC_5); break; | ||
89 | case 0x023: th_map_key_clear(KEY_NUMERIC_6); break; | ||
90 | case 0x024: th_map_key_clear(KEY_NUMERIC_7); break; | ||
91 | case 0x025: th_map_key_clear(KEY_NUMERIC_8); break; | ||
92 | case 0x026: th_map_key_clear(KEY_NUMERIC_9); break; | ||
93 | case 0x027: th_map_key_clear(KEY_NUMERIC_0); break; | ||
94 | case 0x028: th_map_key_clear(KEY_PLAY); break; | ||
95 | case 0x029: th_map_key_clear(KEY_CANCEL); break; | ||
96 | case 0x02b: th_map_key_clear(KEY_TAB); break; | ||
97 | /* Power = 0x0e0 + 0x0e1 + 0x0e2 + 0x03f */ | ||
98 | case 0x03f: th_map_key_clear(KEY_POWER2); break; | ||
99 | case 0x04a: th_map_key_clear(KEY_RECORD); break; | ||
100 | case 0x04b: th_map_key_clear(KEY_CHANNELUP); break; | ||
101 | case 0x04d: th_map_key_clear(KEY_STOP); break; | ||
102 | case 0x04e: th_map_key_clear(KEY_CHANNELDOWN); break; | ||
103 | /* Volume down = 0x0e1 + 0x051 */ | ||
104 | case 0x051: th_map_key_clear(KEY_VOLUMEDOWN); break; | ||
105 | /* Volume up = 0x0e1 + 0x052 */ | ||
106 | case 0x052: th_map_key_clear(KEY_VOLUMEUP); break; | ||
107 | /* Kill the extra keys used for multi-key "power" and "volume" keys | ||
108 | * as well as continuously to release CTRL,ALT,META,... keys */ | ||
109 | case 0x0e0: | ||
110 | case 0x0e1: | ||
111 | case 0x0e2: | ||
112 | case 0x0e3: | ||
113 | case 0x0e4: | ||
114 | case 0x0e5: | ||
115 | case 0x0e6: | ||
116 | case 0x0e7: | ||
117 | default: | ||
118 | return -1; | ||
119 | } | ||
120 | return 1; | ||
121 | } | ||
122 | |||
123 | static const struct hid_device_id twinhan_devices[] = { | ||
124 | { HID_USB_DEVICE(USB_VENDOR_ID_TWINHAN, USB_DEVICE_ID_TWINHAN_IR_REMOTE) }, | ||
125 | { } | ||
126 | }; | ||
127 | MODULE_DEVICE_TABLE(hid, twinhan_devices); | ||
128 | |||
129 | static struct hid_driver twinhan_driver = { | ||
130 | .name = "twinhan", | ||
131 | .id_table = twinhan_devices, | ||
132 | .input_mapping = twinhan_input_mapping, | ||
133 | }; | ||
134 | |||
135 | static int twinhan_init(void) | ||
136 | { | ||
137 | return hid_register_driver(&twinhan_driver); | ||
138 | } | ||
139 | |||
140 | static void twinhan_exit(void) | ||
141 | { | ||
142 | hid_unregister_driver(&twinhan_driver); | ||
143 | } | ||
144 | |||
145 | module_init(twinhan_init); | ||
146 | module_exit(twinhan_exit); | ||
147 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/hid/hid-wacom.c b/drivers/hid/hid-wacom.c index 1f9237f511e3..747542172242 100644 --- a/drivers/hid/hid-wacom.c +++ b/drivers/hid/hid-wacom.c | |||
@@ -237,7 +237,7 @@ static struct hid_driver wacom_driver = { | |||
237 | .raw_event = wacom_raw_event, | 237 | .raw_event = wacom_raw_event, |
238 | }; | 238 | }; |
239 | 239 | ||
240 | static int wacom_init(void) | 240 | static int __init wacom_init(void) |
241 | { | 241 | { |
242 | int ret; | 242 | int ret; |
243 | 243 | ||
@@ -248,7 +248,7 @@ static int wacom_init(void) | |||
248 | return ret; | 248 | return ret; |
249 | } | 249 | } |
250 | 250 | ||
251 | static void wacom_exit(void) | 251 | static void __exit wacom_exit(void) |
252 | { | 252 | { |
253 | hid_unregister_driver(&wacom_driver); | 253 | hid_unregister_driver(&wacom_driver); |
254 | } | 254 | } |
diff --git a/drivers/hid/hid-zpff.c b/drivers/hid/hid-zpff.c index 57f710757bf4..a79f0d78c6be 100644 --- a/drivers/hid/hid-zpff.c +++ b/drivers/hid/hid-zpff.c | |||
@@ -152,12 +152,12 @@ static struct hid_driver zp_driver = { | |||
152 | .probe = zp_probe, | 152 | .probe = zp_probe, |
153 | }; | 153 | }; |
154 | 154 | ||
155 | static int zp_init(void) | 155 | static int __init zp_init(void) |
156 | { | 156 | { |
157 | return hid_register_driver(&zp_driver); | 157 | return hid_register_driver(&zp_driver); |
158 | } | 158 | } |
159 | 159 | ||
160 | static void zp_exit(void) | 160 | static void __exit zp_exit(void) |
161 | { | 161 | { |
162 | hid_unregister_driver(&zp_driver); | 162 | hid_unregister_driver(&zp_driver); |
163 | } | 163 | } |
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 3c1fcb7640ab..03bd703255a3 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c | |||
@@ -4,8 +4,8 @@ | |||
4 | * Copyright (c) 1999 Andreas Gal | 4 | * Copyright (c) 1999 Andreas Gal |
5 | * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> | 5 | * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> |
6 | * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc | 6 | * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc |
7 | * Copyright (c) 2006-2008 Jiri Kosina | ||
8 | * Copyright (c) 2007-2008 Oliver Neukum | 7 | * Copyright (c) 2007-2008 Oliver Neukum |
8 | * Copyright (c) 2006-2009 Jiri Kosina | ||
9 | */ | 9 | */ |
10 | 10 | ||
11 | /* | 11 | /* |
@@ -489,7 +489,8 @@ static void hid_ctrl(struct urb *urb) | |||
489 | wake_up(&usbhid->wait); | 489 | wake_up(&usbhid->wait); |
490 | } | 490 | } |
491 | 491 | ||
492 | void __usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir) | 492 | static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *report, |
493 | unsigned char dir) | ||
493 | { | 494 | { |
494 | int head; | 495 | int head; |
495 | struct usbhid_device *usbhid = hid->driver_data; | 496 | struct usbhid_device *usbhid = hid->driver_data; |
@@ -885,11 +886,6 @@ static int usbhid_parse(struct hid_device *hid) | |||
885 | goto err; | 886 | goto err; |
886 | } | 887 | } |
887 | 888 | ||
888 | dbg_hid("report descriptor (size %u, read %d) = ", rsize, n); | ||
889 | for (n = 0; n < rsize; n++) | ||
890 | dbg_hid_line(" %02x", (unsigned char) rdesc[n]); | ||
891 | dbg_hid_line("\n"); | ||
892 | |||
893 | ret = hid_parse_report(hid, rdesc, rsize); | 889 | ret = hid_parse_report(hid, rdesc, rsize); |
894 | kfree(rdesc); | 890 | kfree(rdesc); |
895 | if (ret) { | 891 | if (ret) { |
@@ -986,7 +982,6 @@ static int usbhid_start(struct hid_device *hid) | |||
986 | setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid); | 982 | setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid); |
987 | 983 | ||
988 | spin_lock_init(&usbhid->lock); | 984 | spin_lock_init(&usbhid->lock); |
989 | spin_lock_init(&usbhid->lock); | ||
990 | 985 | ||
991 | usbhid->intf = intf; | 986 | usbhid->intf = intf; |
992 | usbhid->ifnum = interface->desc.bInterfaceNumber; | 987 | usbhid->ifnum = interface->desc.bInterfaceNumber; |
@@ -1004,7 +999,6 @@ static int usbhid_start(struct hid_device *hid) | |||
1004 | usbhid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP); | 999 | usbhid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP); |
1005 | 1000 | ||
1006 | usbhid_init_reports(hid); | 1001 | usbhid_init_reports(hid); |
1007 | hid_dump_device(hid); | ||
1008 | 1002 | ||
1009 | set_bit(HID_STARTED, &usbhid->iofl); | 1003 | set_bit(HID_STARTED, &usbhid->iofl); |
1010 | 1004 | ||
@@ -1047,13 +1041,6 @@ static void usbhid_stop(struct hid_device *hid) | |||
1047 | 1041 | ||
1048 | hid_cancel_delayed_stuff(usbhid); | 1042 | hid_cancel_delayed_stuff(usbhid); |
1049 | 1043 | ||
1050 | if (hid->claimed & HID_CLAIMED_INPUT) | ||
1051 | hidinput_disconnect(hid); | ||
1052 | if (hid->claimed & HID_CLAIMED_HIDDEV) | ||
1053 | hiddev_disconnect(hid); | ||
1054 | if (hid->claimed & HID_CLAIMED_HIDRAW) | ||
1055 | hidraw_disconnect(hid); | ||
1056 | |||
1057 | hid->claimed = 0; | 1044 | hid->claimed = 0; |
1058 | 1045 | ||
1059 | usb_free_urb(usbhid->urbin); | 1046 | usb_free_urb(usbhid->urbin); |
@@ -1091,7 +1078,7 @@ static struct hid_ll_driver usb_hid_driver = { | |||
1091 | .hidinput_input_event = usb_hidinput_input_event, | 1078 | .hidinput_input_event = usb_hidinput_input_event, |
1092 | }; | 1079 | }; |
1093 | 1080 | ||
1094 | static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id) | 1081 | static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id *id) |
1095 | { | 1082 | { |
1096 | struct usb_host_interface *interface = intf->cur_altsetting; | 1083 | struct usb_host_interface *interface = intf->cur_altsetting; |
1097 | struct usb_device *dev = interface_to_usbdev(intf); | 1084 | struct usb_device *dev = interface_to_usbdev(intf); |
@@ -1123,6 +1110,7 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id) | |||
1123 | hid->ff_init = hid_pidff_init; | 1110 | hid->ff_init = hid_pidff_init; |
1124 | #ifdef CONFIG_USB_HIDDEV | 1111 | #ifdef CONFIG_USB_HIDDEV |
1125 | hid->hiddev_connect = hiddev_connect; | 1112 | hid->hiddev_connect = hiddev_connect; |
1113 | hid->hiddev_disconnect = hiddev_disconnect; | ||
1126 | hid->hiddev_hid_event = hiddev_hid_event; | 1114 | hid->hiddev_hid_event = hiddev_hid_event; |
1127 | hid->hiddev_report_event = hiddev_report_event; | 1115 | hid->hiddev_report_event = hiddev_report_event; |
1128 | #endif | 1116 | #endif |
@@ -1183,7 +1171,7 @@ err: | |||
1183 | return ret; | 1171 | return ret; |
1184 | } | 1172 | } |
1185 | 1173 | ||
1186 | static void hid_disconnect(struct usb_interface *intf) | 1174 | static void usbhid_disconnect(struct usb_interface *intf) |
1187 | { | 1175 | { |
1188 | struct hid_device *hid = usb_get_intfdata(intf); | 1176 | struct hid_device *hid = usb_get_intfdata(intf); |
1189 | struct usbhid_device *usbhid; | 1177 | struct usbhid_device *usbhid; |
@@ -1365,8 +1353,8 @@ MODULE_DEVICE_TABLE (usb, hid_usb_ids); | |||
1365 | 1353 | ||
1366 | static struct usb_driver hid_driver = { | 1354 | static struct usb_driver hid_driver = { |
1367 | .name = "usbhid", | 1355 | .name = "usbhid", |
1368 | .probe = hid_probe, | 1356 | .probe = usbhid_probe, |
1369 | .disconnect = hid_disconnect, | 1357 | .disconnect = usbhid_disconnect, |
1370 | #ifdef CONFIG_PM | 1358 | #ifdef CONFIG_PM |
1371 | .suspend = hid_suspend, | 1359 | .suspend = hid_suspend, |
1372 | .resume = hid_resume, | 1360 | .resume = hid_resume, |
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index d8f7423f363e..0d9045aa2c4b 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c | |||
@@ -201,7 +201,7 @@ int usbhid_quirks_init(char **quirks_param) | |||
201 | u32 quirks; | 201 | u32 quirks; |
202 | int n = 0, m; | 202 | int n = 0, m; |
203 | 203 | ||
204 | for (; quirks_param[n] && n < MAX_USBHID_BOOT_QUIRKS; n++) { | 204 | for (; n < MAX_USBHID_BOOT_QUIRKS && quirks_param[n]; n++) { |
205 | 205 | ||
206 | m = sscanf(quirks_param[n], "0x%hx:0x%hx:0x%x", | 206 | m = sscanf(quirks_param[n], "0x%hx:0x%hx:0x%x", |
207 | &idVendor, &idProduct, &quirks); | 207 | &idVendor, &idProduct, &quirks); |
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index 215b2addddbb..8b6ee247bfe4 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c | |||
@@ -44,7 +44,7 @@ | |||
44 | #define HIDDEV_MINOR_BASE 96 | 44 | #define HIDDEV_MINOR_BASE 96 |
45 | #define HIDDEV_MINORS 16 | 45 | #define HIDDEV_MINORS 16 |
46 | #endif | 46 | #endif |
47 | #define HIDDEV_BUFFER_SIZE 64 | 47 | #define HIDDEV_BUFFER_SIZE 2048 |
48 | 48 | ||
49 | struct hiddev { | 49 | struct hiddev { |
50 | int exist; | 50 | int exist; |
@@ -852,14 +852,14 @@ static const struct file_operations hiddev_fops = { | |||
852 | #endif | 852 | #endif |
853 | }; | 853 | }; |
854 | 854 | ||
855 | static char *hiddev_nodename(struct device *dev) | 855 | static char *hiddev_devnode(struct device *dev, mode_t *mode) |
856 | { | 856 | { |
857 | return kasprintf(GFP_KERNEL, "usb/%s", dev_name(dev)); | 857 | return kasprintf(GFP_KERNEL, "usb/%s", dev_name(dev)); |
858 | } | 858 | } |
859 | 859 | ||
860 | static struct usb_class_driver hiddev_class = { | 860 | static struct usb_class_driver hiddev_class = { |
861 | .name = "hiddev%d", | 861 | .name = "hiddev%d", |
862 | .nodename = hiddev_nodename, | 862 | .devnode = hiddev_devnode, |
863 | .fops = &hiddev_fops, | 863 | .fops = &hiddev_fops, |
864 | .minor_base = HIDDEV_MINOR_BASE, | 864 | .minor_base = HIDDEV_MINOR_BASE, |
865 | }; | 865 | }; |