diff options
Diffstat (limited to 'drivers/hid')
-rw-r--r-- | drivers/hid/Kconfig | 7 | ||||
-rw-r--r-- | drivers/hid/Makefile | 1 | ||||
-rw-r--r-- | drivers/hid/hid-core.c | 3 | ||||
-rw-r--r-- | drivers/hid/hid-cypress.c | 158 | ||||
-rw-r--r-- | drivers/hid/hid-dummy.c | 3 | ||||
-rw-r--r-- | drivers/hid/hid-input-quirks.c | 4 | ||||
-rw-r--r-- | drivers/hid/hid-input.c | 6 | ||||
-rw-r--r-- | drivers/hid/usbhid/hid-quirks.c | 31 |
8 files changed, 177 insertions, 36 deletions
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 147223993b86..69f3420882a6 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig | |||
@@ -96,6 +96,13 @@ config HID_APPLE | |||
96 | 96 | ||
97 | If unsure, say M. | 97 | If unsure, say M. |
98 | 98 | ||
99 | config HID_CYPRESS | ||
100 | tristate "Cypress" | ||
101 | default m | ||
102 | depends on USB_HID | ||
103 | ---help--- | ||
104 | Support for Cypress mouse and barcodes. | ||
105 | |||
99 | config HID_LOGITECH | 106 | config HID_LOGITECH |
100 | tristate "Logitech" | 107 | tristate "Logitech" |
101 | default m | 108 | default m |
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index 314d5b0c70d5..061066201186 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile | |||
@@ -13,6 +13,7 @@ obj-m += hid-dummy.o | |||
13 | endif | 13 | endif |
14 | 14 | ||
15 | obj-$(CONFIG_HID_APPLE) += hid-apple.o | 15 | obj-$(CONFIG_HID_APPLE) += hid-apple.o |
16 | obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o | ||
16 | obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o | 17 | obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o |
17 | obj-$(CONFIG_HID_MICROSOFT) += hid-microsoft.o | 18 | obj-$(CONFIG_HID_MICROSOFT) += hid-microsoft.o |
18 | obj-$(CONFIG_HID_SUNPLUS) += hid-sunplus.o | 19 | obj-$(CONFIG_HID_SUNPLUS) += hid-sunplus.o |
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index e9e6dbbaaa83..331670b32e68 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
@@ -1162,6 +1162,9 @@ static const struct hid_device_id hid_blacklist[] = { | |||
1162 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS) }, | 1162 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS) }, |
1163 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, | 1163 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, |
1164 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, | 1164 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, |
1165 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) }, | ||
1166 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) }, | ||
1167 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE) }, | ||
1165 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) }, | 1168 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) }, |
1166 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) }, | 1169 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) }, |
1167 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2) }, | 1170 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2) }, |
diff --git a/drivers/hid/hid-cypress.c b/drivers/hid/hid-cypress.c new file mode 100644 index 000000000000..a1e13f15f0a7 --- /dev/null +++ b/drivers/hid/hid-cypress.c | |||
@@ -0,0 +1,158 @@ | |||
1 | /* | ||
2 | * HID driver for some cypress "special" devices | ||
3 | * | ||
4 | * Copyright (c) 1999 Andreas Gal | ||
5 | * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> | ||
6 | * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc | ||
7 | * Copyright (c) 2006-2007 Jiri Kosina | ||
8 | * Copyright (c) 2007 Paul Walmsley | ||
9 | * Copyright (c) 2008 Jiri Slaby | ||
10 | */ | ||
11 | |||
12 | /* | ||
13 | * This program is free software; you can redistribute it and/or modify it | ||
14 | * under the terms of the GNU General Public License as published by the Free | ||
15 | * Software Foundation; either version 2 of the License, or (at your option) | ||
16 | * any later version. | ||
17 | */ | ||
18 | |||
19 | #include <linux/device.h> | ||
20 | #include <linux/hid.h> | ||
21 | #include <linux/input.h> | ||
22 | #include <linux/module.h> | ||
23 | |||
24 | #include "hid-ids.h" | ||
25 | |||
26 | #define CP_RDESC_SWAPPED_MIN_MAX 0x01 | ||
27 | #define CP_2WHEEL_MOUSE_HACK 0x02 | ||
28 | #define CP_2WHEEL_MOUSE_HACK_ON 0x04 | ||
29 | |||
30 | /* | ||
31 | * Some USB barcode readers from cypress have usage min and usage max in | ||
32 | * the wrong order | ||
33 | */ | ||
34 | static void cp_report_fixup(struct hid_device *hdev, __u8 *rdesc, | ||
35 | unsigned int rsize) | ||
36 | { | ||
37 | unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); | ||
38 | unsigned int i; | ||
39 | |||
40 | if (!(quirks & CP_RDESC_SWAPPED_MIN_MAX)) | ||
41 | return; | ||
42 | |||
43 | for (i = 0; i < rsize - 4; i++) | ||
44 | if (rdesc[i] == 0x29 && rdesc[i + 2] == 0x19) { | ||
45 | __u8 tmp; | ||
46 | |||
47 | rdesc[i] = 0x19; | ||
48 | rdesc[i + 2] = 0x29; | ||
49 | tmp = rdesc[i + 3]; | ||
50 | rdesc[i + 3] = rdesc[i + 1]; | ||
51 | rdesc[i + 1] = tmp; | ||
52 | } | ||
53 | } | ||
54 | |||
55 | static int cp_input_mapped(struct hid_device *hdev, struct hid_input *hi, | ||
56 | struct hid_field *field, struct hid_usage *usage, | ||
57 | unsigned long **bit, int *max) | ||
58 | { | ||
59 | unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); | ||
60 | |||
61 | if (!(quirks & CP_2WHEEL_MOUSE_HACK)) | ||
62 | return 0; | ||
63 | |||
64 | if (usage->type == EV_REL && usage->code == REL_WHEEL) | ||
65 | set_bit(REL_HWHEEL, *bit); | ||
66 | if (usage->hid == 0x00090005) | ||
67 | return -1; | ||
68 | |||
69 | return 0; | ||
70 | } | ||
71 | |||
72 | static int cp_event(struct hid_device *hdev, struct hid_field *field, | ||
73 | struct hid_usage *usage, __s32 value) | ||
74 | { | ||
75 | unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); | ||
76 | |||
77 | if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput || | ||
78 | !usage->type || !(quirks & CP_2WHEEL_MOUSE_HACK)) | ||
79 | return 0; | ||
80 | |||
81 | if (usage->hid == 0x00090005) { | ||
82 | if (value) | ||
83 | quirks |= CP_2WHEEL_MOUSE_HACK_ON; | ||
84 | else | ||
85 | quirks &= ~CP_2WHEEL_MOUSE_HACK_ON; | ||
86 | hid_set_drvdata(hdev, (void *)quirks); | ||
87 | return 1; | ||
88 | } | ||
89 | |||
90 | if (usage->code == REL_WHEEL && (quirks & CP_2WHEEL_MOUSE_HACK_ON)) { | ||
91 | struct input_dev *input = field->hidinput->input; | ||
92 | |||
93 | input_event(input, usage->type, REL_HWHEEL, value); | ||
94 | return 1; | ||
95 | } | ||
96 | |||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | static int cp_probe(struct hid_device *hdev, const struct hid_device_id *id) | ||
101 | { | ||
102 | unsigned long quirks = id->driver_data; | ||
103 | int ret; | ||
104 | |||
105 | hid_set_drvdata(hdev, (void *)quirks); | ||
106 | |||
107 | ret = hid_parse(hdev); | ||
108 | if (ret) { | ||
109 | dev_err(&hdev->dev, "parse failed\n"); | ||
110 | goto err_free; | ||
111 | } | ||
112 | |||
113 | ret = hid_hw_start(hdev); | ||
114 | if (ret) { | ||
115 | dev_err(&hdev->dev, "hw start failed\n"); | ||
116 | goto err_free; | ||
117 | } | ||
118 | |||
119 | return 0; | ||
120 | err_free: | ||
121 | return ret; | ||
122 | } | ||
123 | |||
124 | static const struct hid_device_id cp_devices[] = { | ||
125 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1), | ||
126 | .driver_data = CP_RDESC_SWAPPED_MIN_MAX }, | ||
127 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2), | ||
128 | .driver_data = CP_RDESC_SWAPPED_MIN_MAX }, | ||
129 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE), | ||
130 | .driver_data = CP_2WHEEL_MOUSE_HACK }, | ||
131 | { } | ||
132 | }; | ||
133 | MODULE_DEVICE_TABLE(hid, cp_devices); | ||
134 | |||
135 | static struct hid_driver cp_driver = { | ||
136 | .name = "cypress", | ||
137 | .id_table = cp_devices, | ||
138 | .report_fixup = cp_report_fixup, | ||
139 | .input_mapped = cp_input_mapped, | ||
140 | .event = cp_event, | ||
141 | .probe = cp_probe, | ||
142 | }; | ||
143 | |||
144 | static int cp_init(void) | ||
145 | { | ||
146 | return hid_register_driver(&cp_driver); | ||
147 | } | ||
148 | |||
149 | static void cp_exit(void) | ||
150 | { | ||
151 | hid_unregister_driver(&cp_driver); | ||
152 | } | ||
153 | |||
154 | module_init(cp_init); | ||
155 | module_exit(cp_exit); | ||
156 | MODULE_LICENSE("GPL"); | ||
157 | |||
158 | HID_COMPAT_LOAD_DRIVER(cypress); | ||
diff --git a/drivers/hid/hid-dummy.c b/drivers/hid/hid-dummy.c index 0c833d920c3d..27cffe3586f5 100644 --- a/drivers/hid/hid-dummy.c +++ b/drivers/hid/hid-dummy.c | |||
@@ -7,6 +7,9 @@ static int __init hid_dummy_init(void) | |||
7 | #ifdef CONFIG_HID_APPLE_MODULE | 7 | #ifdef CONFIG_HID_APPLE_MODULE |
8 | HID_COMPAT_CALL_DRIVER(apple); | 8 | HID_COMPAT_CALL_DRIVER(apple); |
9 | #endif | 9 | #endif |
10 | #ifdef CONFIG_HID_CYPRESS_MODULE | ||
11 | HID_COMPAT_CALL_DRIVER(cypress); | ||
12 | #endif | ||
10 | #ifdef CONFIG_HID_LOGITECH_MODULE | 13 | #ifdef CONFIG_HID_LOGITECH_MODULE |
11 | HID_COMPAT_CALL_DRIVER(logitech); | 14 | HID_COMPAT_CALL_DRIVER(logitech); |
12 | #endif | 15 | #endif |
diff --git a/drivers/hid/hid-input-quirks.c b/drivers/hid/hid-input-quirks.c index a5e7163158fb..6e7314f7b998 100644 --- a/drivers/hid/hid-input-quirks.c +++ b/drivers/hid/hid-input-quirks.c | |||
@@ -236,8 +236,8 @@ int hidinput_event_quirks(struct hid_device *hid, struct hid_field *field, struc | |||
236 | 236 | ||
237 | input = field->hidinput->input; | 237 | input = field->hidinput->input; |
238 | 238 | ||
239 | if (((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_5) && (usage->hid == 0x00090005)) | 239 | if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_7) && |
240 | || ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_7) && (usage->hid == 0x00090007))) { | 240 | (usage->hid == 0x00090007)) { |
241 | if (value) hid->quirks |= HID_QUIRK_2WHEEL_MOUSE_HACK_ON; | 241 | if (value) hid->quirks |= HID_QUIRK_2WHEEL_MOUSE_HACK_ON; |
242 | else hid->quirks &= ~HID_QUIRK_2WHEEL_MOUSE_HACK_ON; | 242 | else hid->quirks &= ~HID_QUIRK_2WHEEL_MOUSE_HACK_ON; |
243 | return 1; | 243 | return 1; |
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index a6223bc5c734..f1df25ab0baa 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c | |||
@@ -515,13 +515,13 @@ mapped: | |||
515 | hidinput, field, usage, &bit, &max) < 0) | 515 | hidinput, field, usage, &bit, &max) < 0) |
516 | goto ignore; | 516 | goto ignore; |
517 | 517 | ||
518 | if ((device->quirks & (HID_QUIRK_2WHEEL_MOUSE_HACK_7 | HID_QUIRK_2WHEEL_MOUSE_HACK_5 | | 518 | if ((device->quirks & (HID_QUIRK_2WHEEL_MOUSE_HACK_7 | |
519 | HID_QUIRK_2WHEEL_MOUSE_HACK_B8)) && (usage->type == EV_REL) && | 519 | HID_QUIRK_2WHEEL_MOUSE_HACK_B8)) && (usage->type == EV_REL) && |
520 | (usage->code == REL_WHEEL)) | 520 | (usage->code == REL_WHEEL)) |
521 | set_bit(REL_HWHEEL, bit); | 521 | set_bit(REL_HWHEEL, bit); |
522 | 522 | ||
523 | if (((device->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_5) && (usage->hid == 0x00090005)) | 523 | if ((device->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_7) && |
524 | || ((device->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_7) && (usage->hid == 0x00090007))) | 524 | (usage->hid == 0x00090007)) |
525 | goto ignore; | 525 | goto ignore; |
526 | 526 | ||
527 | set_bit(usage->type, input->evbit); | 527 | set_bit(usage->type, input->evbit); |
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 7f38c21e146b..da80c64fb25c 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c | |||
@@ -31,7 +31,6 @@ static const struct hid_blacklist { | |||
31 | 31 | ||
32 | { USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, HID_QUIRK_2WHEEL_MOUSE_HACK_7 }, | 32 | { USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, HID_QUIRK_2WHEEL_MOUSE_HACK_7 }, |
33 | { USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D, HID_QUIRK_2WHEEL_MOUSE_HACK_B8 }, | 33 | { USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D, HID_QUIRK_2WHEEL_MOUSE_HACK_B8 }, |
34 | { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE, HID_QUIRK_2WHEEL_MOUSE_HACK_5 }, | ||
35 | 34 | ||
36 | { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_GAMEPAD, HID_QUIRK_BADPAD }, | 35 | { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_GAMEPAD, HID_QUIRK_BADPAD }, |
37 | { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_PREDATOR, HID_QUIRK_BADPAD }, | 36 | { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_PREDATOR, HID_QUIRK_BADPAD }, |
@@ -93,9 +92,6 @@ static const struct hid_rdesc_blacklist { | |||
93 | 92 | ||
94 | { USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE, HID_QUIRK_RDESC_SAMSUNG_REMOTE }, | 93 | { USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE, HID_QUIRK_RDESC_SAMSUNG_REMOTE }, |
95 | 94 | ||
96 | { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1, HID_QUIRK_RDESC_SWAPPED_MIN_MAX }, | ||
97 | { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2, HID_QUIRK_RDESC_SWAPPED_MIN_MAX }, | ||
98 | |||
99 | { 0, 0 } | 95 | { 0, 0 } |
100 | }; | 96 | }; |
101 | 97 | ||
@@ -382,30 +378,6 @@ static void usbhid_fixup_petalynx_descriptor(unsigned char *rdesc, int rsize) | |||
382 | } | 378 | } |
383 | } | 379 | } |
384 | 380 | ||
385 | /* | ||
386 | * Some USB barcode readers from cypress have usage min and usage max in | ||
387 | * the wrong order | ||
388 | */ | ||
389 | static void usbhid_fixup_cypress_descriptor(unsigned char *rdesc, int rsize) | ||
390 | { | ||
391 | short fixed = 0; | ||
392 | int i; | ||
393 | |||
394 | for (i = 0; i < rsize - 4; i++) { | ||
395 | if (rdesc[i] == 0x29 && rdesc [i+2] == 0x19) { | ||
396 | unsigned char tmp; | ||
397 | |||
398 | rdesc[i] = 0x19; rdesc[i+2] = 0x29; | ||
399 | tmp = rdesc[i+3]; | ||
400 | rdesc[i+3] = rdesc[i+1]; | ||
401 | rdesc[i+1] = tmp; | ||
402 | } | ||
403 | } | ||
404 | |||
405 | if (fixed) | ||
406 | printk(KERN_INFO "Fixing up Cypress report descriptor\n"); | ||
407 | } | ||
408 | |||
409 | static void usbhid_fixup_button_consumer_descriptor(unsigned char *rdesc, int rsize) | 381 | static void usbhid_fixup_button_consumer_descriptor(unsigned char *rdesc, int rsize) |
410 | { | 382 | { |
411 | if (rsize >= 30 && rdesc[29] == 0x05 | 383 | if (rsize >= 30 && rdesc[29] == 0x05 |
@@ -420,9 +392,6 @@ static void __usbhid_fixup_report_descriptor(__u32 quirks, char *rdesc, unsigned | |||
420 | if ((quirks & HID_QUIRK_RDESC_CYMOTION)) | 392 | if ((quirks & HID_QUIRK_RDESC_CYMOTION)) |
421 | usbhid_fixup_cymotion_descriptor(rdesc, rsize); | 393 | usbhid_fixup_cymotion_descriptor(rdesc, rsize); |
422 | 394 | ||
423 | if (quirks & HID_QUIRK_RDESC_SWAPPED_MIN_MAX) | ||
424 | usbhid_fixup_cypress_descriptor(rdesc, rsize); | ||
425 | |||
426 | if (quirks & HID_QUIRK_RDESC_PETALYNX) | 395 | if (quirks & HID_QUIRK_RDESC_PETALYNX) |
427 | usbhid_fixup_petalynx_descriptor(rdesc, rsize); | 396 | usbhid_fixup_petalynx_descriptor(rdesc, rsize); |
428 | 397 | ||