aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/hid/Kconfig7
-rw-r--r--drivers/hid/Makefile1
-rw-r--r--drivers/hid/hid-core.c3
-rw-r--r--drivers/hid/hid-cypress.c158
-rw-r--r--drivers/hid/hid-dummy.c3
-rw-r--r--drivers/hid/hid-input-quirks.c4
-rw-r--r--drivers/hid/hid-input.c6
-rw-r--r--drivers/hid/usbhid/hid-quirks.c31
-rw-r--r--include/linux/hid.h2
9 files changed, 177 insertions, 38 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
99config HID_CYPRESS
100 tristate "Cypress"
101 default m
102 depends on USB_HID
103 ---help---
104 Support for Cypress mouse and barcodes.
105
99config HID_LOGITECH 106config 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
13endif 13endif
14 14
15obj-$(CONFIG_HID_APPLE) += hid-apple.o 15obj-$(CONFIG_HID_APPLE) += hid-apple.o
16obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o
16obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o 17obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o
17obj-$(CONFIG_HID_MICROSOFT) += hid-microsoft.o 18obj-$(CONFIG_HID_MICROSOFT) += hid-microsoft.o
18obj-$(CONFIG_HID_SUNPLUS) += hid-sunplus.o 19obj-$(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 */
34static 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
55static 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
72static 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
100static 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;
120err_free:
121 return ret;
122}
123
124static 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};
133MODULE_DEVICE_TABLE(hid, cp_devices);
134
135static 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
144static int cp_init(void)
145{
146 return hid_register_driver(&cp_driver);
147}
148
149static void cp_exit(void)
150{
151 hid_unregister_driver(&cp_driver);
152}
153
154module_init(cp_init);
155module_exit(cp_exit);
156MODULE_LICENSE("GPL");
157
158HID_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 */
389static 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
409static void usbhid_fixup_button_consumer_descriptor(unsigned char *rdesc, int rsize) 381static 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
diff --git a/include/linux/hid.h b/include/linux/hid.h
index a83d211021de..27bfbcc1ef81 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -262,7 +262,6 @@ struct hid_item {
262#define HID_QUIRK_BADPAD 0x00000020 262#define HID_QUIRK_BADPAD 0x00000020
263#define HID_QUIRK_MULTI_INPUT 0x00000040 263#define HID_QUIRK_MULTI_INPUT 0x00000040
264#define HID_QUIRK_2WHEEL_MOUSE_HACK_7 0x00000080 264#define HID_QUIRK_2WHEEL_MOUSE_HACK_7 0x00000080
265#define HID_QUIRK_2WHEEL_MOUSE_HACK_5 0x00000100
266#define HID_QUIRK_2WHEEL_MOUSE_HACK_ON 0x00000200 265#define HID_QUIRK_2WHEEL_MOUSE_HACK_ON 0x00000200
267#define HID_QUIRK_SKIP_OUTPUT_REPORTS 0x00010000 266#define HID_QUIRK_SKIP_OUTPUT_REPORTS 0x00010000
268#define HID_QUIRK_SONY_PS3_CONTROLLER 0x00040000 267#define HID_QUIRK_SONY_PS3_CONTROLLER 0x00040000
@@ -278,7 +277,6 @@ struct hid_item {
278 */ 277 */
279 278
280#define HID_QUIRK_RDESC_CYMOTION 0x00000001 279#define HID_QUIRK_RDESC_CYMOTION 0x00000001
281#define HID_QUIRK_RDESC_SWAPPED_MIN_MAX 0x00000004
282#define HID_QUIRK_RDESC_PETALYNX 0x00000008 280#define HID_QUIRK_RDESC_PETALYNX 0x00000008
283#define HID_QUIRK_RDESC_BUTTON_CONSUMER 0x00000020 281#define HID_QUIRK_RDESC_BUTTON_CONSUMER 0x00000020
284#define HID_QUIRK_RDESC_SAMSUNG_REMOTE 0x00000040 282#define HID_QUIRK_RDESC_SAMSUNG_REMOTE 0x00000040