diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-03-01 20:30:51 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-03-01 20:30:51 -0500 |
commit | b4350861dd6d5668bb9fe18eec4227d30e9131b0 (patch) | |
tree | c410415ddd2ee50e76448df0d6aed83198d80d5e /drivers | |
parent | 132a69c6cc3dfa7fa354a88128acee7e6ee7082b (diff) | |
parent | 25914662b7e86f8cf8abdde0497e7fe8bdddf2ae (diff) |
Merge branch 'for-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jikos/hid
* 'for-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jikos/hid:
HID: fix Logitech DiNovo Edge touchwheel and Logic3 /SpectraVideo middle button
HID: add git tree information to MAINTAINERS
HID: fix broken Logitech S510 keyboard report descriptor; make extra keys work
HID: fix possible double-free on error path in hid parser
HID: hid-debug.c should #include <linux/hid-debug.h>
HID: fix bug in zeroing the last field byte in output reports
USB HID: use CONFIG_HID_DEBUG for outputting report descriptor
USB HID: Fix USB vendor and product IDs endianness for USB HID devices
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/hid/hid-core.c | 7 | ||||
-rw-r--r-- | drivers/hid/hid-debug.c | 1 | ||||
-rw-r--r-- | drivers/hid/hid-input.c | 37 | ||||
-rw-r--r-- | drivers/usb/input/hid-core.c | 35 |
4 files changed, 61 insertions, 19 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 7452399501b4..f4ee1afe488f 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
@@ -667,7 +667,6 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size) | |||
667 | 667 | ||
668 | if (item.format != HID_ITEM_FORMAT_SHORT) { | 668 | if (item.format != HID_ITEM_FORMAT_SHORT) { |
669 | dbg("unexpected long global item"); | 669 | dbg("unexpected long global item"); |
670 | kfree(device->collection); | ||
671 | hid_free_device(device); | 670 | hid_free_device(device); |
672 | kfree(parser); | 671 | kfree(parser); |
673 | return NULL; | 672 | return NULL; |
@@ -676,7 +675,6 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size) | |||
676 | if (dispatch_type[item.type](parser, &item)) { | 675 | if (dispatch_type[item.type](parser, &item)) { |
677 | dbg("item %u %u %u %u parsing failed\n", | 676 | dbg("item %u %u %u %u parsing failed\n", |
678 | item.format, (unsigned)item.size, (unsigned)item.type, (unsigned)item.tag); | 677 | item.format, (unsigned)item.size, (unsigned)item.type, (unsigned)item.tag); |
679 | kfree(device->collection); | ||
680 | hid_free_device(device); | 678 | hid_free_device(device); |
681 | kfree(parser); | 679 | kfree(parser); |
682 | return NULL; | 680 | return NULL; |
@@ -685,14 +683,12 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size) | |||
685 | if (start == end) { | 683 | if (start == end) { |
686 | if (parser->collection_stack_ptr) { | 684 | if (parser->collection_stack_ptr) { |
687 | dbg("unbalanced collection at end of report description"); | 685 | dbg("unbalanced collection at end of report description"); |
688 | kfree(device->collection); | ||
689 | hid_free_device(device); | 686 | hid_free_device(device); |
690 | kfree(parser); | 687 | kfree(parser); |
691 | return NULL; | 688 | return NULL; |
692 | } | 689 | } |
693 | if (parser->local.delimiter_depth) { | 690 | if (parser->local.delimiter_depth) { |
694 | dbg("unbalanced delimiter at end of report description"); | 691 | dbg("unbalanced delimiter at end of report description"); |
695 | kfree(device->collection); | ||
696 | hid_free_device(device); | 692 | hid_free_device(device); |
697 | kfree(parser); | 693 | kfree(parser); |
698 | return NULL; | 694 | return NULL; |
@@ -703,7 +699,6 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size) | |||
703 | } | 699 | } |
704 | 700 | ||
705 | dbg("item fetching failed at offset %d\n", (int)(end - start)); | 701 | dbg("item fetching failed at offset %d\n", (int)(end - start)); |
706 | kfree(device->collection); | ||
707 | hid_free_device(device); | 702 | hid_free_device(device); |
708 | kfree(parser); | 703 | kfree(parser); |
709 | return NULL; | 704 | return NULL; |
@@ -880,7 +875,7 @@ static void hid_output_field(struct hid_field *field, __u8 *data) | |||
880 | 875 | ||
881 | /* make sure the unused bits in the last byte are zeros */ | 876 | /* make sure the unused bits in the last byte are zeros */ |
882 | if (count > 0 && size > 0) | 877 | if (count > 0 && size > 0) |
883 | data[(count*size-1)/8] = 0; | 878 | data[(offset+count*size-1)/8] = 0; |
884 | 879 | ||
885 | for (n = 0; n < count; n++) { | 880 | for (n = 0; n < count; n++) { |
886 | if (field->logical_minimum < 0) /* signed values */ | 881 | if (field->logical_minimum < 0) /* signed values */ |
diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c index 89241be4ec9b..83c4126b37c3 100644 --- a/drivers/hid/hid-debug.c +++ b/drivers/hid/hid-debug.c | |||
@@ -29,6 +29,7 @@ | |||
29 | */ | 29 | */ |
30 | 30 | ||
31 | #include <linux/hid.h> | 31 | #include <linux/hid.h> |
32 | #include <linux/hid-debug.h> | ||
32 | 33 | ||
33 | struct hid_usage_entry { | 34 | struct hid_usage_entry { |
34 | unsigned page; | 35 | unsigned page; |
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 25d180a24fc4..c8434023ba65 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * $Id: hid-input.c,v 1.2 2002/04/23 00:59:25 rdamazio Exp $ | 2 | * $Id: hid-input.c,v 1.2 2002/04/23 00:59:25 rdamazio Exp $ |
3 | * | 3 | * |
4 | * Copyright (c) 2000-2001 Vojtech Pavlik | 4 | * Copyright (c) 2000-2001 Vojtech Pavlik |
5 | * Copyright (c) 2006 Jiri Kosina | 5 | * Copyright (c) 2006-2007 Jiri Kosina |
6 | * | 6 | * |
7 | * HID to Linux Input mapping | 7 | * HID to Linux Input mapping |
8 | */ | 8 | */ |
@@ -71,7 +71,6 @@ static const struct { | |||
71 | #define map_led(c) do { usage->code = c; usage->type = EV_LED; bit = input->ledbit; max = LED_MAX; } while (0) | 71 | #define map_led(c) do { usage->code = c; usage->type = EV_LED; bit = input->ledbit; max = LED_MAX; } while (0) |
72 | 72 | ||
73 | #define map_abs_clear(c) do { map_abs(c); clear_bit(c, bit); } while (0) | 73 | #define map_abs_clear(c) do { map_abs(c); clear_bit(c, bit); } while (0) |
74 | #define map_rel_clear(c) do { map_rel(c); clear_bit(c, bit); } while (0) | ||
75 | #define map_key_clear(c) do { map_key(c); clear_bit(c, bit); } while (0) | 74 | #define map_key_clear(c) do { map_key(c); clear_bit(c, bit); } while (0) |
76 | 75 | ||
77 | #ifdef CONFIG_USB_HIDINPUT_POWERBOOK | 76 | #ifdef CONFIG_USB_HIDINPUT_POWERBOOK |
@@ -296,7 +295,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
296 | } | 295 | } |
297 | } | 296 | } |
298 | 297 | ||
299 | map_key_clear(code); | 298 | map_key(code); |
300 | break; | 299 | break; |
301 | 300 | ||
302 | 301 | ||
@@ -347,9 +346,9 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
347 | case HID_GD_RX: case HID_GD_RY: case HID_GD_RZ: | 346 | case HID_GD_RX: case HID_GD_RY: case HID_GD_RZ: |
348 | case HID_GD_SLIDER: case HID_GD_DIAL: case HID_GD_WHEEL: | 347 | case HID_GD_SLIDER: case HID_GD_DIAL: case HID_GD_WHEEL: |
349 | if (field->flags & HID_MAIN_ITEM_RELATIVE) | 348 | if (field->flags & HID_MAIN_ITEM_RELATIVE) |
350 | map_rel_clear(usage->hid & 0xf); | 349 | map_rel(usage->hid & 0xf); |
351 | else | 350 | else |
352 | map_abs_clear(usage->hid & 0xf); | 351 | map_abs(usage->hid & 0xf); |
353 | break; | 352 | break; |
354 | 353 | ||
355 | case HID_GD_HATSWITCH: | 354 | case HID_GD_HATSWITCH: |
@@ -519,7 +518,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
519 | case 0x22f: map_key_clear(KEY_ZOOMRESET); break; | 518 | case 0x22f: map_key_clear(KEY_ZOOMRESET); break; |
520 | case 0x233: map_key_clear(KEY_SCROLLUP); break; | 519 | case 0x233: map_key_clear(KEY_SCROLLUP); break; |
521 | case 0x234: map_key_clear(KEY_SCROLLDOWN); break; | 520 | case 0x234: map_key_clear(KEY_SCROLLDOWN); break; |
522 | case 0x238: map_rel_clear(REL_HWHEEL); break; | 521 | case 0x238: map_rel(REL_HWHEEL); break; |
523 | case 0x25f: map_key_clear(KEY_CANCEL); break; | 522 | case 0x25f: map_key_clear(KEY_CANCEL); break; |
524 | case 0x279: map_key_clear(KEY_REDO); break; | 523 | case 0x279: map_key_clear(KEY_REDO); break; |
525 | 524 | ||
@@ -532,6 +531,26 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
532 | case 0x302: map_key_clear(KEY_PROG2); break; | 531 | case 0x302: map_key_clear(KEY_PROG2); break; |
533 | case 0x303: map_key_clear(KEY_PROG3); break; | 532 | case 0x303: map_key_clear(KEY_PROG3); break; |
534 | 533 | ||
534 | /* Reported on Logitech S510 wireless keyboard */ | ||
535 | case 0x101f: map_key_clear(KEY_ZOOMIN); break; | ||
536 | case 0x1020: map_key_clear(KEY_ZOOMOUT); break; | ||
537 | case 0x1021: map_key_clear(KEY_ZOOMRESET); break; | ||
538 | /* this one is marked as 'Rotate' */ | ||
539 | case 0x1028: map_key_clear(KEY_ANGLE); break; | ||
540 | case 0x1029: map_key_clear(KEY_SHUFFLE); break; | ||
541 | case 0x1041: map_key_clear(KEY_BATTERY); break; | ||
542 | case 0x1042: map_key_clear(KEY_WORDPROCESSOR); break; | ||
543 | case 0x1043: map_key_clear(KEY_SPREADSHEET); break; | ||
544 | case 0x1044: map_key_clear(KEY_PRESENTATION); break; | ||
545 | case 0x1045: map_key_clear(KEY_UNDO); break; | ||
546 | case 0x1046: map_key_clear(KEY_REDO); break; | ||
547 | case 0x1047: map_key_clear(KEY_PRINT); break; | ||
548 | case 0x1048: map_key_clear(KEY_SAVE); break; | ||
549 | case 0x1049: map_key_clear(KEY_PROG1); break; | ||
550 | case 0x104a: map_key_clear(KEY_PROG2); break; | ||
551 | case 0x104b: map_key_clear(KEY_PROG3); break; | ||
552 | case 0x104c: map_key_clear(KEY_PROG4); break; | ||
553 | |||
535 | default: goto ignore; | 554 | default: goto ignore; |
536 | } | 555 | } |
537 | break; | 556 | break; |
@@ -647,6 +666,12 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
647 | 666 | ||
648 | set_bit(usage->type, input->evbit); | 667 | set_bit(usage->type, input->evbit); |
649 | 668 | ||
669 | if (device->quirks & HID_QUIRK_DUPLICATE_USAGES && | ||
670 | (usage->type == EV_KEY || | ||
671 | usage->type == EV_REL || | ||
672 | usage->type == EV_ABS)) | ||
673 | clear_bit(usage->code, bit); | ||
674 | |||
650 | while (usage->code <= max && test_and_set_bit(usage->code, bit)) | 675 | while (usage->code <= max && test_and_set_bit(usage->code, bit)) |
651 | usage->code = find_next_zero_bit(bit, max + 1, usage->code); | 676 | usage->code = find_next_zero_bit(bit, max + 1, usage->code); |
652 | 677 | ||
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index ef09952f2039..12ec8b432953 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * Copyright (c) 1999 Andreas Gal | 4 | * Copyright (c) 1999 Andreas Gal |
5 | * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> | 5 | * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> |
6 | * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc | 6 | * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc |
7 | * Copyright (c) 2006 Jiri Kosina | 7 | * Copyright (c) 2006-2007 Jiri Kosina |
8 | */ | 8 | */ |
9 | 9 | ||
10 | /* | 10 | /* |
@@ -27,9 +27,6 @@ | |||
27 | #include <linux/input.h> | 27 | #include <linux/input.h> |
28 | #include <linux/wait.h> | 28 | #include <linux/wait.h> |
29 | 29 | ||
30 | #undef DEBUG | ||
31 | #undef DEBUG_DATA | ||
32 | |||
33 | #include <linux/usb.h> | 30 | #include <linux/usb.h> |
34 | 31 | ||
35 | #include <linux/hid.h> | 32 | #include <linux/hid.h> |
@@ -758,6 +755,8 @@ void usbhid_init_reports(struct hid_device *hid) | |||
758 | 755 | ||
759 | #define USB_VENDOR_ID_LOGITECH 0x046d | 756 | #define USB_VENDOR_ID_LOGITECH 0x046d |
760 | #define USB_DEVICE_ID_LOGITECH_USB_RECEIVER 0xc101 | 757 | #define USB_DEVICE_ID_LOGITECH_USB_RECEIVER 0xc101 |
758 | #define USB_DEVICE_ID_LOGITECH_USB_RECEIVER_2 0xc517 | ||
759 | #define USB_DEVICE_ID_DINOVO_EDGE 0xc714 | ||
761 | 760 | ||
762 | #define USB_VENDOR_ID_IMATION 0x0718 | 761 | #define USB_VENDOR_ID_IMATION 0x0718 |
763 | #define USB_DEVICE_ID_DISC_STAKKA 0xd000 | 762 | #define USB_DEVICE_ID_DISC_STAKKA 0xd000 |
@@ -778,6 +777,8 @@ static const struct hid_blacklist { | |||
778 | unsigned quirks; | 777 | unsigned quirks; |
779 | } hid_blacklist[] = { | 778 | } hid_blacklist[] = { |
780 | 779 | ||
780 | { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE, HID_QUIRK_DUPLICATE_USAGES }, | ||
781 | |||
781 | { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_01, HID_QUIRK_IGNORE }, | 782 | { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_01, HID_QUIRK_IGNORE }, |
782 | { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_10, HID_QUIRK_IGNORE }, | 783 | { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_10, HID_QUIRK_IGNORE }, |
783 | { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_20, HID_QUIRK_IGNORE }, | 784 | { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_20, HID_QUIRK_IGNORE }, |
@@ -944,6 +945,7 @@ static const struct hid_blacklist { | |||
944 | { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET }, | 945 | { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET }, |
945 | 946 | ||
946 | { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_USB_RECEIVER, HID_QUIRK_BAD_RELATIVE_KEYS }, | 947 | { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_USB_RECEIVER, HID_QUIRK_BAD_RELATIVE_KEYS }, |
948 | { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_USB_RECEIVER_2, HID_QUIRK_LOGITECH_S510_DESCRIPTOR }, | ||
947 | 949 | ||
948 | { USB_VENDOR_ID_PANTHERLORD, USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK, HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS }, | 950 | { USB_VENDOR_ID_PANTHERLORD, USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK, HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS }, |
949 | 951 | ||
@@ -1041,6 +1043,22 @@ static void hid_fixup_sony_ps3_controller(struct usb_device *dev, int ifnum) | |||
1041 | kfree(buf); | 1043 | kfree(buf); |
1042 | } | 1044 | } |
1043 | 1045 | ||
1046 | /* | ||
1047 | * Logitech S510 keyboard sends in report #3 keys which are far | ||
1048 | * above the logical maximum described in descriptor. This extends | ||
1049 | * the original value of 0x28c of logical maximum to 0x104d | ||
1050 | */ | ||
1051 | static void hid_fixup_s510_descriptor(unsigned char *rdesc, int rsize) | ||
1052 | { | ||
1053 | if (rsize >= 90 && rdesc[83] == 0x26 | ||
1054 | && rdesc[84] == 0x8c | ||
1055 | && rdesc[85] == 0x02) { | ||
1056 | info("Fixing up Logitech S510 report descriptor"); | ||
1057 | rdesc[84] = rdesc[89] = 0x4d; | ||
1058 | rdesc[85] = rdesc[90] = 0x10; | ||
1059 | } | ||
1060 | } | ||
1061 | |||
1044 | static struct hid_device *usb_hid_configure(struct usb_interface *intf) | 1062 | static struct hid_device *usb_hid_configure(struct usb_interface *intf) |
1045 | { | 1063 | { |
1046 | struct usb_host_interface *interface = intf->cur_altsetting; | 1064 | struct usb_host_interface *interface = intf->cur_altsetting; |
@@ -1109,7 +1127,10 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) | |||
1109 | if ((quirks & HID_QUIRK_CYMOTION)) | 1127 | if ((quirks & HID_QUIRK_CYMOTION)) |
1110 | hid_fixup_cymotion_descriptor(rdesc, rsize); | 1128 | hid_fixup_cymotion_descriptor(rdesc, rsize); |
1111 | 1129 | ||
1112 | #ifdef DEBUG_DATA | 1130 | if (quirks & HID_QUIRK_LOGITECH_S510_DESCRIPTOR) |
1131 | hid_fixup_s510_descriptor(rdesc, rsize); | ||
1132 | |||
1133 | #ifdef CONFIG_HID_DEBUG | ||
1113 | printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n); | 1134 | printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n); |
1114 | for (n = 0; n < rsize; n++) | 1135 | for (n = 0; n < rsize; n++) |
1115 | printk(" %02x", (unsigned char) rdesc[n]); | 1136 | printk(" %02x", (unsigned char) rdesc[n]); |
@@ -1225,8 +1246,8 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) | |||
1225 | le16_to_cpu(dev->descriptor.idProduct)); | 1246 | le16_to_cpu(dev->descriptor.idProduct)); |
1226 | 1247 | ||
1227 | hid->bus = BUS_USB; | 1248 | hid->bus = BUS_USB; |
1228 | hid->vendor = dev->descriptor.idVendor; | 1249 | hid->vendor = le16_to_cpu(dev->descriptor.idVendor); |
1229 | hid->product = dev->descriptor.idProduct; | 1250 | hid->product = le16_to_cpu(dev->descriptor.idProduct); |
1230 | 1251 | ||
1231 | usb_make_path(dev, hid->phys, sizeof(hid->phys)); | 1252 | usb_make_path(dev, hid->phys, sizeof(hid->phys)); |
1232 | strlcat(hid->phys, "/input", sizeof(hid->phys)); | 1253 | strlcat(hid->phys, "/input", sizeof(hid->phys)); |