Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b4350861 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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
parents 132a69c6 25914662
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -1492,6 +1492,7 @@ HID CORE LAYER
P:	Jiri Kosina
M:	jkosina@suse.cz
L:	linux-input@atrey.karlin.mff.cuni.cz
T:	git kernel.org:/pub/scm/linux/kernel/git/jikos/hid.git
S:	Maintained

HIGH-RESOLUTION TIMERS, CLOCKEVENTS, DYNTICKS
@@ -3423,6 +3424,7 @@ USB HID/HIDBP DRIVERS
P:	Jiri Kosina
M:	jkosina@suse.cz
L:	linux-usb-devel@lists.sourceforge.net
T:	git kernel.org:/pub/scm/linux/kernel/git/jikos/hid.git
S:	Maintained

USB HUB DRIVER
+1 −6
Original line number Diff line number Diff line
@@ -667,7 +667,6 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size)

		if (item.format != HID_ITEM_FORMAT_SHORT) {
			dbg("unexpected long global item");
			kfree(device->collection);
			hid_free_device(device);
			kfree(parser);
			return NULL;
@@ -676,7 +675,6 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size)
		if (dispatch_type[item.type](parser, &item)) {
			dbg("item %u %u %u %u parsing failed\n",
				item.format, (unsigned)item.size, (unsigned)item.type, (unsigned)item.tag);
			kfree(device->collection);
			hid_free_device(device);
			kfree(parser);
			return NULL;
@@ -685,14 +683,12 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size)
		if (start == end) {
			if (parser->collection_stack_ptr) {
				dbg("unbalanced collection at end of report description");
				kfree(device->collection);
				hid_free_device(device);
				kfree(parser);
				return NULL;
			}
			if (parser->local.delimiter_depth) {
				dbg("unbalanced delimiter at end of report description");
				kfree(device->collection);
				hid_free_device(device);
				kfree(parser);
				return NULL;
@@ -703,7 +699,6 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size)
	}

	dbg("item fetching failed at offset %d\n", (int)(end - start));
	kfree(device->collection);
	hid_free_device(device);
	kfree(parser);
	return NULL;
@@ -880,7 +875,7 @@ static void hid_output_field(struct hid_field *field, __u8 *data)

	/* make sure the unused bits in the last byte are zeros */
	if (count > 0 && size > 0)
		data[(count*size-1)/8] = 0;
		data[(offset+count*size-1)/8] = 0;

	for (n = 0; n < count; n++) {
		if (field->logical_minimum < 0)	/* signed values */
+1 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@
 */

#include <linux/hid.h>
#include <linux/hid-debug.h>

struct hid_usage_entry {
	unsigned  page;
+31 −6
Original line number Diff line number Diff line
@@ -2,7 +2,7 @@
 * $Id: hid-input.c,v 1.2 2002/04/23 00:59:25 rdamazio Exp $
 *
 *  Copyright (c) 2000-2001 Vojtech Pavlik
 *  Copyright (c) 2006 Jiri Kosina
 *  Copyright (c) 2006-2007 Jiri Kosina
 *
 *  HID to Linux Input mapping
 */
@@ -71,7 +71,6 @@ static const struct {
#define map_led(c)	do { usage->code = c; usage->type = EV_LED; bit = input->ledbit; max = LED_MAX; } while (0)

#define map_abs_clear(c)	do { map_abs(c); clear_bit(c, bit); } while (0)
#define map_rel_clear(c)	do { map_rel(c); clear_bit(c, bit); } while (0)
#define map_key_clear(c)	do { map_key(c); clear_bit(c, bit); } while (0)

#ifdef CONFIG_USB_HIDINPUT_POWERBOOK
@@ -296,7 +295,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
					}
			}

			map_key_clear(code);
			map_key(code);
			break;


@@ -347,9 +346,9 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
				case HID_GD_RX: case HID_GD_RY: case HID_GD_RZ:
				case HID_GD_SLIDER: case HID_GD_DIAL: case HID_GD_WHEEL:
					if (field->flags & HID_MAIN_ITEM_RELATIVE)
						map_rel_clear(usage->hid & 0xf);
						map_rel(usage->hid & 0xf);
					else
						map_abs_clear(usage->hid & 0xf);
						map_abs(usage->hid & 0xf);
					break;

				case HID_GD_HATSWITCH:
@@ -519,7 +518,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
				case 0x22f: map_key_clear(KEY_ZOOMRESET);	break;
				case 0x233: map_key_clear(KEY_SCROLLUP);	break;
				case 0x234: map_key_clear(KEY_SCROLLDOWN);	break;
				case 0x238: map_rel_clear(REL_HWHEEL);		break;
				case 0x238: map_rel(REL_HWHEEL);		break;
				case 0x25f: map_key_clear(KEY_CANCEL);		break;
				case 0x279: map_key_clear(KEY_REDO);		break;

@@ -532,6 +531,26 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
				case 0x302: map_key_clear(KEY_PROG2);		break;
				case 0x303: map_key_clear(KEY_PROG3);		break;

				/* Reported on Logitech S510 wireless keyboard */
				case 0x101f: map_key_clear(KEY_ZOOMIN);		break;
				case 0x1020: map_key_clear(KEY_ZOOMOUT);	break;
				case 0x1021: map_key_clear(KEY_ZOOMRESET);	break;
				/* this one is marked as 'Rotate' */
				case 0x1028: map_key_clear(KEY_ANGLE);		break;
				case 0x1029: map_key_clear(KEY_SHUFFLE);	break;
				case 0x1041: map_key_clear(KEY_BATTERY);	break;
				case 0x1042: map_key_clear(KEY_WORDPROCESSOR);	break;
				case 0x1043: map_key_clear(KEY_SPREADSHEET);	break;
				case 0x1044: map_key_clear(KEY_PRESENTATION);	break;
				case 0x1045: map_key_clear(KEY_UNDO);		break;
				case 0x1046: map_key_clear(KEY_REDO);		break;
				case 0x1047: map_key_clear(KEY_PRINT);		break;
				case 0x1048: map_key_clear(KEY_SAVE);		break;
				case 0x1049: map_key_clear(KEY_PROG1);		break;
				case 0x104a: map_key_clear(KEY_PROG2);		break;
				case 0x104b: map_key_clear(KEY_PROG3);		break;
				case 0x104c: map_key_clear(KEY_PROG4);		break;

				default:    goto ignore;
			}
			break;
