diff options
author | Jiri Slaby <jirislaby@gmail.com> | 2008-05-16 05:49:19 -0400 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2008-10-14 17:50:49 -0400 |
commit | 5f22a7992349c5ca3842190be52d5e9a1dd7adf4 (patch) | |
tree | edcb112c502a311d51c29cc0304a1316dcd2d433 /drivers | |
parent | 022e8c4d08b3b06361594b60412db0242035c4b4 (diff) |
HID: move logitech quirks
Move them from the core and input code to a separate driver.
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/hid/Kconfig | 13 | ||||
-rw-r--r-- | drivers/hid/Makefile | 2 | ||||
-rw-r--r-- | drivers/hid/hid-core.c | 16 | ||||
-rw-r--r-- | drivers/hid/hid-input-quirks.c | 96 | ||||
-rw-r--r-- | drivers/hid/hid-input.c | 38 | ||||
-rw-r--r-- | drivers/hid/hid-logitech.c | 312 | ||||
-rw-r--r-- | drivers/hid/usbhid/hid-quirks.c | 37 |
7 files changed, 343 insertions, 171 deletions
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index cacf89e65af4..066e8c08c268 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig | |||
@@ -67,4 +67,17 @@ config HIDRAW | |||
67 | 67 | ||
68 | source "drivers/hid/usbhid/Kconfig" | 68 | source "drivers/hid/usbhid/Kconfig" |
69 | 69 | ||
70 | menu "Special HID drivers" | ||
71 | depends on HID | ||
72 | |||
73 | config HID_LOGITECH | ||
74 | tristate "Logitech" | ||
75 | default m | ||
76 | depends on USB_HID | ||
77 | ---help--- | ||
78 | Support for some Logitech devices which breaks less or more | ||
79 | HID specification. | ||
80 | |||
81 | endmenu | ||
82 | |||
70 | endif # HID_SUPPORT | 83 | endif # HID_SUPPORT |
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index 275dc522c738..cae036bfe837 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile | |||
@@ -8,6 +8,8 @@ obj-$(CONFIG_HID) += hid.o | |||
8 | hid-$(CONFIG_HID_DEBUG) += hid-debug.o | 8 | hid-$(CONFIG_HID_DEBUG) += hid-debug.o |
9 | hid-$(CONFIG_HIDRAW) += hidraw.o | 9 | hid-$(CONFIG_HIDRAW) += hidraw.o |
10 | 10 | ||
11 | obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o | ||
12 | |||
11 | obj-$(CONFIG_USB_HID) += usbhid/ | 13 | obj-$(CONFIG_USB_HID) += usbhid/ |
12 | obj-$(CONFIG_USB_MOUSE) += usbhid/ | 14 | obj-$(CONFIG_USB_MOUSE) += usbhid/ |
13 | obj-$(CONFIG_USB_KBD) += usbhid/ | 15 | obj-$(CONFIG_USB_KBD) += usbhid/ |
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 3dacbcd7e41c..c3ff7b13a4be 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
@@ -33,6 +33,8 @@ | |||
33 | #include <linux/hid-debug.h> | 33 | #include <linux/hid-debug.h> |
34 | #include <linux/hidraw.h> | 34 | #include <linux/hidraw.h> |
35 | 35 | ||
36 | #include "hid-ids.h" | ||
37 | |||
36 | /* | 38 | /* |
37 | * Version Information | 39 | * Version Information |
38 | */ | 40 | */ |
@@ -1128,6 +1130,20 @@ static const struct hid_device_id *hid_match_id(struct hid_device *hdev, | |||
1128 | } | 1130 | } |
1129 | 1131 | ||
1130 | static const struct hid_device_id hid_blacklist[] = { | 1132 | static const struct hid_device_id hid_blacklist[] = { |
1133 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) }, | ||
1134 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) }, | ||
1135 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2) }, | ||
1136 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RECEIVER) }, | ||
1137 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP) }, | ||
1138 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE) }, | ||
1139 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI) }, | ||
1140 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KBD) }, | ||
1141 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD) }, | ||
1142 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500) }, | ||
1143 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_LX3) }, | ||
1144 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_V150) }, | ||
1145 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D) }, | ||
1146 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL) }, | ||
1131 | { } | 1147 | { } |
1132 | }; | 1148 | }; |
1133 | 1149 | ||
diff --git a/drivers/hid/hid-input-quirks.c b/drivers/hid/hid-input-quirks.c index 8ec64b74d38d..10451ca3a786 100644 --- a/drivers/hid/hid-input-quirks.c +++ b/drivers/hid/hid-input-quirks.c | |||
@@ -54,39 +54,6 @@ static int quirk_cherry_cymotion(struct hid_usage *usage, | |||
54 | return 1; | 54 | return 1; |
55 | } | 55 | } |
56 | 56 | ||
57 | static int quirk_logitech_ultrax_remote(struct hid_usage *usage, | ||
58 | struct hid_input *hidinput, unsigned long **bit, int *max) | ||
59 | { | ||
60 | if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR) | ||
61 | return 0; | ||
62 | |||
63 | set_bit(EV_REP, hidinput->input->evbit); | ||
64 | switch(usage->hid & HID_USAGE) { | ||
65 | /* Reported on Logitech Ultra X Media Remote */ | ||
66 | case 0x004: map_key_clear(KEY_AGAIN); break; | ||
67 | case 0x00d: map_key_clear(KEY_HOME); break; | ||
68 | case 0x024: map_key_clear(KEY_SHUFFLE); break; | ||
69 | case 0x025: map_key_clear(KEY_TV); break; | ||
70 | case 0x026: map_key_clear(KEY_MENU); break; | ||
71 | case 0x031: map_key_clear(KEY_AUDIO); break; | ||
72 | case 0x032: map_key_clear(KEY_TEXT); break; | ||
73 | case 0x033: map_key_clear(KEY_LAST); break; | ||
74 | case 0x047: map_key_clear(KEY_MP3); break; | ||
75 | case 0x048: map_key_clear(KEY_DVD); break; | ||
76 | case 0x049: map_key_clear(KEY_MEDIA); break; | ||
77 | case 0x04a: map_key_clear(KEY_VIDEO); break; | ||
78 | case 0x04b: map_key_clear(KEY_ANGLE); break; | ||
79 | case 0x04c: map_key_clear(KEY_LANGUAGE); break; | ||
80 | case 0x04d: map_key_clear(KEY_SUBTITLE); break; | ||
81 | case 0x051: map_key_clear(KEY_RED); break; | ||
82 | case 0x052: map_key_clear(KEY_CLOSE); break; | ||
83 | |||
84 | default: | ||
85 | return 0; | ||
86 | } | ||
87 | return 1; | ||
88 | } | ||
89 | |||
90 | static int quirk_gyration_remote(struct hid_usage *usage, | 57 | static int quirk_gyration_remote(struct hid_usage *usage, |
91 | struct hid_input *hidinput, unsigned long **bit, int *max) | 58 | struct hid_input *hidinput, unsigned long **bit, int *max) |
92 | { | 59 | { |
@@ -207,58 +174,6 @@ static int quirk_petalynx_remote(struct hid_usage *usage, | |||
207 | return 1; | 174 | return 1; |
208 | } | 175 | } |
209 | 176 | ||
210 | static int quirk_logitech_wireless(struct hid_usage *usage, | ||
211 | struct hid_input *hidinput, unsigned long **bit, int *max) | ||
212 | { | ||
213 | if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER) | ||
214 | return 0; | ||
215 | |||
216 | switch (usage->hid & HID_USAGE) { | ||
217 | case 0x1001: map_key_clear(KEY_MESSENGER); break; | ||
218 | case 0x1003: map_key_clear(KEY_SOUND); break; | ||
219 | case 0x1004: map_key_clear(KEY_VIDEO); break; | ||
220 | case 0x1005: map_key_clear(KEY_AUDIO); break; | ||
221 | case 0x100a: map_key_clear(KEY_DOCUMENTS); break; | ||
222 | case 0x1011: map_key_clear(KEY_PREVIOUSSONG); break; | ||
223 | case 0x1012: map_key_clear(KEY_NEXTSONG); break; | ||
224 | case 0x1013: map_key_clear(KEY_CAMERA); break; | ||
225 | case 0x1014: map_key_clear(KEY_MESSENGER); break; | ||
226 | case 0x1015: map_key_clear(KEY_RECORD); break; | ||
227 | case 0x1016: map_key_clear(KEY_PLAYER); break; | ||
228 | case 0x1017: map_key_clear(KEY_EJECTCD); break; | ||
229 | case 0x1018: map_key_clear(KEY_MEDIA); break; | ||
230 | case 0x1019: map_key_clear(KEY_PROG1); break; | ||
231 | case 0x101a: map_key_clear(KEY_PROG2); break; | ||
232 | case 0x101b: map_key_clear(KEY_PROG3); break; | ||
233 | case 0x101f: map_key_clear(KEY_ZOOMIN); break; | ||
234 | case 0x1020: map_key_clear(KEY_ZOOMOUT); break; | ||
235 | case 0x1021: map_key_clear(KEY_ZOOMRESET); break; | ||
236 | case 0x1023: map_key_clear(KEY_CLOSE); break; | ||
237 | case 0x1027: map_key_clear(KEY_MENU); break; | ||
238 | /* this one is marked as 'Rotate' */ | ||
239 | case 0x1028: map_key_clear(KEY_ANGLE); break; | ||
240 | case 0x1029: map_key_clear(KEY_SHUFFLE); break; | ||
241 | case 0x102a: map_key_clear(KEY_BACK); break; | ||
242 | case 0x102b: map_key_clear(KEY_CYCLEWINDOWS); break; | ||
243 | case 0x1041: map_key_clear(KEY_BATTERY); break; | ||
244 | case 0x1042: map_key_clear(KEY_WORDPROCESSOR); break; | ||
245 | case 0x1043: map_key_clear(KEY_SPREADSHEET); break; | ||
246 | case 0x1044: map_key_clear(KEY_PRESENTATION); break; | ||
247 | case 0x1045: map_key_clear(KEY_UNDO); break; | ||
248 | case 0x1046: map_key_clear(KEY_REDO); break; | ||
249 | case 0x1047: map_key_clear(KEY_PRINT); break; | ||
250 | case 0x1048: map_key_clear(KEY_SAVE); break; | ||
251 | case 0x1049: map_key_clear(KEY_PROG1); break; | ||
252 | case 0x104a: map_key_clear(KEY_PROG2); break; | ||
253 | case 0x104b: map_key_clear(KEY_PROG3); break; | ||
254 | case 0x104c: map_key_clear(KEY_PROG4); break; | ||
255 | |||
256 | default: | ||
257 | return 0; | ||
258 | } | ||
259 | return 1; | ||
260 | } | ||
261 | |||
262 | static int quirk_cherry_genius_29e(struct hid_usage *usage, | 177 | static int quirk_cherry_genius_29e(struct hid_usage *usage, |
263 | struct hid_input *hidinput, unsigned long **bit, int *max) | 178 | struct hid_input *hidinput, unsigned long **bit, int *max) |
264 | { | 179 | { |
@@ -329,12 +244,6 @@ static int quirk_sunplus_wdesktop(struct hid_usage *usage, | |||
329 | #define VENDOR_ID_GYRATION 0x0c16 | 244 | #define VENDOR_ID_GYRATION 0x0c16 |
330 | #define DEVICE_ID_GYRATION_REMOTE 0x0002 | 245 | #define DEVICE_ID_GYRATION_REMOTE 0x0002 |
331 | 246 | ||
332 | #define VENDOR_ID_LOGITECH 0x046d | ||
333 | #define DEVICE_ID_LOGITECH_RECEIVER 0xc101 | ||
334 | #define DEVICE_ID_S510_RECEIVER 0xc50c | ||
335 | #define DEVICE_ID_S510_RECEIVER_2 0xc517 | ||
336 | #define DEVICE_ID_MX3000_RECEIVER 0xc513 | ||
337 | |||
338 | #define VENDOR_ID_MICROSOFT 0x045e | 247 | #define VENDOR_ID_MICROSOFT 0x045e |
339 | #define DEVICE_ID_MS4K 0x00db | 248 | #define DEVICE_ID_MS4K 0x00db |
340 | #define DEVICE_ID_MS6K 0x00f9 | 249 | #define DEVICE_ID_MS6K 0x00f9 |
@@ -366,11 +275,6 @@ static const struct hid_input_blacklist { | |||
366 | 275 | ||
367 | { VENDOR_ID_GYRATION, DEVICE_ID_GYRATION_REMOTE, quirk_gyration_remote }, | 276 | { VENDOR_ID_GYRATION, DEVICE_ID_GYRATION_REMOTE, quirk_gyration_remote }, |
368 | 277 | ||
369 | { VENDOR_ID_LOGITECH, DEVICE_ID_LOGITECH_RECEIVER, quirk_logitech_ultrax_remote }, | ||
370 | { VENDOR_ID_LOGITECH, DEVICE_ID_S510_RECEIVER, quirk_logitech_wireless }, | ||
371 | { VENDOR_ID_LOGITECH, DEVICE_ID_S510_RECEIVER_2, quirk_logitech_wireless }, | ||
372 | { VENDOR_ID_LOGITECH, DEVICE_ID_MX3000_RECEIVER, quirk_logitech_wireless }, | ||
373 | |||
374 | { VENDOR_ID_MICROSOFT, DEVICE_ID_MS4K, quirk_microsoft_ergonomy_kb }, | 278 | { VENDOR_ID_MICROSOFT, DEVICE_ID_MS4K, quirk_microsoft_ergonomy_kb }, |
375 | { VENDOR_ID_MICROSOFT, DEVICE_ID_MS6K, quirk_microsoft_ergonomy_kb }, | 279 | { VENDOR_ID_MICROSOFT, DEVICE_ID_MS6K, quirk_microsoft_ergonomy_kb }, |
376 | { VENDOR_ID_MICROSOFT, DEVICE_IS_MS_PRESENTER_8K_BT, quirk_microsoft_presenter_8k }, | 280 | { VENDOR_ID_MICROSOFT, DEVICE_IS_MS_PRESENTER_8K_BT, quirk_microsoft_presenter_8k }, |
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index be2c7a8ad254..4f2bac010f59 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c | |||
@@ -58,19 +58,6 @@ static const unsigned char hid_keyboard[256] = { | |||
58 | 150,158,159,128,136,177,178,176,142,152,173,140,unk,unk,unk,unk | 58 | 150,158,159,128,136,177,178,176,142,152,173,140,unk,unk,unk,unk |
59 | }; | 59 | }; |
60 | 60 | ||
61 | /* extended mapping for certain Logitech hardware (Logitech cordless desktop LX500) */ | ||
62 | #define LOGITECH_EXPANDED_KEYMAP_SIZE 80 | ||
63 | static int logitech_expanded_keymap[LOGITECH_EXPANDED_KEYMAP_SIZE] = { | ||
64 | 0,216, 0,213,175,156, 0, 0, 0, 0, | ||
65 | 144, 0, 0, 0, 0, 0, 0, 0, 0,212, | ||
66 | 174,167,152,161,112, 0, 0, 0,154, 0, | ||
67 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
68 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
69 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
70 | 0, 0, 0, 0, 0,183,184,185,186,187, | ||
71 | 188,189,190,191,192,193,194, 0, 0, 0 | ||
72 | }; | ||
73 | |||
74 | static const struct { | 61 | static const struct { |
75 | __s32 x; | 62 | __s32 x; |
76 | __s32 y; | 63 | __s32 y; |
@@ -437,21 +424,6 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
437 | } | 424 | } |
438 | } | 425 | } |
439 | 426 | ||
440 | /* Special handling for Logitech Cordless Desktop */ | ||
441 | if (field->application != HID_GD_MOUSE) { | ||
442 | if (device->quirks & HID_QUIRK_LOGITECH_EXPANDED_KEYMAP) { | ||
443 | int hid = usage->hid & HID_USAGE; | ||
444 | if (hid < LOGITECH_EXPANDED_KEYMAP_SIZE && logitech_expanded_keymap[hid] != 0) | ||
445 | code = logitech_expanded_keymap[hid]; | ||
446 | } | ||
447 | } else { | ||
448 | if (device->quirks & HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL) { | ||
449 | int hid = usage->hid & HID_USAGE; | ||
450 | if (hid == 7 || hid == 8) | ||
451 | goto ignore; | ||
452 | } | ||
453 | } | ||
454 | |||
455 | map_key(code); | 427 | map_key(code); |
456 | break; | 428 | break; |
457 | 429 | ||
@@ -788,18 +760,8 @@ mapped: | |||
788 | || ((device->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_7) && (usage->hid == 0x00090007))) | 760 | || ((device->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_7) && (usage->hid == 0x00090007))) |
789 | goto ignore; | 761 | goto ignore; |
790 | 762 | ||
791 | if ((device->quirks & HID_QUIRK_BAD_RELATIVE_KEYS) && | ||
792 | usage->type == EV_KEY && (field->flags & HID_MAIN_ITEM_RELATIVE)) | ||
793 | field->flags &= ~HID_MAIN_ITEM_RELATIVE; | ||
794 | |||
795 | set_bit(usage->type, input->evbit); | 763 | set_bit(usage->type, input->evbit); |
796 | 764 | ||
797 | if (device->quirks & HID_QUIRK_DUPLICATE_USAGES && | ||
798 | (usage->type == EV_KEY || | ||
799 | usage->type == EV_REL || | ||
800 | usage->type == EV_ABS)) | ||
801 | clear_bit(usage->code, bit); | ||
802 | |||
803 | while (usage->code <= max && test_and_set_bit(usage->code, bit)) | 765 | while (usage->code <= max && test_and_set_bit(usage->code, bit)) |
804 | usage->code = find_next_zero_bit(bit, max + 1, usage->code); | 766 | usage->code = find_next_zero_bit(bit, max + 1, usage->code); |
805 | 767 | ||
diff --git a/drivers/hid/hid-logitech.c b/drivers/hid/hid-logitech.c new file mode 100644 index 000000000000..395e42ffb4d5 --- /dev/null +++ b/drivers/hid/hid-logitech.c | |||
@@ -0,0 +1,312 @@ | |||
1 | /* | ||
2 | * HID driver for some logitech "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 | #define LG_RDESC 0x001 | ||
26 | #define LG_BAD_RELATIVE_KEYS 0x002 | ||
27 | #define LG_DUPLICATE_USAGES 0x004 | ||
28 | #define LG_RESET_LEDS 0x008 | ||
29 | #define LG_EXPANDED_KEYMAP 0x010 | ||
30 | #define LG_IGNORE_DOUBLED_WHEEL 0x020 | ||
31 | #define LG_WIRELESS 0x040 | ||
32 | #define LG_INVERT_HWHEEL 0x080 | ||
33 | #define LG_NOGET 0x100 | ||
34 | |||
35 | /* | ||
36 | * Certain Logitech keyboards send in report #3 keys which are far | ||
37 | * above the logical maximum described in descriptor. This extends | ||
38 | * the original value of 0x28c of logical maximum to 0x104d | ||
39 | */ | ||
40 | static void lg_report_fixup(struct hid_device *hdev, __u8 *rdesc, | ||
41 | unsigned int rsize) | ||
42 | { | ||
43 | unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); | ||
44 | |||
45 | if ((quirks & LG_RDESC) && rsize >= 90 && rdesc[83] == 0x26 && | ||
46 | rdesc[84] == 0x8c && rdesc[85] == 0x02) { | ||
47 | dev_info(&hdev->dev, "fixing up Logitech keyboard report " | ||
48 | "descriptor\n"); | ||
49 | rdesc[84] = rdesc[89] = 0x4d; | ||
50 | rdesc[85] = rdesc[90] = 0x10; | ||
51 | } | ||
52 | } | ||
53 | |||
54 | #define lg_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ | ||
55 | EV_KEY, (c)) | ||
56 | |||
57 | static int lg_ultrax_remote_mapping(struct hid_input *hi, | ||
58 | struct hid_usage *usage, unsigned long **bit, int *max) | ||
59 | { | ||
60 | if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR) | ||
61 | return 0; | ||
62 | |||
63 | set_bit(EV_REP, hi->input->evbit); | ||
64 | switch (usage->hid & HID_USAGE) { | ||
65 | /* Reported on Logitech Ultra X Media Remote */ | ||
66 | case 0x004: lg_map_key_clear(KEY_AGAIN); break; | ||
67 | case 0x00d: lg_map_key_clear(KEY_HOME); break; | ||
68 | case 0x024: lg_map_key_clear(KEY_SHUFFLE); break; | ||
69 | case 0x025: lg_map_key_clear(KEY_TV); break; | ||
70 | case 0x026: lg_map_key_clear(KEY_MENU); break; | ||
71 | case 0x031: lg_map_key_clear(KEY_AUDIO); break; | ||
72 | case 0x032: lg_map_key_clear(KEY_TEXT); break; | ||
73 | case 0x033: lg_map_key_clear(KEY_LAST); break; | ||
74 | case 0x047: lg_map_key_clear(KEY_MP3); break; | ||
75 | case 0x048: lg_map_key_clear(KEY_DVD); break; | ||
76 | case 0x049: lg_map_key_clear(KEY_MEDIA); break; | ||
77 | case 0x04a: lg_map_key_clear(KEY_VIDEO); break; | ||
78 | case 0x04b: lg_map_key_clear(KEY_ANGLE); break; | ||
79 | case 0x04c: lg_map_key_clear(KEY_LANGUAGE); break; | ||
80 | case 0x04d: lg_map_key_clear(KEY_SUBTITLE); break; | ||
81 | case 0x051: lg_map_key_clear(KEY_RED); break; | ||
82 | case 0x052: lg_map_key_clear(KEY_CLOSE); break; | ||
83 | |||
84 | default: | ||
85 | return 0; | ||
86 | } | ||
87 | return 1; | ||
88 | } | ||
89 | |||
90 | static int lg_wireless_mapping(struct hid_input *hi, struct hid_usage *usage, | ||
91 | unsigned long **bit, int *max) | ||
92 | { | ||
93 | if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER) | ||
94 | return 0; | ||
95 | |||
96 | switch (usage->hid & HID_USAGE) { | ||
97 | case 0x1001: lg_map_key_clear(KEY_MESSENGER); break; | ||
98 | case 0x1003: lg_map_key_clear(KEY_SOUND); break; | ||
99 | case 0x1004: lg_map_key_clear(KEY_VIDEO); break; | ||
100 | case 0x1005: lg_map_key_clear(KEY_AUDIO); break; | ||
101 | case 0x100a: lg_map_key_clear(KEY_DOCUMENTS); break; | ||
102 | case 0x1011: lg_map_key_clear(KEY_PREVIOUSSONG); break; | ||
103 | case 0x1012: lg_map_key_clear(KEY_NEXTSONG); break; | ||
104 | case 0x1013: lg_map_key_clear(KEY_CAMERA); break; | ||
105 | case 0x1014: lg_map_key_clear(KEY_MESSENGER); break; | ||
106 | case 0x1015: lg_map_key_clear(KEY_RECORD); break; | ||
107 | case 0x1016: lg_map_key_clear(KEY_PLAYER); break; | ||
108 | case 0x1017: lg_map_key_clear(KEY_EJECTCD); break; | ||
109 | case 0x1018: lg_map_key_clear(KEY_MEDIA); break; | ||
110 | case 0x1019: lg_map_key_clear(KEY_PROG1); break; | ||
111 | case 0x101a: lg_map_key_clear(KEY_PROG2); break; | ||
112 | case 0x101b: lg_map_key_clear(KEY_PROG3); break; | ||
113 | case 0x101f: lg_map_key_clear(KEY_ZOOMIN); break; | ||
114 | case 0x1020: lg_map_key_clear(KEY_ZOOMOUT); break; | ||
115 | case 0x1021: lg_map_key_clear(KEY_ZOOMRESET); break; | ||
116 | case 0x1023: lg_map_key_clear(KEY_CLOSE); break; | ||
117 | case 0x1027: lg_map_key_clear(KEY_MENU); break; | ||
118 | /* this one is marked as 'Rotate' */ | ||
119 | case 0x1028: lg_map_key_clear(KEY_ANGLE); break; | ||
120 | case 0x1029: lg_map_key_clear(KEY_SHUFFLE); break; | ||
121 | case 0x102a: lg_map_key_clear(KEY_BACK); break; | ||
122 | case 0x102b: lg_map_key_clear(KEY_CYCLEWINDOWS); break; | ||
123 | case 0x1041: lg_map_key_clear(KEY_BATTERY); break; | ||
124 | case 0x1042: lg_map_key_clear(KEY_WORDPROCESSOR); break; | ||
125 | case 0x1043: lg_map_key_clear(KEY_SPREADSHEET); break; | ||
126 | case 0x1044: lg_map_key_clear(KEY_PRESENTATION); break; | ||
127 | case 0x1045: lg_map_key_clear(KEY_UNDO); break; | ||
128 | case 0x1046: lg_map_key_clear(KEY_REDO); break; | ||
129 | case 0x1047: lg_map_key_clear(KEY_PRINT); break; | ||
130 | case 0x1048: lg_map_key_clear(KEY_SAVE); break; | ||
131 | case 0x1049: lg_map_key_clear(KEY_PROG1); break; | ||
132 | case 0x104a: lg_map_key_clear(KEY_PROG2); break; | ||
133 | case 0x104b: lg_map_key_clear(KEY_PROG3); break; | ||
134 | case 0x104c: lg_map_key_clear(KEY_PROG4); break; | ||
135 | |||
136 | default: | ||
137 | return 0; | ||
138 | } | ||
139 | return 1; | ||
140 | } | ||
141 | |||
142 | static int lg_input_mapping(struct hid_device *hdev, struct hid_input *hi, | ||
143 | struct hid_field *field, struct hid_usage *usage, | ||
144 | unsigned long **bit, int *max) | ||
145 | { | ||
146 | /* extended mapping for certain Logitech hardware (Logitech cordless | ||
147 | desktop LX500) */ | ||
148 | static const u8 e_keymap[] = { | ||
149 | 0,216, 0,213,175,156, 0, 0, 0, 0, | ||
150 | 144, 0, 0, 0, 0, 0, 0, 0, 0,212, | ||
151 | 174,167,152,161,112, 0, 0, 0,154, 0, | ||
152 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
153 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
154 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
155 | 0, 0, 0, 0, 0,183,184,185,186,187, | ||
156 | 188,189,190,191,192,193,194, 0, 0, 0 | ||
157 | }; | ||
158 | unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); | ||
159 | unsigned int hid = usage->hid; | ||
160 | |||
161 | if (hdev->product == USB_DEVICE_ID_LOGITECH_RECEIVER && | ||
162 | lg_ultrax_remote_mapping(hi, usage, bit, max)) | ||
163 | return 1; | ||
164 | |||
165 | if ((quirks & LG_WIRELESS) && lg_wireless_mapping(hi, usage, bit, max)) | ||
166 | return 1; | ||
167 | |||
168 | if ((hid & HID_USAGE_PAGE) != HID_UP_BUTTON) | ||
169 | return 0; | ||
170 | |||
171 | hid &= HID_USAGE; | ||
172 | |||
173 | /* Special handling for Logitech Cordless Desktop */ | ||
174 | if (field->application == HID_GD_MOUSE) { | ||
175 | if ((quirks & LG_IGNORE_DOUBLED_WHEEL) && | ||
176 | (hid == 7 || hid == 8)) | ||
177 | return -1; | ||
178 | } else { | ||
179 | if ((quirks & LG_EXPANDED_KEYMAP) && | ||
180 | hid < ARRAY_SIZE(e_keymap) && | ||
181 | e_keymap[hid] != 0) { | ||
182 | hid_map_usage(hi, usage, bit, max, EV_KEY, | ||
183 | e_keymap[hid]); | ||
184 | return 1; | ||
185 | } | ||
186 | } | ||
187 | |||
188 | return 0; | ||
189 | } | ||
190 | |||
191 | static int lg_input_mapped(struct hid_device *hdev, struct hid_input *hi, | ||
192 | struct hid_field *field, struct hid_usage *usage, | ||
193 | unsigned long **bit, int *max) | ||
194 | { | ||
195 | unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); | ||
196 | |||
197 | if ((quirks & LG_BAD_RELATIVE_KEYS) && usage->type == EV_KEY && | ||
198 | (field->flags & HID_MAIN_ITEM_RELATIVE)) | ||
199 | field->flags &= ~HID_MAIN_ITEM_RELATIVE; | ||
200 | |||
201 | if ((quirks & LG_DUPLICATE_USAGES) && (usage->type == EV_KEY || | ||
202 | usage->type == EV_REL || usage->type == EV_ABS)) | ||
203 | clear_bit(usage->code, *bit); | ||
204 | |||
205 | return 0; | ||
206 | } | ||
207 | |||
208 | static int lg_event(struct hid_device *hdev, struct hid_field *field, | ||
209 | struct hid_usage *usage, __s32 value) | ||
210 | { | ||
211 | unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); | ||
212 | |||
213 | if ((quirks & LG_INVERT_HWHEEL) && usage->code == REL_HWHEEL) { | ||
214 | input_event(field->hidinput->input, usage->type, usage->code, | ||
215 | -value); | ||
216 | return 1; | ||
217 | } | ||
218 | |||
219 | return 0; | ||
220 | } | ||
221 | |||
222 | static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id) | ||
223 | { | ||
224 | unsigned long quirks = id->driver_data; | ||
225 | int ret; | ||
226 | |||
227 | hid_set_drvdata(hdev, (void *)quirks); | ||
228 | |||
229 | if (quirks & LG_RESET_LEDS) | ||
230 | hdev->quirks |= HID_QUIRK_RESET_LEDS; | ||
231 | if (quirks & LG_NOGET) | ||
232 | hdev->quirks |= HID_QUIRK_NOGET; | ||
233 | |||
234 | ret = hid_parse(hdev); | ||
235 | if (ret) { | ||
236 | dev_err(&hdev->dev, "parse failed\n"); | ||
237 | goto err_free; | ||
238 | } | ||
239 | |||
240 | ret = hid_hw_start(hdev); | ||
241 | if (ret) { | ||
242 | dev_err(&hdev->dev, "hw start failed\n"); | ||
243 | goto err_free; | ||
244 | } | ||
245 | |||
246 | return 0; | ||
247 | err_free: | ||
248 | return ret; | ||
249 | } | ||
250 | |||
251 | static const struct hid_device_id lg_devices[] = { | ||
252 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER), | ||
253 | .driver_data = LG_RDESC | LG_WIRELESS }, | ||
254 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER), | ||
255 | .driver_data = LG_RDESC | LG_WIRELESS }, | ||
256 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2), | ||
257 | .driver_data = LG_RDESC | LG_WIRELESS }, | ||
258 | |||
259 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RECEIVER), | ||
260 | .driver_data = LG_BAD_RELATIVE_KEYS }, | ||
261 | |||
262 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP), | ||
263 | .driver_data = LG_DUPLICATE_USAGES }, | ||
264 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE), | ||
265 | .driver_data = LG_DUPLICATE_USAGES }, | ||
266 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI), | ||
267 | .driver_data = LG_DUPLICATE_USAGES }, | ||
268 | |||
269 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KBD), | ||
270 | .driver_data = LG_RESET_LEDS }, | ||
271 | |||
272 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD), | ||
273 | .driver_data = LG_IGNORE_DOUBLED_WHEEL | LG_EXPANDED_KEYMAP }, | ||
274 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500), | ||
275 | .driver_data = LG_IGNORE_DOUBLED_WHEEL | LG_EXPANDED_KEYMAP }, | ||
276 | |||
277 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_LX3), | ||
278 | .driver_data = LG_INVERT_HWHEEL }, | ||
279 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_V150), | ||
280 | .driver_data = LG_INVERT_HWHEEL }, | ||
281 | |||
282 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D), | ||
283 | .driver_data = LG_NOGET }, | ||
284 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL), | ||
285 | .driver_data = LG_NOGET }, | ||
286 | { } | ||
287 | }; | ||
288 | MODULE_DEVICE_TABLE(hid, lg_devices); | ||
289 | |||
290 | static struct hid_driver lg_driver = { | ||
291 | .name = "logitech", | ||
292 | .id_table = lg_devices, | ||
293 | .report_fixup = lg_report_fixup, | ||
294 | .input_mapping = lg_input_mapping, | ||
295 | .input_mapped = lg_input_mapped, | ||
296 | .event = lg_event, | ||
297 | .probe = lg_probe, | ||
298 | }; | ||
299 | |||
300 | static int lg_init(void) | ||
301 | { | ||
302 | return hid_register_driver(&lg_driver); | ||
303 | } | ||
304 | |||
305 | static void lg_exit(void) | ||
306 | { | ||
307 | hid_unregister_driver(&lg_driver); | ||
308 | } | ||
309 | |||
310 | module_init(lg_init); | ||
311 | module_exit(lg_exit); | ||
312 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 8b5ce9c9e353..48fdaa5db739 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c | |||
@@ -33,8 +33,6 @@ static const struct hid_blacklist { | |||
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 }, | 34 | { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE, HID_QUIRK_2WHEEL_MOUSE_HACK_5 }, |
35 | 35 | ||
36 | { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RECEIVER, HID_QUIRK_BAD_RELATIVE_KEYS }, | ||
37 | |||
38 | { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_GAMEPAD, HID_QUIRK_BADPAD }, | 36 | { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_GAMEPAD, HID_QUIRK_BADPAD }, |
39 | { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_PREDATOR, HID_QUIRK_BADPAD }, | 37 | { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_PREDATOR, HID_QUIRK_BADPAD }, |
40 | { USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD }, | 38 | { USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD }, |
@@ -48,10 +46,6 @@ static const struct hid_blacklist { | |||
48 | { USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD }, | 46 | { USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD }, |
49 | { USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD }, | 47 | { USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD }, |
50 | 48 | ||
51 | { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP, HID_QUIRK_DUPLICATE_USAGES }, | ||
52 | { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE, HID_QUIRK_DUPLICATE_USAGES }, | ||
53 | { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI, HID_QUIRK_DUPLICATE_USAGES }, | ||
54 | |||
55 | { USB_VENDOR_ID_AFATECH, USB_DEVICE_ID_AFATECH_AF9016, HID_QUIRK_FULLSPEED_INTERVAL }, | 49 | { USB_VENDOR_ID_AFATECH, USB_DEVICE_ID_AFATECH_AF9016, HID_QUIRK_FULLSPEED_INTERVAL }, |
56 | 50 | ||
57 | { USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM, HID_QUIRK_HIDDEV }, | 51 | { USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM, HID_QUIRK_HIDDEV }, |
@@ -196,11 +190,6 @@ static const struct hid_blacklist { | |||
196 | { USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICKIT1, HID_QUIRK_IGNORE }, | 190 | { USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICKIT1, HID_QUIRK_IGNORE }, |
197 | { USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICKIT2, HID_QUIRK_IGNORE }, | 191 | { USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICKIT2, HID_QUIRK_IGNORE }, |
198 | 192 | ||
199 | { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD, HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL | HID_QUIRK_LOGITECH_EXPANDED_KEYMAP }, | ||
200 | { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500, HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL | HID_QUIRK_LOGITECH_EXPANDED_KEYMAP }, | ||
201 | { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_LX3, HID_QUIRK_INVERT_HWHEEL }, | ||
202 | { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_V150, HID_QUIRK_INVERT_HWHEEL }, | ||
203 | |||
204 | { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K, HID_QUIRK_MICROSOFT_KEYS }, | 193 | { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K, HID_QUIRK_MICROSOFT_KEYS }, |
205 | { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_LK6K, HID_QUIRK_MICROSOFT_KEYS }, | 194 | { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_LK6K, HID_QUIRK_MICROSOFT_KEYS }, |
206 | 195 | ||
@@ -218,8 +207,6 @@ static const struct hid_blacklist { | |||
218 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET }, | 207 | { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET }, |
219 | { USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET }, | 208 | { USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET }, |
220 | { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET }, | 209 | { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET }, |
221 | { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D, HID_QUIRK_NOGET }, | ||
222 | { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL, HID_QUIRK_NOGET }, | ||
223 | { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0, HID_QUIRK_NOGET }, | 210 | { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0, HID_QUIRK_NOGET }, |
224 | { USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE, HID_QUIRK_NOGET }, | 211 | { USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE, HID_QUIRK_NOGET }, |
225 | { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET }, | 212 | { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET }, |
@@ -259,7 +246,6 @@ static const struct hid_blacklist { | |||
259 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, | 246 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, |
260 | 247 | ||
261 | { USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658, HID_QUIRK_RESET_LEDS }, | 248 | { USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658, HID_QUIRK_RESET_LEDS }, |
262 | { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KBD, HID_QUIRK_RESET_LEDS }, | ||
263 | { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY, HID_QUIRK_IGNORE }, | 249 | { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY, HID_QUIRK_IGNORE }, |
264 | { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_2, HID_QUIRK_IGNORE }, | 250 | { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_2, HID_QUIRK_IGNORE }, |
265 | { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_3, HID_QUIRK_IGNORE }, | 251 | { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_3, HID_QUIRK_IGNORE }, |
@@ -339,9 +325,6 @@ static const struct hid_rdesc_blacklist { | |||
339 | 325 | ||
340 | { USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_RDESC_CYMOTION }, | 326 | { USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_RDESC_CYMOTION }, |
341 | 327 | ||
342 | { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER, HID_QUIRK_RDESC_LOGITECH }, | ||
343 | { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER, HID_QUIRK_RDESC_LOGITECH }, | ||
344 | { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2, HID_QUIRK_RDESC_LOGITECH }, | ||
345 | { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_DESKTOP_RECV_1028, HID_QUIRK_RDESC_MICROSOFT_RECV_1028 }, | 328 | { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_DESKTOP_RECV_1028, HID_QUIRK_RDESC_MICROSOFT_RECV_1028 }, |
346 | 329 | ||
347 | { USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E, HID_QUIRK_RDESC_BUTTON_CONSUMER }, | 330 | { USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E, HID_QUIRK_RDESC_BUTTON_CONSUMER }, |
@@ -611,23 +594,6 @@ static void usbhid_fixup_cymotion_descriptor(char *rdesc, int rsize) | |||
611 | } | 594 | } |
612 | } | 595 | } |
613 | 596 | ||
614 | |||
615 | /* | ||
616 | * Certain Logitech keyboards send in report #3 keys which are far | ||
617 | * above the logical maximum described in descriptor. This extends | ||
618 | * the original value of 0x28c of logical maximum to 0x104d | ||
619 | */ | ||
620 | static void usbhid_fixup_logitech_descriptor(unsigned char *rdesc, int rsize) | ||
621 | { | ||
622 | if (rsize >= 90 && rdesc[83] == 0x26 | ||
623 | && rdesc[84] == 0x8c | ||
624 | && rdesc[85] == 0x02) { | ||
625 | printk(KERN_INFO "Fixing up Logitech keyboard report descriptor\n"); | ||
626 | rdesc[84] = rdesc[89] = 0x4d; | ||
627 | rdesc[85] = rdesc[90] = 0x10; | ||
628 | } | ||
629 | } | ||
630 | |||
631 | static void usbhid_fixup_sunplus_wdesktop(unsigned char *rdesc, int rsize) | 597 | static void usbhid_fixup_sunplus_wdesktop(unsigned char *rdesc, int rsize) |
632 | { | 598 | { |
633 | if (rsize >= 107 && rdesc[104] == 0x26 | 599 | if (rsize >= 107 && rdesc[104] == 0x26 |
@@ -753,9 +719,6 @@ static void __usbhid_fixup_report_descriptor(__u32 quirks, char *rdesc, unsigned | |||
753 | if ((quirks & HID_QUIRK_RDESC_CYMOTION)) | 719 | if ((quirks & HID_QUIRK_RDESC_CYMOTION)) |
754 | usbhid_fixup_cymotion_descriptor(rdesc, rsize); | 720 | usbhid_fixup_cymotion_descriptor(rdesc, rsize); |
755 | 721 | ||
756 | if (quirks & HID_QUIRK_RDESC_LOGITECH) | ||
757 | usbhid_fixup_logitech_descriptor(rdesc, rsize); | ||
758 | |||
759 | if (quirks & HID_QUIRK_RDESC_SWAPPED_MIN_MAX) | 722 | if (quirks & HID_QUIRK_RDESC_SWAPPED_MIN_MAX) |
760 | usbhid_fixup_cypress_descriptor(rdesc, rsize); | 723 | usbhid_fixup_cypress_descriptor(rdesc, rsize); |
761 | 724 | ||