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

Commit 5884c406 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'upstream-fixes' of master.kernel.org:/pub/scm/linux/kernel/git/jikos/hid

* 'upstream-fixes' of master.kernel.org:/pub/scm/linux/kernel/git/jikos/hid:
  USB HID: hiddev - fix race between hiddev_send_event() and hiddev_release()
  HID: add hooks for getkeycode() and setkeycode() methods
  HID: switch to using input_dev->dev.parent
  USB HID: Logitech wheel 0x046d/0xc294 needs HID_QUIRK_NOGET quirk
  USB HID: usb_buffer_free() cleanup
  USB HID: report descriptor of Cypress USB barcode readers needs fixup
  Bluetooth HID: HIDP - don't initialize force feedback
  USB HID: update CONFIG_USB_HIDINPUT_POWERBOOK description
  HID: add input mappings for non-working keys on Logitech S510 remote
parents ee54d2d8 cdcb44e8
Loading
Loading
Loading
Loading
+96 −5
Original line number Diff line number Diff line
@@ -240,11 +240,94 @@ static inline void hidinput_pb_setup(struct input_dev *input)
}
#endif

static inline int match_scancode(int code, int scancode)
{
	if (scancode == 0)
		return 1;
	return ((code & (HID_USAGE_PAGE | HID_USAGE)) == scancode);
}

static inline int match_keycode(int code, int keycode)
{
	if (keycode == 0)
		return 1;
	return (code == keycode);
}

static struct hid_usage *hidinput_find_key(struct hid_device *hid,
		int scancode, int keycode)
{
	int i, j, k;
	struct hid_report *report;
	struct hid_usage *usage;

	for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) {
		list_for_each_entry(report, &hid->report_enum[k].report_list, list) {
			for (i = 0; i < report->maxfield; i++) {
				for ( j = 0; j < report->field[i]->maxusage; j++) {
					usage = report->field[i]->usage + j;
					if (usage->type == EV_KEY &&
						match_scancode(usage->hid, scancode) &&
						match_keycode(usage->code, keycode))
						return usage;
				}
			}
		}
	}
	return NULL;
}

static int hidinput_getkeycode(struct input_dev *dev, int scancode,
				int *keycode)
{
	struct hid_device *hid = dev->private;
	struct hid_usage *usage;
	
	usage = hidinput_find_key(hid, scancode, 0);
	if (usage) {
		*keycode = usage->code;
		return 0;
	}
	return -EINVAL;
}

static int hidinput_setkeycode(struct input_dev *dev, int scancode,
				int keycode)
{
	struct hid_device *hid = dev->private;
	struct hid_usage *usage;
	int old_keycode;
	
	if (keycode < 0 || keycode > KEY_MAX)
		return -EINVAL;
	
	usage = hidinput_find_key(hid, scancode, 0);
	if (usage) {
		old_keycode = usage->code;
		usage->code = keycode;
		
		clear_bit(old_keycode, dev->keybit);
		set_bit(usage->code, dev->keybit);
#ifdef CONFIG_HID_DEBUG
		printk (KERN_DEBUG "Assigned keycode %d to HID usage code %x\n", keycode, scancode);
#endif
		/* Set the keybit for the old keycode if the old keycode is used
		 * by another key */
		if (hidinput_find_key (hid, 0, old_keycode))
			set_bit(old_keycode, dev->keybit);
		
		return 0;
	}
	
	return -EINVAL;
}


static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field,
				     struct hid_usage *usage)
{
	struct input_dev *input = hidinput->input;
	struct hid_device *device = input->private;
	struct hid_device *device = input_get_drvdata(input);
	int max = 0, code;
	unsigned long *bit = NULL;

@@ -553,6 +636,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
				case 0x1015: map_key_clear(KEY_RECORD);		break;
				case 0x1016: map_key_clear(KEY_PLAYER);		break;
				case 0x1017: map_key_clear(KEY_EJECTCD);	break;
				case 0x1018: map_key_clear(KEY_MEDIA);          break;
				case 0x1019: map_key_clear(KEY_PROG1);		break;
				case 0x101a: map_key_clear(KEY_PROG2);		break;
				case 0x101b: map_key_clear(KEY_PROG3);		break;
@@ -560,9 +644,12 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
				case 0x1020: map_key_clear(KEY_ZOOMOUT);	break;
				case 0x1021: map_key_clear(KEY_ZOOMRESET);	break;
				case 0x1023: map_key_clear(KEY_CLOSE);		break;
				case 0x1027: map_key_clear(KEY_MENU);           break;
				/* this one is marked as 'Rotate' */
				case 0x1028: map_key_clear(KEY_ANGLE);		break;
				case 0x1029: map_key_clear(KEY_SHUFFLE);	break;
				case 0x102a: map_key_clear(KEY_BACK);           break;
				case 0x102b: map_key_clear(KEY_CYCLEWINDOWS);   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;
@@ -855,13 +942,15 @@ EXPORT_SYMBOL_GPL(hidinput_find_field);

static int hidinput_open(struct input_dev *dev)
{
	struct hid_device *hid = dev->private;
	struct hid_device *hid = input_get_drvdata(dev);

	return hid->hid_open(hid);
}

static void hidinput_close(struct input_dev *dev)
{
	struct hid_device *hid = dev->private;
	struct hid_device *hid = input_get_drvdata(dev);

	hid->hid_close(hid);
}

@@ -909,10 +998,12 @@ int hidinput_connect(struct hid_device *hid)
					return -1;
				}

				input_dev->private = hid;
				input_set_drvdata(input_dev, hid);
				input_dev->event = hid->hidinput_input_event;
				input_dev->open = hidinput_open;
				input_dev->close = hidinput_close;
				input_dev->setkeycode = hidinput_setkeycode;
				input_dev->getkeycode = hidinput_getkeycode;

				input_dev->name = hid->name;
				input_dev->phys = hid->phys;
