aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-03-01 20:30:51 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-03-01 20:30:51 -0500
commitb4350861dd6d5668bb9fe18eec4227d30e9131b0 (patch)
treec410415ddd2ee50e76448df0d6aed83198d80d5e
parent132a69c6cc3dfa7fa354a88128acee7e6ee7082b (diff)
parent25914662b7e86f8cf8abdde0497e7fe8bdddf2ae (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
-rw-r--r--MAINTAINERS2
-rw-r--r--drivers/hid/hid-core.c7
-rw-r--r--drivers/hid/hid-debug.c1
-rw-r--r--drivers/hid/hid-input.c37
-rw-r--r--drivers/usb/input/hid-core.c35
-rw-r--r--include/linux/hid.h6
6 files changed, 67 insertions, 21 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 480ccb9d6cc9..1dfba85ca7b5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1492,6 +1492,7 @@ HID CORE LAYER
1492P: Jiri Kosina 1492P: Jiri Kosina
1493M: jkosina@suse.cz 1493M: jkosina@suse.cz
1494L: linux-input@atrey.karlin.mff.cuni.cz 1494L: linux-input@atrey.karlin.mff.cuni.cz
1495T: git kernel.org:/pub/scm/linux/kernel/git/jikos/hid.git
1495S: Maintained 1496S: Maintained
1496 1497
1497HIGH-RESOLUTION TIMERS, CLOCKEVENTS, DYNTICKS 1498HIGH-RESOLUTION TIMERS, CLOCKEVENTS, DYNTICKS
@@ -3423,6 +3424,7 @@ USB HID/HIDBP DRIVERS
3423P: Jiri Kosina 3424P: Jiri Kosina
3424M: jkosina@suse.cz 3425M: jkosina@suse.cz
3425L: linux-usb-devel@lists.sourceforge.net 3426L: linux-usb-devel@lists.sourceforge.net
3427T: git kernel.org:/pub/scm/linux/kernel/git/jikos/hid.git
3426S: Maintained 3428S: Maintained
3427 3429
3428USB HUB DRIVER 3430USB HUB DRIVER
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
33struct hid_usage_entry { 34struct 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 */
1051static 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
1044static struct hid_device *usb_hid_configure(struct usb_interface *intf) 1062static 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));
diff --git a/include/linux/hid.h b/include/linux/hid.h
index d26b08f461f2..8c97d4d3fdb0 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -6,7 +6,7 @@
6 * 6 *
7 * Copyright (c) 1999 Andreas Gal 7 * Copyright (c) 1999 Andreas Gal
8 * Copyright (c) 2000-2001 Vojtech Pavlik 8 * Copyright (c) 2000-2001 Vojtech Pavlik
9 * Copyright (c) 2006 Jiri Kosina 9 * Copyright (c) 2006-2007 Jiri Kosina
10 */ 10 */
11 11
12/* 12/*
@@ -267,6 +267,8 @@ struct hid_item {
267#define HID_QUIRK_SKIP_OUTPUT_REPORTS 0x00020000 267#define HID_QUIRK_SKIP_OUTPUT_REPORTS 0x00020000
268#define HID_QUIRK_IGNORE_MOUSE 0x00040000 268#define HID_QUIRK_IGNORE_MOUSE 0x00040000
269#define HID_QUIRK_SONY_PS3_CONTROLLER 0x00080000 269#define HID_QUIRK_SONY_PS3_CONTROLLER 0x00080000
270#define HID_QUIRK_LOGITECH_S510_DESCRIPTOR 0x00100000
271#define HID_QUIRK_DUPLICATE_USAGES 0x00200000
270 272
271/* 273/*
272 * This is the global environment of the parser. This information is 274 * This is the global environment of the parser. This information is
@@ -292,7 +294,7 @@ struct hid_global {
292 */ 294 */
293 295
294#define HID_MAX_DESCRIPTOR_SIZE 4096 296#define HID_MAX_DESCRIPTOR_SIZE 4096
295#define HID_MAX_USAGES 1024 297#define HID_MAX_USAGES 8192
296#define HID_DEFAULT_NUM_COLLECTIONS 16 298#define HID_DEFAULT_NUM_COLLECTIONS 16
297 299
298struct hid_local { 300struct hid_local {