aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiri Kosina <jkosina@suse.cz>2007-07-09 08:23:37 -0400
committerJiri Kosina <jkosina@suse.cz>2007-07-09 08:23:37 -0400
commitfeb485d4010e450183bd422d90c0d0f6be98f932 (patch)
tree6c6b14d67b81fe98d6bee658c0caaffefae6b789
parent58037eb961f859607b161c50d9d4ecb374de1e8f (diff)
parent2c1d8aea2ca76df1b1de2aed23e3ceda2a044ed1 (diff)
Merge branches 'debug-module-param' and 'upstream' into for-linus
-rw-r--r--drivers/hid/Kconfig9
-rw-r--r--drivers/hid/hid-input.c99
-rw-r--r--drivers/hid/usbhid/hid-core.c73
-rw-r--r--drivers/hid/usbhid/hid-pidff.c1
-rw-r--r--drivers/hid/usbhid/hid-quirks.c177
-rw-r--r--include/linux/hid.h36
6 files changed, 303 insertions, 92 deletions
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 5b004b2b1a4e..3b63b0b78122 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -1,8 +1,12 @@
1# 1#
2# HID driver configuration 2# HID driver configuration
3# 3#
4menu "HID Devices" 4menuconfig HID_SUPPORT
5 bool "HID Devices"
5 depends on INPUT 6 depends on INPUT
7 default y
8
9if HID_SUPPORT
6 10
7config HID 11config HID
8 tristate "Generic HID support" 12 tristate "Generic HID support"
@@ -39,5 +43,4 @@ config HID_DEBUG
39 43
40source "drivers/hid/usbhid/Kconfig" 44source "drivers/hid/usbhid/Kconfig"
41 45
42endmenu 46endif # HID_SUPPORT
43
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 38595d3935ce..8edbd30cf795 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -60,6 +60,19 @@ static const unsigned char hid_keyboard[256] = {
60 150,158,159,128,136,177,178,176,142,152,173,140,unk,unk,unk,unk 60 150,158,159,128,136,177,178,176,142,152,173,140,unk,unk,unk,unk
61}; 61};
62 62
63/* extended mapping for certain Logitech hardware (Logitech cordless desktop LX500) */
64#define LOGITECH_EXPANDED_KEYMAP_SIZE 80
65static int logitech_expanded_keymap[LOGITECH_EXPANDED_KEYMAP_SIZE] = {
66 0,216, 0,213,175,156, 0, 0, 0, 0,
67 144, 0, 0, 0, 0, 0, 0, 0, 0,212,
68 174,167,152,161,112, 0, 0, 0,154, 0,
69 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
70 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
71 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
72 0, 0, 0, 0, 0,183,184,185,186,187,
73 188,189,190,191,192,193,194, 0, 0, 0
74};
75
63static const struct { 76static const struct {
64 __s32 x; 77 __s32 x;
65 __s32 y; 78 __s32 y;
@@ -374,6 +387,21 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
374 } 387 }
375 } 388 }
376 389
390 /* Special handling for Logitech Cordless Desktop */
391 if (field->application != HID_GD_MOUSE) {
392 if (device->quirks & HID_QUIRK_LOGITECH_EXPANDED_KEYMAP) {
393 int hid = usage->hid & HID_USAGE;
394 if (hid < LOGITECH_EXPANDED_KEYMAP_SIZE && logitech_expanded_keymap[hid] != 0)
395 code = logitech_expanded_keymap[hid];
396 }
397 } else {
398 if (device->quirks & HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL) {
399 int hid = usage->hid & HID_USAGE;
400 if (hid == 7 || hid == 8)
401 goto ignore;
402 }
403 }
404
377 map_key(code); 405 map_key(code);
378 break; 406 break;
379 407
@@ -562,6 +590,11 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
562 case 0x0e5: map_key_clear(KEY_BASSBOOST); break; 590 case 0x0e5: map_key_clear(KEY_BASSBOOST); break;
563 case 0x0e9: map_key_clear(KEY_VOLUMEUP); break; 591 case 0x0e9: map_key_clear(KEY_VOLUMEUP); break;
564 case 0x0ea: map_key_clear(KEY_VOLUMEDOWN); break; 592 case 0x0ea: map_key_clear(KEY_VOLUMEDOWN); break;
593
594 /* reserved in HUT 1.12. Reported on Petalynx remote */
595 case 0x0f6: map_key_clear(KEY_NEXT); break;
596 case 0x0fa: map_key_clear(KEY_BACK); break;
597
565 case 0x183: map_key_clear(KEY_CONFIG); break; 598 case 0x183: map_key_clear(KEY_CONFIG); break;
566 case 0x184: map_key_clear(KEY_WORDPROCESSOR); break; 599 case 0x184: map_key_clear(KEY_WORDPROCESSOR); break;
567 case 0x185: map_key_clear(KEY_EDITOR); break; 600 case 0x185: map_key_clear(KEY_EDITOR); break;
@@ -594,7 +627,9 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
594 case 0x21b: map_key_clear(KEY_COPY); break; 627 case 0x21b: map_key_clear(KEY_COPY); break;
595 case 0x21c: map_key_clear(KEY_CUT); break; 628 case 0x21c: map_key_clear(KEY_CUT); break;
596 case 0x21d: map_key_clear(KEY_PASTE); break; 629 case 0x21d: map_key_clear(KEY_PASTE); break;
597 case 0x221: map_key_clear(KEY_FIND); break; 630 case 0x21f: map_key_clear(KEY_FIND); break;
631 case 0x221: map_key_clear(KEY_SEARCH); break;
632 case 0x222: map_key_clear(KEY_GOTO); break;
598 case 0x223: map_key_clear(KEY_HOMEPAGE); break; 633 case 0x223: map_key_clear(KEY_HOMEPAGE); break;
599 case 0x224: map_key_clear(KEY_BACK); break; 634 case 0x224: map_key_clear(KEY_BACK); break;
600 case 0x225: map_key_clear(KEY_FORWARD); break; 635 case 0x225: map_key_clear(KEY_FORWARD); break;
@@ -684,7 +719,28 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
684 break; 719 break;
685 720
686 case HID_UP_MSVENDOR: 721 case HID_UP_MSVENDOR:
687 goto ignore; 722
723 /* special case - Chicony Chicony KU-0418 tactical pad */
724 if (device->vendor == 0x04f2 && device->product == 0x0418) {
725 set_bit(EV_REP, input->evbit);
726 switch(usage->hid & HID_USAGE) {
727 case 0xff01: map_key_clear(BTN_1); break;
728 case 0xff02: map_key_clear(BTN_2); break;
729 case 0xff03: map_key_clear(BTN_3); break;
730 case 0xff04: map_key_clear(BTN_4); break;
731 case 0xff05: map_key_clear(BTN_5); break;
732 case 0xff06: map_key_clear(BTN_6); break;
733 case 0xff07: map_key_clear(BTN_7); break;
734 case 0xff08: map_key_clear(BTN_8); break;
735 case 0xff09: map_key_clear(BTN_9); break;
736 case 0xff0a: map_key_clear(BTN_A); break;
737 case 0xff0b: map_key_clear(BTN_B); break;
738 default: goto ignore;
739 }
740 } else {
741 goto ignore;
742 }
743 break;
688 744
689 case HID_UP_CUSTOM: /* Reported on Logitech and Powerbook USB keyboards */ 745 case HID_UP_CUSTOM: /* Reported on Logitech and Powerbook USB keyboards */
690 746
@@ -700,10 +756,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
700 } 756 }
701 break; 757 break;
702 758
703 case HID_UP_LOGIVENDOR: /* Reported on Logitech Ultra X Media Remote */ 759 case HID_UP_LOGIVENDOR:
704
705 set_bit(EV_REP, input->evbit); 760 set_bit(EV_REP, input->evbit);
706 switch(usage->hid & HID_USAGE) { 761 switch(usage->hid & HID_USAGE) {
762 /* Reported on Logitech Ultra X Media Remote */
707 case 0x004: map_key_clear(KEY_AGAIN); break; 763 case 0x004: map_key_clear(KEY_AGAIN); break;
708 case 0x00d: map_key_clear(KEY_HOME); break; 764 case 0x00d: map_key_clear(KEY_HOME); break;
709 case 0x024: map_key_clear(KEY_SHUFFLE); break; 765 case 0x024: map_key_clear(KEY_SHUFFLE); break;
@@ -721,6 +777,14 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
721 case 0x04d: map_key_clear(KEY_SUBTITLE); break; 777 case 0x04d: map_key_clear(KEY_SUBTITLE); break;
722 case 0x051: map_key_clear(KEY_RED); break; 778 case 0x051: map_key_clear(KEY_RED); break;
723 case 0x052: map_key_clear(KEY_CLOSE); break; 779 case 0x052: map_key_clear(KEY_CLOSE); break;
780
781 /* Reported on Petalynx Maxter remote */
782 case 0x05a: map_key_clear(KEY_TEXT); break;
783 case 0x05b: map_key_clear(KEY_RED); break;
784 case 0x05c: map_key_clear(KEY_GREEN); break;
785 case 0x05d: map_key_clear(KEY_YELLOW); break;
786 case 0x05e: map_key_clear(KEY_BLUE); break;
787
724 default: goto ignore; 788 default: goto ignore;
725 } 789 }
726 break; 790 break;
@@ -814,6 +878,16 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
814 field->dpad = usage->code; 878 field->dpad = usage->code;
815 } 879 }
816 880
881 /* for those devices which produce Consumer volume usage as relative,
882 * we emulate pressing volumeup/volumedown appropriate number of times
883 * in hidinput_hid_event()
884 */
885 if ((usage->type == EV_ABS) && (field->flags & HID_MAIN_ITEM_RELATIVE) &&
886 (usage->code == ABS_VOLUME)) {
887 set_bit(KEY_VOLUMEUP, input->keybit);
888 set_bit(KEY_VOLUMEDOWN, input->keybit);
889 }
890
817 hid_resolv_event(usage->type, usage->code); 891 hid_resolv_event(usage->type, usage->code);
818 892
819 dbg_hid_line("\n"); 893 dbg_hid_line("\n");
@@ -902,6 +976,21 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
902 if ((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UNKNOWN */ 976 if ((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UNKNOWN */
903 return; 977 return;
904 978
979 if ((usage->type == EV_ABS) && (field->flags & HID_MAIN_ITEM_RELATIVE) &&
980 (usage->code == ABS_VOLUME)) {
981 int count = abs(value);
982 int direction = value > 0 ? KEY_VOLUMEUP : KEY_VOLUMEDOWN;
983 int i;
984
985 for (i = 0; i < count; i++) {
986 input_event(input, EV_KEY, direction, 1);
987 input_sync(input);
988 input_event(input, EV_KEY, direction, 0);
989 input_sync(input);
990 }
991 return;
992 }
993
905 input_event(input, usage->type, usage->code, value); 994 input_event(input, usage->type, usage->code, value);
906 995
907 if ((field->flags & HID_MAIN_ITEM_RELATIVE) && (usage->type == EV_KEY)) 996 if ((field->flags & HID_MAIN_ITEM_RELATIVE) && (usage->type == EV_KEY))
@@ -970,7 +1059,7 @@ int hidinput_connect(struct hid_device *hid)
970 if (IS_INPUT_APPLICATION(hid->collection[i].usage)) 1059 if (IS_INPUT_APPLICATION(hid->collection[i].usage))
971 break; 1060 break;
972 1061
973 if (i == hid->maxcollection) 1062 if (i == hid->maxcollection && (hid->quirks & HID_QUIRK_HIDINPUT) == 0)
974 return -1; 1063 return -1;
975 1064
976 if (hid->quirks & HID_QUIRK_SKIP_OUTPUT_REPORTS) 1065 if (hid->quirks & HID_QUIRK_SKIP_OUTPUT_REPORTS)
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 1eb2c64bc44a..3afa4a5035b7 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -60,6 +60,12 @@ MODULE_PARM_DESC(quirks, "Add/modify USB HID quirks by specifying "
60 " quirks=vendorID:productID:quirks" 60 " quirks=vendorID:productID:quirks"
61 " where vendorID, productID, and quirks are all in" 61 " where vendorID, productID, and quirks are all in"
62 " 0x-prefixed hex"); 62 " 0x-prefixed hex");
63static char *rdesc_quirks_param[MAX_USBHID_BOOT_QUIRKS] = { [ 0 ... (MAX_USBHID_BOOT_QUIRKS - 1) ] = NULL };
64module_param_array_named(rdesc_quirks, rdesc_quirks_param, charp, NULL, 0444);
65MODULE_PARM_DESC(rdesc_quirks, "Add/modify report descriptor quirks by specifying "
66 " rdesc_quirks=vendorID:productID:rdesc_quirks"
67 " where vendorID, productID, and rdesc_quirks are all in"
68 " 0x-prefixed hex");
63/* 69/*
64 * Input submission and I/O error handler. 70 * Input submission and I/O error handler.
65 */ 71 */
@@ -633,20 +639,6 @@ static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid)
633} 639}
634 640
635/* 641/*
636 * Cherry Cymotion keyboard have an invalid HID report descriptor,
637 * that needs fixing before we can parse it.
638 */
639
640static void hid_fixup_cymotion_descriptor(char *rdesc, int rsize)
641{
642 if (rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) {
643 info("Fixing up Cherry Cymotion report descriptor");
644 rdesc[11] = rdesc[16] = 0xff;
645 rdesc[12] = rdesc[17] = 0x03;
646 }
647}
648
649/*
650 * Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller 642 * Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller
651 * to "operational". Without this, the ps3 controller will not report any 643 * to "operational". Without this, the ps3 controller will not report any
652 * events. 644 * events.
@@ -672,46 +664,6 @@ static void hid_fixup_sony_ps3_controller(struct usb_device *dev, int ifnum)
672 kfree(buf); 664 kfree(buf);
673} 665}
674 666
675/*
676 * Certain Logitech keyboards send in report #3 keys which are far
677 * above the logical maximum described in descriptor. This extends
678 * the original value of 0x28c of logical maximum to 0x104d
679 */
680static void hid_fixup_logitech_descriptor(unsigned char *rdesc, int rsize)
681{
682 if (rsize >= 90 && rdesc[83] == 0x26
683 && rdesc[84] == 0x8c
684 && rdesc[85] == 0x02) {
685 info("Fixing up Logitech keyboard report descriptor");
686 rdesc[84] = rdesc[89] = 0x4d;
687 rdesc[85] = rdesc[90] = 0x10;
688 }
689}
690
691/*
692 * Some USB barcode readers from cypress have usage min and usage max in
693 * the wrong order
694 */
695static void hid_fixup_cypress_descriptor(unsigned char *rdesc, int rsize)
696{
697 short fixed = 0;
698 int i;
699
700 for (i = 0; i < rsize - 4; i++) {
701 if (rdesc[i] == 0x29 && rdesc [i+2] == 0x19) {
702 unsigned char tmp;
703
704 rdesc[i] = 0x19; rdesc[i+2] = 0x29;
705 tmp = rdesc[i+3];
706 rdesc[i+3] = rdesc[i+1];
707 rdesc[i+1] = tmp;
708 }
709 }
710
711 if (fixed)
712 info("Fixing up Cypress report descriptor");
713}
714
715static struct hid_device *usb_hid_configure(struct usb_interface *intf) 667static struct hid_device *usb_hid_configure(struct usb_interface *intf)
716{ 668{
717 struct usb_host_interface *interface = intf->cur_altsetting; 669 struct usb_host_interface *interface = intf->cur_altsetting;
@@ -772,14 +724,9 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
772 return NULL; 724 return NULL;
773 } 725 }
774 726
775 if ((quirks & HID_QUIRK_CYMOTION)) 727 usbhid_fixup_report_descriptor(le16_to_cpu(dev->descriptor.idVendor),
776 hid_fixup_cymotion_descriptor(rdesc, rsize); 728 le16_to_cpu(dev->descriptor.idProduct), rdesc,
777 729 rsize, rdesc_quirks_param);
778 if (quirks & HID_QUIRK_LOGITECH_DESCRIPTOR)
779 hid_fixup_logitech_descriptor(rdesc, rsize);
780
781 if (quirks & HID_QUIRK_SWAPPED_MIN_MAX)
782 hid_fixup_cypress_descriptor(rdesc, rsize);
783 730
784 dbg_hid("report descriptor (size %u, read %d) = ", rsize, n); 731 dbg_hid("report descriptor (size %u, read %d) = ", rsize, n);
785 for (n = 0; n < rsize; n++) 732 for (n = 0; n < rsize; n++)
@@ -954,7 +901,7 @@ static void hid_disconnect(struct usb_interface *intf)
954 usb_kill_urb(usbhid->urbctrl); 901 usb_kill_urb(usbhid->urbctrl);
955 902
956 del_timer_sync(&usbhid->io_retry); 903 del_timer_sync(&usbhid->io_retry);
957 flush_scheduled_work(); 904 cancel_work_sync(&usbhid->reset_work);
958 905
959 if (hid->claimed & HID_CLAIMED_INPUT) 906 if (hid->claimed & HID_CLAIMED_INPUT)
960 hidinput_disconnect(hid); 907 hidinput_disconnect(hid);
diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
index f5a90e950e6b..011326178c06 100644
--- a/drivers/hid/usbhid/hid-pidff.c
+++ b/drivers/hid/usbhid/hid-pidff.c
@@ -738,6 +738,7 @@ static void pidff_autocenter(struct pidff_device *pidff, u16 magnitude)
738 pidff->set_effect[PID_TRIGGER_BUTTON].value[0] = 0; 738 pidff->set_effect[PID_TRIGGER_BUTTON].value[0] = 0;
739 pidff->set_effect[PID_TRIGGER_REPEAT_INT].value[0] = 0; 739 pidff->set_effect[PID_TRIGGER_REPEAT_INT].value[0] = 0;
740 pidff_set(&pidff->set_effect[PID_GAIN], magnitude); 740 pidff_set(&pidff->set_effect[PID_GAIN], magnitude);
741 pidff->set_effect[PID_DIRECTION_ENABLE].value[0] = 1;
741 pidff->set_effect[PID_START_DELAY].value[0] = 0; 742 pidff->set_effect[PID_START_DELAY].value[0] = 0;
742 743
743 usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT], 744 usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT],
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index a418ebfe39b8..775b9f3b8ce3 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -105,6 +105,9 @@
105#define USB_VENDOR_ID_ESSENTIAL_REALITY 0x0d7f 105#define USB_VENDOR_ID_ESSENTIAL_REALITY 0x0d7f
106#define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100 106#define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100
107 107
108#define USB_VENDOR_ID_GAMERON 0x0810
109#define USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR 0x0001
110
108#define USB_VENDOR_ID_GLAB 0x06c2 111#define USB_VENDOR_ID_GLAB 0x06c2
109#define USB_DEVICE_ID_4_PHIDGETSERVO_30 0x0038 112#define USB_DEVICE_ID_4_PHIDGETSERVO_30 0x0038
110#define USB_DEVICE_ID_1_PHIDGETSERVO_30 0x0039 113#define USB_DEVICE_ID_1_PHIDGETSERVO_30 0x0039
@@ -196,8 +199,10 @@
196#define USB_VENDOR_ID_LOGITECH 0x046d 199#define USB_VENDOR_ID_LOGITECH 0x046d
197#define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101 200#define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101
198#define USB_DEVICE_ID_LOGITECH_WHEEL 0xc294 201#define USB_DEVICE_ID_LOGITECH_WHEEL 0xc294
202#define USB_DEVICE_ID_LOGITECH_KBD 0xc311
199#define USB_DEVICE_ID_S510_RECEIVER 0xc50c 203#define USB_DEVICE_ID_S510_RECEIVER 0xc50c
200#define USB_DEVICE_ID_S510_RECEIVER_2 0xc517 204#define USB_DEVICE_ID_S510_RECEIVER_2 0xc517
205#define USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500 0xc512
201#define USB_DEVICE_ID_MX3000_RECEIVER 0xc513 206#define USB_DEVICE_ID_MX3000_RECEIVER 0xc513
202#define USB_DEVICE_ID_DINOVO_EDGE 0xc714 207#define USB_DEVICE_ID_DINOVO_EDGE 0xc714
203 208
@@ -209,6 +214,13 @@
209#define USB_DEVICE_ID_MGE_UPS 0xffff 214#define USB_DEVICE_ID_MGE_UPS 0xffff
210#define USB_DEVICE_ID_MGE_UPS1 0x0001 215#define USB_DEVICE_ID_MGE_UPS1 0x0001
211 216
217#define USB_VENDOR_ID_MICROSOFT 0x045e
218#define USB_DEVICE_ID_SIDEWINDER_GV 0x003b
219
220#define USB_VENDOR_ID_NCR 0x0404
221#define USB_DEVICE_ID_NCR_FIRST 0x0300
222#define USB_DEVICE_ID_NCR_LAST 0x03ff
223
212#define USB_VENDOR_ID_NEC 0x073e 224#define USB_VENDOR_ID_NEC 0x073e
213#define USB_DEVICE_ID_NEC_USB_GAME_PAD 0x0301 225#define USB_DEVICE_ID_NEC_USB_GAME_PAD 0x0301
214 226
@@ -220,6 +232,9 @@
220#define USB_VENDOR_ID_PANTHERLORD 0x0810 232#define USB_VENDOR_ID_PANTHERLORD 0x0810
221#define USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK 0x0001 233#define USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK 0x0001
222 234
235#define USB_VENDOR_ID_PETALYNX 0x18b1
236#define USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE 0x0037
237
223#define USB_VENDOR_ID_PLAYDOTCOM 0x0b43 238#define USB_VENDOR_ID_PLAYDOTCOM 0x0b43
224#define USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII 0x0003 239#define USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII 0x0003
225 240
@@ -278,6 +293,7 @@ static const struct hid_blacklist {
278 { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_PREDATOR, HID_QUIRK_BADPAD }, 293 { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_PREDATOR, HID_QUIRK_BADPAD },
279 { USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD }, 294 { USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD },
280 { USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD }, 295 { USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD },
296 { USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR, HID_QUIRK_MULTI_INPUT },
281 { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, 297 { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
282 { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, 298 { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
283 { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, 299 { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
@@ -285,11 +301,10 @@ static const struct hid_blacklist {
285 { USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD }, 301 { USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD },
286 { USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD }, 302 { USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD },
287 303
288 { USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_CYMOTION },
289
290 { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE, HID_QUIRK_DUPLICATE_USAGES }, 304 { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE, HID_QUIRK_DUPLICATE_USAGES },
291 305
292 { USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM, HID_QUIRK_HIDDEV }, 306 { USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM, HID_QUIRK_HIDDEV },
307 { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV, HID_QUIRK_HIDINPUT },
293 308
294 { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_01, HID_QUIRK_IGNORE }, 309 { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_01, HID_QUIRK_IGNORE },
295 { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_10, HID_QUIRK_IGNORE }, 310 { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_10, HID_QUIRK_IGNORE },
@@ -409,9 +424,7 @@ static const struct hid_blacklist {
409 { USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_FLAIR, HID_QUIRK_IGNORE }, 424 { USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_FLAIR, HID_QUIRK_IGNORE },
410 { USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_302, HID_QUIRK_IGNORE }, 425 { USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_302, HID_QUIRK_IGNORE },
411 426
412 { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER, HID_QUIRK_LOGITECH_DESCRIPTOR }, 427 { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500, HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL | HID_QUIRK_LOGITECH_EXPANDED_KEYMAP },
413 { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER, HID_QUIRK_LOGITECH_DESCRIPTOR },
414 { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2, HID_QUIRK_LOGITECH_DESCRIPTOR },
415 428
416 { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE, HID_QUIRK_MIGHTYMOUSE | HID_QUIRK_INVERT_HWHEEL }, 429 { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE, HID_QUIRK_MIGHTYMOUSE | HID_QUIRK_INVERT_HWHEEL },
417 430
@@ -426,6 +439,7 @@ static const struct hid_blacklist {
426 { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET }, 439 { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET },
427 { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET }, 440 { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET },
428 { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL, HID_QUIRK_NOGET }, 441 { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL, HID_QUIRK_NOGET },
442 { USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE, HID_QUIRK_NOGET },
429 { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET }, 443 { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET },
430 { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET }, 444 { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET },
431 { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, 445 { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
@@ -448,9 +462,28 @@ static const struct hid_blacklist {
448 { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, 462 { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
449 463
450 { USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658, HID_QUIRK_RESET_LEDS }, 464 { USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658, HID_QUIRK_RESET_LEDS },
465 { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KBD, HID_QUIRK_RESET_LEDS },
451 466
452 { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1, HID_QUIRK_SWAPPED_MIN_MAX }, 467 { 0, 0 }
453 { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2, HID_QUIRK_SWAPPED_MIN_MAX }, 468};
469
470/* Quirks for devices which require report descriptor fixup go here */
471static const struct hid_rdesc_blacklist {
472 __u16 idVendor;
473 __u16 idProduct;
474 __u32 quirks;
475} hid_rdesc_blacklist[] = {
476
477 { USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_RDESC_CYMOTION },
478
479 { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER, HID_QUIRK_RDESC_LOGITECH },
480 { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER, HID_QUIRK_RDESC_LOGITECH },
481 { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2, HID_QUIRK_RDESC_LOGITECH },
482
483 { USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE, HID_QUIRK_RDESC_PETALYNX },
484
485 { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1, HID_QUIRK_RDESC_SWAPPED_MIN_MAX },
486 { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2, HID_QUIRK_RDESC_SWAPPED_MIN_MAX },
454 487
455 { 0, 0 } 488 { 0, 0 }
456}; 489};
@@ -559,7 +592,6 @@ int usbhid_modify_dquirk(const u16 idVendor, const u16 idProduct,
559 return 0; 592 return 0;
560} 593}
561 594
562
563/** 595/**
564 * usbhid_remove_all_dquirks: remove all runtime HID quirks from memory 596 * usbhid_remove_all_dquirks: remove all runtime HID quirks from memory
565 * 597 *
@@ -675,6 +707,12 @@ u32 usbhid_lookup_quirk(const u16 idVendor, const u16 idProduct)
675 idProduct <= USB_DEVICE_ID_CODEMERCS_IOW_LAST) 707 idProduct <= USB_DEVICE_ID_CODEMERCS_IOW_LAST)
676 return HID_QUIRK_IGNORE; 708 return HID_QUIRK_IGNORE;
677 709
710 /* NCR devices must not be queried for reports */
711 if (idVendor == USB_VENDOR_ID_NCR &&
712 idProduct >= USB_DEVICE_ID_NCR_FIRST &&
713 idProduct <= USB_DEVICE_ID_NCR_LAST)
714 return HID_QUIRK_NOGET;
715
678 down_read(&dquirks_rwsem); 716 down_read(&dquirks_rwsem);
679 bl_entry = usbhid_exists_dquirk(idVendor, idProduct); 717 bl_entry = usbhid_exists_dquirk(idVendor, idProduct);
680 if (!bl_entry) 718 if (!bl_entry)
@@ -686,3 +724,126 @@ u32 usbhid_lookup_quirk(const u16 idVendor, const u16 idProduct)
686 return quirks; 724 return quirks;
687} 725}
688 726
727/*
728 * Cherry Cymotion keyboard have an invalid HID report descriptor,
729 * that needs fixing before we can parse it.
730 */
731static void usbhid_fixup_cymotion_descriptor(char *rdesc, int rsize)
732{
733 if (rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) {
734 printk(KERN_INFO "Fixing up Cherry Cymotion report descriptor\n");
735 rdesc[11] = rdesc[16] = 0xff;
736 rdesc[12] = rdesc[17] = 0x03;
737 }
738}
739
740
741/*
742 * Certain Logitech keyboards send in report #3 keys which are far
743 * above the logical maximum described in descriptor. This extends
744 * the original value of 0x28c of logical maximum to 0x104d
745 */
746static void usbhid_fixup_logitech_descriptor(unsigned char *rdesc, int rsize)
747{
748 if (rsize >= 90 && rdesc[83] == 0x26
749 && rdesc[84] == 0x8c
750 && rdesc[85] == 0x02) {
751 printk(KERN_INFO "Fixing up Logitech keyboard report descriptor\n");
752 rdesc[84] = rdesc[89] = 0x4d;
753 rdesc[85] = rdesc[90] = 0x10;
754 }
755}
756
757/* Petalynx Maxter Remote has maximum for consumer page set too low */
758static void usbhid_fixup_petalynx_descriptor(unsigned char *rdesc, int rsize)
759{
760 if (rsize >= 60 && rdesc[39] == 0x2a
761 && rdesc[40] == 0xf5
762 && rdesc[41] == 0x00
763 && rdesc[59] == 0x26
764 && rdesc[60] == 0xf9
765 && rdesc[61] == 0x00) {
766 printk(KERN_INFO "Fixing up Petalynx Maxter Remote report descriptor\n");
767 rdesc[60] = 0xfa;
768 rdesc[40] = 0xfa;
769 }
770}
771
772/*
773 * Some USB barcode readers from cypress have usage min and usage max in
774 * the wrong order
775 */
776static void usbhid_fixup_cypress_descriptor(unsigned char *rdesc, int rsize)
777{
778 short fixed = 0;
779 int i;
780
781 for (i = 0; i < rsize - 4; i++) {
782 if (rdesc[i] == 0x29 && rdesc [i+2] == 0x19) {
783 unsigned char tmp;
784
785 rdesc[i] = 0x19; rdesc[i+2] = 0x29;
786 tmp = rdesc[i+3];
787 rdesc[i+3] = rdesc[i+1];
788 rdesc[i+1] = tmp;
789 }
790 }
791
792 if (fixed)
793 printk(KERN_INFO "Fixing up Cypress report descriptor\n");
794}
795
796
797static void __usbhid_fixup_report_descriptor(__u32 quirks, char *rdesc, unsigned rsize)
798{
799 if ((quirks & HID_QUIRK_RDESC_CYMOTION))
800 usbhid_fixup_cymotion_descriptor(rdesc, rsize);
801
802 if (quirks & HID_QUIRK_RDESC_LOGITECH)
803 usbhid_fixup_logitech_descriptor(rdesc, rsize);
804
805 if (quirks & HID_QUIRK_RDESC_SWAPPED_MIN_MAX)
806 usbhid_fixup_cypress_descriptor(rdesc, rsize);
807
808 if (quirks & HID_QUIRK_RDESC_PETALYNX)
809 usbhid_fixup_petalynx_descriptor(rdesc, rsize);
810}
811
812/**
813 * usbhid_fixup_report_descriptor: check if report descriptor needs fixup
814 *
815 * Description:
816 * Walks the hid_rdesc_blacklist[] array and checks whether the device
817 * is known to have broken report descriptor that needs to be fixed up
818 * prior to entering the HID parser
819 *
820 * Returns: nothing
821 */
822void usbhid_fixup_report_descriptor(const u16 idVendor, const u16 idProduct,
823 char *rdesc, unsigned rsize, char **quirks_param)
824{
825 int n, m;
826 u16 paramVendor, paramProduct;
827 u32 quirks;
828
829 /* static rdesc quirk entries */
830 for (n = 0; hid_rdesc_blacklist[n].idVendor; n++)
831 if (hid_rdesc_blacklist[n].idVendor == idVendor &&
832 hid_rdesc_blacklist[n].idProduct == idProduct)
833 __usbhid_fixup_report_descriptor(hid_rdesc_blacklist[n].quirks,
834 rdesc, rsize);
835
836 /* runtime rdesc quirk entries handling */
837 for (n = 0; quirks_param[n] && n < MAX_USBHID_BOOT_QUIRKS; n++) {
838 m = sscanf(quirks_param[n], "0x%hx:0x%hx:0x%x",
839 &paramVendor, &paramProduct, &quirks);
840
841 if (m != 3)
842 printk(KERN_WARNING
843 "Could not parse HID quirk module param %s\n",
844 quirks_param[n]);
845 else if (paramVendor == idVendor && paramProduct == idProduct)
846 __usbhid_fixup_report_descriptor(quirks, rdesc, rsize);
847 }
848
849}
diff --git a/include/linux/hid.h b/include/linux/hid.h
index eb53d9a9ae54..898103b401f1 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -263,19 +263,28 @@ struct hid_item {
263#define HID_QUIRK_2WHEEL_MOUSE_HACK_5 0x00000100 263#define HID_QUIRK_2WHEEL_MOUSE_HACK_5 0x00000100
264#define HID_QUIRK_2WHEEL_MOUSE_HACK_ON 0x00000200 264#define HID_QUIRK_2WHEEL_MOUSE_HACK_ON 0x00000200
265#define HID_QUIRK_MIGHTYMOUSE 0x00000400 265#define HID_QUIRK_MIGHTYMOUSE 0x00000400
266#define HID_QUIRK_CYMOTION 0x00000800 266#define HID_QUIRK_POWERBOOK_HAS_FN 0x00000800
267#define HID_QUIRK_POWERBOOK_HAS_FN 0x00001000 267#define HID_QUIRK_POWERBOOK_FN_ON 0x00001000
268#define HID_QUIRK_POWERBOOK_FN_ON 0x00002000 268#define HID_QUIRK_INVERT_HWHEEL 0x00002000
269#define HID_QUIRK_INVERT_HWHEEL 0x00004000 269#define HID_QUIRK_POWERBOOK_ISO_KEYBOARD 0x00004000
270#define HID_QUIRK_POWERBOOK_ISO_KEYBOARD 0x00008000 270#define HID_QUIRK_BAD_RELATIVE_KEYS 0x00008000
271#define HID_QUIRK_BAD_RELATIVE_KEYS 0x00010000 271#define HID_QUIRK_SKIP_OUTPUT_REPORTS 0x00010000
272#define HID_QUIRK_SKIP_OUTPUT_REPORTS 0x00020000 272#define HID_QUIRK_IGNORE_MOUSE 0x00020000
273#define HID_QUIRK_IGNORE_MOUSE 0x00040000 273#define HID_QUIRK_SONY_PS3_CONTROLLER 0x00040000
274#define HID_QUIRK_SONY_PS3_CONTROLLER 0x00080000 274#define HID_QUIRK_DUPLICATE_USAGES 0x00080000
275#define HID_QUIRK_LOGITECH_DESCRIPTOR 0x00100000 275#define HID_QUIRK_RESET_LEDS 0x00100000
276#define HID_QUIRK_DUPLICATE_USAGES 0x00200000 276#define HID_QUIRK_HIDINPUT 0x00200000
277#define HID_QUIRK_RESET_LEDS 0x00400000 277#define HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL 0x00400000
278#define HID_QUIRK_SWAPPED_MIN_MAX 0x00800000 278#define HID_QUIRK_LOGITECH_EXPANDED_KEYMAP 0x00800000
279
280/*
281 * Separate quirks for runtime report descriptor fixup
282 */
283
284#define HID_QUIRK_RDESC_CYMOTION 0x00000001
285#define HID_QUIRK_RDESC_LOGITECH 0x00000002
286#define HID_QUIRK_RDESC_SWAPPED_MIN_MAX 0x00000004
287#define HID_QUIRK_RDESC_PETALYNX 0x00000008
279 288
280/* 289/*
281 * This is the global environment of the parser. This information is 290 * This is the global environment of the parser. This information is
@@ -511,6 +520,7 @@ u32 usbhid_lookup_quirk(const u16 idVendor, const u16 idProduct);
511int usbhid_modify_dquirk(const u16 idVendor, const u16 idProduct, const u32 quirks); 520int usbhid_modify_dquirk(const u16 idVendor, const u16 idProduct, const u32 quirks);
512int usbhid_quirks_init(char **quirks_param); 521int usbhid_quirks_init(char **quirks_param);
513void usbhid_quirks_exit(void); 522void usbhid_quirks_exit(void);
523void usbhid_fixup_report_descriptor(const u16, const u16, char *, unsigned, char **);
514 524
515#ifdef CONFIG_HID_FF 525#ifdef CONFIG_HID_FF
516int hid_ff_init(struct hid_device *hid); 526int hid_ff_init(struct hid_device *hid);