@@ -921,7 +1012,7 @@ int hidinput_connect(struct hid_device *hid)
				input_dev->id.vendor  = hid->vendor;
				input_dev->id.product = hid->product;
				input_dev->id.version = hid->version;
				input_dev->cdev.dev = hid->dev;
				input_dev->dev.parent = hid->dev;
				hidinput->input = input_dev;
				list_add_tail(&hidinput->list, &hid->inputs);
			}
+2 −2
Original line number Diff line number Diff line
@@ -25,12 +25,12 @@ comment "Input core support is needed for USB HID input layer or HIDBP support"
	depends on USB_HID && INPUT=n

config USB_HIDINPUT_POWERBOOK
	bool "Enable support for iBook/PowerBook special keys"
	bool "Enable support for iBook/PowerBook/MacBook/MacBookPro special keys"
	default n
	depends on USB_HID
	help
	  Say Y here if you want support for the special keys (Fn, Numlock) on
	  Apple iBooks and PowerBooks.
	  Apple iBooks, PowerBooks, MacBooks and MacBook Pros.

	  If unsure, say N.

+32 −9
Original line number Diff line number Diff line
@@ -446,7 +446,7 @@ void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, uns

static int usb_hidinput_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
{
	struct hid_device *hid = dev->private;
	struct hid_device *hid = input_get_drvdata(dev);
	struct hid_field *field;
	int offset;

@@ -626,13 +626,9 @@ static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid)
{
	struct usbhid_device *usbhid = hid->driver_data;

	if (usbhid->inbuf)
	usb_buffer_free(dev, usbhid->bufsize, usbhid->inbuf, usbhid->inbuf_dma);
	if (usbhid->outbuf)
	usb_buffer_free(dev, usbhid->bufsize, usbhid->outbuf, usbhid->outbuf_dma);
	if (usbhid->cr)
	usb_buffer_free(dev, sizeof(*(usbhid->cr)), usbhid->cr, usbhid->cr_dma);
	if (usbhid->ctrlbuf)
	usb_buffer_free(dev, usbhid->bufsize, usbhid->ctrlbuf, usbhid->ctrlbuf_dma);
}

@@ -692,6 +688,30 @@ static void hid_fixup_logitech_descriptor(unsigned char *rdesc, int rsize)
	}
}

/*
 * Some USB barcode readers from cypress have usage min and usage max in
 * the wrong order
 */
static void hid_fixup_cypress_descriptor(unsigned char *rdesc, int rsize)
{
	short fixed = 0;
	int i;

	for (i = 0; i < rsize - 4; i++) {
		if (rdesc[i] == 0x29 && rdesc [i+2] == 0x19) {
			unsigned char tmp;

			rdesc[i] = 0x19; rdesc[i+2] = 0x29;
			tmp = rdesc[i+3];
			rdesc[i+3] = rdesc[i+1];
			rdesc[i+1] = tmp;
		}
	}

	if (fixed)
		info("Fixing up Cypress report descriptor");
}

static struct hid_device *usb_hid_configure(struct usb_interface *intf)
{
	struct usb_host_interface *interface = intf->cur_altsetting;
@@ -758,6 +778,9 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
	if (quirks & HID_QUIRK_LOGITECH_DESCRIPTOR)
		hid_fixup_logitech_descriptor(rdesc, rsize);

	if (quirks & HID_QUIRK_SWAPPED_MIN_MAX)
		hid_fixup_cypress_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++)
+1 −1
Original line number Diff line number Diff line
@@ -60,7 +60,7 @@ static const struct dev_type devices[] = {

static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *effect)
{
	struct hid_device *hid = dev->private;
	struct hid_device *hid = input_get_drvdata(dev);
	struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
	struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
	int x, y;
+1 −1
Original line number Diff line number Diff line
@@ -37,7 +37,7 @@ struct plff_device {
static int hid_plff_play(struct input_dev *dev, void *data,
			 struct ff_effect *effect)
{
	struct hid_device *hid = dev->private;
	struct hid_device *hid = input_get_drvdata(dev);
	struct plff_device *plff = data;
	int left, right;

Loading