diff options
-rw-r--r-- | drivers/hid/Kconfig | 7 | ||||
-rw-r--r-- | drivers/hid/Makefile | 1 | ||||
-rw-r--r-- | drivers/hid/hid-core.c | 1 | ||||
-rw-r--r-- | drivers/hid/hid-dummy.c | 3 | ||||
-rw-r--r-- | drivers/hid/hid-samsung.c | 101 | ||||
-rw-r--r-- | drivers/hid/usbhid/hid-quirks.c | 33 | ||||
-rw-r--r-- | include/linux/hid.h | 6 |
7 files changed, 113 insertions, 39 deletions
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 4dcb92ac887a..52b617bf2b93 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig | |||
@@ -175,6 +175,13 @@ config HID_PETALYNX | |||
175 | ---help--- | 175 | ---help--- |
176 | Support for Petalynx Maxter remote. | 176 | Support for Petalynx Maxter remote. |
177 | 177 | ||
178 | config HID_SAMSUNG | ||
179 | tristate "Samsung" | ||
180 | default m | ||
181 | depends on USB_HID | ||
182 | ---help--- | ||
183 | Support for Samsung IR remote. | ||
184 | |||
178 | config HID_SUNPLUS | 185 | config HID_SUNPLUS |
179 | tristate "Sunplus" | 186 | tristate "Sunplus" |
180 | default m | 187 | default m |
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index 50a06f71b48a..735c371ca02e 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile | |||
@@ -24,6 +24,7 @@ obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o | |||
24 | obj-$(CONFIG_HID_MICROSOFT) += hid-microsoft.o | 24 | obj-$(CONFIG_HID_MICROSOFT) += hid-microsoft.o |
25 | obj-$(CONFIG_HID_MONTEREY) += hid-monterey.o | 25 | obj-$(CONFIG_HID_MONTEREY) += hid-monterey.o |
26 | obj-$(CONFIG_HID_PETALYNX) += hid-petalynx.o | 26 | obj-$(CONFIG_HID_PETALYNX) += hid-petalynx.o |
27 | obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o | ||
27 | obj-$(CONFIG_HID_SUNPLUS) += hid-sunplus.o | 28 | obj-$(CONFIG_HID_SUNPLUS) += hid-sunplus.o |
28 | 29 | ||
29 | obj-$(CONFIG_USB_HID) += usbhid/ | 30 | obj-$(CONFIG_USB_HID) += usbhid/ |
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 53f30560b930..1b43af072ce0 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
@@ -1194,6 +1194,7 @@ static const struct hid_device_id hid_blacklist[] = { | |||
1194 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) }, | 1194 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) }, |
1195 | { HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) }, | 1195 | { HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) }, |
1196 | { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) }, | 1196 | { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) }, |
1197 | { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, | ||
1197 | { HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) }, | 1198 | { HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) }, |
1198 | 1199 | ||
1199 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, 0x030c) }, | 1200 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, 0x030c) }, |
diff --git a/drivers/hid/hid-dummy.c b/drivers/hid/hid-dummy.c index 1c9e7c2814a5..cd21dcc41816 100644 --- a/drivers/hid/hid-dummy.c +++ b/drivers/hid/hid-dummy.c | |||
@@ -40,6 +40,9 @@ static int __init hid_dummy_init(void) | |||
40 | #ifdef CONFIG_HID_PETALYNX_MODULE | 40 | #ifdef CONFIG_HID_PETALYNX_MODULE |
41 | HID_COMPAT_CALL_DRIVER(petalynx); | 41 | HID_COMPAT_CALL_DRIVER(petalynx); |
42 | #endif | 42 | #endif |
43 | #ifdef CONFIG_HID_SAMSUNG_MODULE | ||
44 | HID_COMPAT_CALL_DRIVER(samsung); | ||
45 | #endif | ||
43 | #ifdef CONFIG_HID_SUNPLUS_MODULE | 46 | #ifdef CONFIG_HID_SUNPLUS_MODULE |
44 | HID_COMPAT_CALL_DRIVER(sunplus); | 47 | HID_COMPAT_CALL_DRIVER(sunplus); |
45 | #endif | 48 | #endif |
diff --git a/drivers/hid/hid-samsung.c b/drivers/hid/hid-samsung.c new file mode 100644 index 000000000000..8771bfae02f5 --- /dev/null +++ b/drivers/hid/hid-samsung.c | |||
@@ -0,0 +1,101 @@ | |||
1 | /* | ||
2 | * HID driver for some samsung "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/module.h> | ||
22 | |||
23 | #include "hid-ids.h" | ||
24 | |||
25 | /* | ||
26 | * Samsung IrDA remote controller (reports as Cypress USB Mouse). | ||
27 | * | ||
28 | * Vendor specific report #4 has a size of 48 bit, | ||
29 | * and therefore is not accepted when inspecting the descriptors. | ||
30 | * As a workaround we reinterpret the report as: | ||
31 | * Variable type, count 6, size 8 bit, log. maximum 255 | ||
32 | * The burden to reconstruct the data is moved into user space. | ||
33 | */ | ||
34 | static void samsung_report_fixup(struct hid_device *hdev, __u8 *rdesc, | ||
35 | unsigned int rsize) | ||
36 | { | ||
37 | if (rsize >= 182 && rdesc[175] == 0x25 && rdesc[176] == 0x40 && | ||
38 | rdesc[177] == 0x75 && rdesc[178] == 0x30 && | ||
39 | rdesc[179] == 0x95 && rdesc[180] == 0x01 && | ||
40 | rdesc[182] == 0x40) { | ||
41 | dev_info(&hdev->dev, "fixing up Samsung IrDA report " | ||
42 | "descriptor\n"); | ||
43 | rdesc[176] = 0xff; | ||
44 | rdesc[178] = 0x08; | ||
45 | rdesc[180] = 0x06; | ||
46 | rdesc[182] = 0x42; | ||
47 | } | ||
48 | } | ||
49 | |||
50 | static int samsung_probe(struct hid_device *hdev, | ||
51 | const struct hid_device_id *id) | ||
52 | { | ||
53 | int ret; | ||
54 | |||
55 | hdev->quirks |= HID_QUIRK_HIDDEV | HID_QUIRK_IGNORE_HIDINPUT; | ||
56 | |||
57 | ret = hid_parse(hdev); | ||
58 | if (ret) { | ||
59 | dev_err(&hdev->dev, "parse failed\n"); | ||
60 | goto err_free; | ||
61 | } | ||
62 | |||
63 | ret = hid_hw_start(hdev); | ||
64 | if (ret) { | ||
65 | dev_err(&hdev->dev, "hw start failed\n"); | ||
66 | goto err_free; | ||
67 | } | ||
68 | |||
69 | return 0; | ||
70 | err_free: | ||
71 | return ret; | ||
72 | } | ||
73 | |||
74 | static const struct hid_device_id samsung_devices[] = { | ||
75 | { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, | ||
76 | { } | ||
77 | }; | ||
78 | MODULE_DEVICE_TABLE(hid, samsung_devices); | ||
79 | |||
80 | static struct hid_driver samsung_driver = { | ||
81 | .name = "samsung", | ||
82 | .id_table = samsung_devices, | ||
83 | .report_fixup = samsung_report_fixup, | ||
84 | .probe = samsung_probe, | ||
85 | }; | ||
86 | |||
87 | static int samsung_init(void) | ||
88 | { | ||
89 | return hid_register_driver(&samsung_driver); | ||
90 | } | ||
91 | |||
92 | static void samsung_exit(void) | ||
93 | { | ||
94 | hid_unregister_driver(&samsung_driver); | ||
95 | } | ||
96 | |||
97 | module_init(samsung_init); | ||
98 | module_exit(samsung_exit); | ||
99 | MODULE_LICENSE("GPL"); | ||
100 | |||
101 | HID_COMPAT_LOAD_DRIVER(samsung); | ||
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index cc1927b1b88a..d57a37997f9a 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c | |||
@@ -43,8 +43,6 @@ static const struct hid_blacklist { | |||
43 | 43 | ||
44 | { USB_VENDOR_ID_AFATECH, USB_DEVICE_ID_AFATECH_AF9016, HID_QUIRK_FULLSPEED_INTERVAL }, | 44 | { USB_VENDOR_ID_AFATECH, USB_DEVICE_ID_AFATECH_AF9016, HID_QUIRK_FULLSPEED_INTERVAL }, |
45 | 45 | ||
46 | { USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE, HID_QUIRK_HIDDEV | HID_QUIRK_IGNORE_HIDINPUT }, | ||
47 | |||
48 | { USB_VENDOR_ID_PANTHERLORD, USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK, HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS }, | 46 | { USB_VENDOR_ID_PANTHERLORD, USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK, HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS }, |
49 | { USB_VENDOR_ID_PLAYDOTCOM, USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII, HID_QUIRK_MULTI_INPUT }, | 47 | { USB_VENDOR_ID_PLAYDOTCOM, USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII, HID_QUIRK_MULTI_INPUT }, |
50 | 48 | ||
@@ -75,8 +73,6 @@ static const struct hid_rdesc_blacklist { | |||
75 | __u16 idProduct; | 73 | __u16 idProduct; |
76 | __u32 quirks; | 74 | __u32 quirks; |
77 | } hid_rdesc_blacklist[] = { | 75 | } hid_rdesc_blacklist[] = { |
78 | { USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE, HID_QUIRK_RDESC_SAMSUNG_REMOTE }, | ||
79 | |||
80 | { 0, 0 } | 76 | { 0, 0 } |
81 | }; | 77 | }; |
82 | 78 | ||
@@ -308,37 +304,8 @@ u32 usbhid_lookup_quirk(const u16 idVendor, const u16 idProduct) | |||
308 | 304 | ||
309 | EXPORT_SYMBOL_GPL(usbhid_lookup_quirk); | 305 | EXPORT_SYMBOL_GPL(usbhid_lookup_quirk); |
310 | 306 | ||
311 | /* | ||
312 | * Samsung IrDA remote controller (reports as Cypress USB Mouse). | ||
313 | * | ||
314 | * Vendor specific report #4 has a size of 48 bit, | ||
315 | * and therefore is not accepted when inspecting the descriptors. | ||
316 | * As a workaround we reinterpret the report as: | ||
317 | * Variable type, count 6, size 8 bit, log. maximum 255 | ||
318 | * The burden to reconstruct the data is moved into user space. | ||
319 | */ | ||
320 | static void usbhid_fixup_samsung_irda_descriptor(unsigned char *rdesc, | ||
321 | int rsize) | ||
322 | { | ||
323 | if (rsize >= 182 && rdesc[175] == 0x25 | ||
324 | && rdesc[176] == 0x40 | ||
325 | && rdesc[177] == 0x75 | ||
326 | && rdesc[178] == 0x30 | ||
327 | && rdesc[179] == 0x95 | ||
328 | && rdesc[180] == 0x01 | ||
329 | && rdesc[182] == 0x40) { | ||
330 | printk(KERN_INFO "Fixing up Samsung IrDA report descriptor\n"); | ||
331 | rdesc[176] = 0xff; | ||
332 | rdesc[178] = 0x08; | ||
333 | rdesc[180] = 0x06; | ||
334 | rdesc[182] = 0x42; | ||
335 | } | ||
336 | } | ||
337 | |||
338 | static void __usbhid_fixup_report_descriptor(__u32 quirks, char *rdesc, unsigned rsize) | 307 | static void __usbhid_fixup_report_descriptor(__u32 quirks, char *rdesc, unsigned rsize) |
339 | { | 308 | { |
340 | if (quirks & HID_QUIRK_RDESC_SAMSUNG_REMOTE) | ||
341 | usbhid_fixup_samsung_irda_descriptor(rdesc, rsize); | ||
342 | } | 309 | } |
343 | 310 | ||
344 | /** | 311 | /** |
diff --git a/include/linux/hid.h b/include/linux/hid.h index 3a639bff4ab2..5b47feecc101 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h | |||
@@ -269,12 +269,6 @@ struct hid_item { | |||
269 | #define HID_QUIRK_FULLSPEED_INTERVAL 0x10000000 | 269 | #define HID_QUIRK_FULLSPEED_INTERVAL 0x10000000 |
270 | 270 | ||
271 | /* | 271 | /* |
272 | * Separate quirks for runtime report descriptor fixup | ||
273 | */ | ||
274 | |||
275 | #define HID_QUIRK_RDESC_SAMSUNG_REMOTE 0x00000040 | ||
276 | |||
277 | /* | ||
278 | * This is the global environment of the parser. This information is | 272 | * This is the global environment of the parser. This information is |
279 | * persistent for main-items. The global environment can be saved and | 273 | * persistent for main-items. The global environment can be saved and |
280 | * restored with PUSH/POP statements. | 274 | * restored with PUSH/POP statements. |