@@ -647,6 +666,12 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel

	set_bit(usage->type, input->evbit);

	if (device->quirks & HID_QUIRK_DUPLICATE_USAGES &&
			(usage->type == EV_KEY ||
			 usage->type == EV_REL ||
			 usage->type == EV_ABS))
		clear_bit(usage->code, bit);

	while (usage->code <= max && test_and_set_bit(usage->code, bit))
		usage->code = find_next_zero_bit(bit, max + 1, usage->code);

+28 −7
Original line number Diff line number Diff line
@@ -4,7 +4,7 @@
 *  Copyright (c) 1999 Andreas Gal
 *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
 *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
 *  Copyright (c) 2006 Jiri Kosina
 *  Copyright (c) 2006-2007 Jiri Kosina
 */

/*
@@ -27,9 +27,6 @@
#include <linux/input.h>
#include <linux/wait.h>

#undef DEBUG
#undef DEBUG_DATA

#include <linux/usb.h>

#include <linux/hid.h>
@@ -758,6 +755,8 @@ void usbhid_init_reports(struct hid_device *hid)

#define USB_VENDOR_ID_LOGITECH		0x046d
#define USB_DEVICE_ID_LOGITECH_USB_RECEIVER	0xc101
#define USB_DEVICE_ID_LOGITECH_USB_RECEIVER_2	0xc517
#define USB_DEVICE_ID_DINOVO_EDGE	0xc714

#define USB_VENDOR_ID_IMATION		0x0718
#define USB_DEVICE_ID_DISC_STAKKA	0xd000
@@ -778,6 +777,8 @@ static const struct hid_blacklist {
	unsigned quirks;
} hid_blacklist[] = {

	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE, HID_QUIRK_DUPLICATE_USAGES },

	{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_01, HID_QUIRK_IGNORE },
	{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_10, HID_QUIRK_IGNORE },
	{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_20, HID_QUIRK_IGNORE },
@@ -944,6 +945,7 @@ static const struct hid_blacklist {
	{ USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET },

	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_USB_RECEIVER, HID_QUIRK_BAD_RELATIVE_KEYS },
	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_USB_RECEIVER_2, HID_QUIRK_LOGITECH_S510_DESCRIPTOR },

	{ USB_VENDOR_ID_PANTHERLORD, USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK, HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS },

@@ -1041,6 +1043,22 @@ static void hid_fixup_sony_ps3_controller(struct usb_device *dev, int ifnum)
	kfree(buf);
}

/*
 * Logitech S510 keyboard sends in report #3 keys which are far
 * above the logical maximum described in descriptor. This extends
 * the original value of 0x28c of logical maximum to 0x104d
 */
static void hid_fixup_s510_descriptor(unsigned char *rdesc, int rsize)
{
	if (rsize >= 90 && rdesc[83] == 0x26
			&& rdesc[84] == 0x8c
			&& rdesc[85] == 0x02) {
		info("Fixing up Logitech S510 report descriptor");
		rdesc[84] = rdesc[89] = 0x4d;
		rdesc[85] = rdesc[90] = 0x10;
	}
}

static struct hid_device *usb_hid_configure(struct usb_interface *intf)
{
	struct usb_host_interface *interface = intf->cur_altsetting;
@@ -1109,7 +1127,10 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
	if ((quirks & HID_QUIRK_CYMOTION))
		hid_fixup_cymotion_descriptor(rdesc, rsize);

#ifdef DEBUG_DATA
	if (quirks & HID_QUIRK_LOGITECH_S510_DESCRIPTOR)
		hid_fixup_s510_descriptor(rdesc, rsize);

#ifdef CONFIG_HID_DEBUG
	printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n);
	for (n = 0; n < rsize; n++)
		printk(" %02x", (unsigned char) rdesc[n]);
@@ -1225,8 +1246,8 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
			 le16_to_cpu(dev->descriptor.idProduct));

	hid->bus = BUS_USB;
	hid->vendor = dev->descriptor.idVendor;
	hid->product = dev->descriptor.idProduct;
	hid->vendor = le16_to_cpu(dev->descriptor.idVendor);
	hid->product = le16_to_cpu(dev->descriptor.idProduct);

	usb_make_path(dev, hid->phys, sizeof(hid->phys));
	strlcat(hid->phys, "/input", sizeof(hid->phys));
Loading