History

Merge branch 'upstream' into for-linus

Jiri Kosina committed 14 years ago

Commit 56ccd182 parents b3d07e0 d12570813 files · +307 −32Browse files

Unified · Split

13 files
  1. drivers/hid/Kconfig +6 −0
  2. drivers/hid/Makefile +1 −0
  3. drivers/hid/hid-apple.c +1 −1
  4. drivers/hid/hid-aureal.c +54 −0
  5. drivers/hid/hid-core.c +23 −8
  6. drivers/hid/hid-ids.h +4 −0
  7. drivers/hid/hid-uclogic.c +141 −0
  8. drivers/hid/hidraw.c +13 −6
  9. drivers/hid/usbhid/hid-core.c +55 −10
  10. drivers/hid/usbhid/hiddev.c +5 −4
  11. drivers/hid/usbhid/usbhid.h +1 −0
  12. include/linux/hid.h +1 −1
  13. include/linux/hidraw.h +2 −2
drivers/hid/Kconfig+6−0
@@ -104,6 +104,12 @@ config HID_APPLE · 103 unmodified lines
104104 Say Y here if you want support for keyboards of Apple iBooks, PowerBooks,
105105 MacBooks, MacBook Pros and Apple Aluminum.
106106
107+config HID_AUREAL
108+ tristate "Aureal"
109+ depends on USB_HID
110+ ---help---
111+ Support for Aureal Cy se W-01RN Remote Controller and other Aureal derived remotes.
112+
107113 config HID_BELKIN
108114 tristate "Belkin Flip KVM and Wireless keyboard" if EXPERT
109115 depends on USB_HID
drivers/hid/Makefile+1−0
@@ -38,6 +38,7 @@ endif · 37 unmodified lines
3838 obj-$(CONFIG_HID_A4TECH) += hid-a4tech.o
3939 obj-$(CONFIG_HID_ACRUX) += hid-axff.o
4040 obj-$(CONFIG_HID_APPLE) += hid-apple.o
41+obj-$(CONFIG_HID_AUREAL) += hid-aureal.o
4142 obj-$(CONFIG_HID_BELKIN) += hid-belkin.o
4243 obj-$(CONFIG_HID_CHERRY) += hid-cherry.o
4344 obj-$(CONFIG_HID_CHICONY) += hid-chicony.o
drivers/hid/hid-apple.c+1−1
@@ -234,7 +234,7 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input, · 233 unmodified lines
234234 }
235235 }
236236
237− if (iso_layout) {
237+ if (iso_layout) {
238238 if (asc->quirks & APPLE_ISO_KEYBOARD) {
239239 trans = apple_find_translation(apple_iso_keyboard, usage->code);
240240 if (trans) {
drivers/hid/hid-aureal.c+54−0
@@ -0,0 +1,54 @@
1+/*
2+ * HID driver for Aureal Cy se W-01RN USB_V3.1 devices
3+ *
4+ * Copyright (c) 2010 Franco Catrin <fcatrin@gmail.com>
5+ * Copyright (c) 2010 Ben Cropley <bcropley@internode.on.net>
6+ *
7+ * Based on HID sunplus driver by
8+ * Copyright (c) 1999 Andreas Gal
9+ * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
10+ * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
11+ * Copyright (c) 2006-2007 Jiri Kosina
12+ * Copyright (c) 2007 Paul Walmsley
13+ * Copyright (c) 2008 Jiri Slaby
14+ */
15+#include <linux/device.h>
16+#include <linux/hid.h>
17+#include <linux/module.h>
18+
19+#include "hid-ids.h"
20+
21+static __u8 *aureal_report_fixup(struct hid_device *hdev, __u8 *rdesc,
22+ unsigned int *rsize)
23+{
24+ if (*rsize >= 54 && rdesc[52] == 0x25 && rdesc[53] == 0x01) {
25+ dev_info(&hdev->dev, "fixing Aureal Cy se W-01RN USB_V3.1 report descriptor.\n");
26+ rdesc[53] = 0x65;
27+ } return rdesc;
28+}
29+
30+static const struct hid_device_id aureal_devices[] = {
31+ { HID_USB_DEVICE(USB_VENDOR_ID_AUREAL, USB_DEVICE_ID_AUREAL_W01RN) },
32+ { }
33+};
34+MODULE_DEVICE_TABLE(hid, aureal_devices);
35+
36+static struct hid_driver aureal_driver = {
37+ .name = "aureal",
38+ .id_table = aureal_devices,
39+ .report_fixup = aureal_report_fixup,
40+};
41+
42+static int __init aureal_init(void)
43+{
44+ return hid_register_driver(&aureal_driver);
45+}
46+
47+static void __exit aureal_exit(void)
48+{
49+ hid_unregister_driver(&aureal_driver);
50+}
51+
52+module_init(aureal_init);
53+module_exit(aureal_exit);
54+MODULE_LICENSE("GPL");
drivers/hid/hid-core.c+23−8
@@ -230,9 +230,16 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign · 229 unmodified lines
230230 return -1;
231231 }
232232
233− if (parser->global.logical_maximum < parser->global.logical_minimum) {
234− hid_err(parser->device, "logical range invalid %d %d\n",
235− parser->global.logical_minimum, parser->global.logical_maximum);
233+ /* Handle both signed and unsigned cases properly */
234+ if ((parser->global.logical_minimum < 0 &&
235+ parser->global.logical_maximum <
236+ parser->global.logical_minimum) ||
237+ (parser->global.logical_minimum >= 0 &&
238+ (__u32)parser->global.logical_maximum <
239+ (__u32)parser->global.logical_minimum)) {
240+ dbg_hid("logical range invalid 0x%x 0x%x\n",
241+ parser->global.logical_minimum,
242+ parser->global.logical_maximum);
236243 return -1;
237244 }
238245
@@ -1149,7 +1156,7 @@ static struct hid_report *hid_get_report(struct hid_report_enum *report_enum, · 910 unmodified lines
11491156 return report;
11501157 }
11511158
1152−void hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
1159+int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
11531160 int interrupt)
11541161 {
11551162 struct hid_report_enum *report_enum = hid->report_enum + type;
@@ -1157,10 +1164,11 @@ void hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size, · 1 unmodified line
11571164 unsigned int a;
11581165 int rsize, csize = size;
11591166 u8 *cdata = data;
1167+ int ret = 0;
11601168
11611169 report = hid_get_report(report_enum, data);
11621170 if (!report)
1163− return;
1171+ goto out;
11641172
11651173 if (report_enum->numbered) {
11661174 cdata++;
@@ -1180,14 +1188,19 @@ void hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size, · 13 unmodified lines
11801188
11811189 if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_report_event)
11821190 hid->hiddev_report_event(hid, report);
1183− if (hid->claimed & HID_CLAIMED_HIDRAW)
1184− hidraw_report_event(hid, data, size);
1191+ if (hid->claimed & HID_CLAIMED_HIDRAW) {
1192+ ret = hidraw_report_event(hid, data, size);
1193+ if (ret)
1194+ goto out;
1195+ }
11851196
11861197 for (a = 0; a < report->maxfield; a++)
11871198 hid_input_field(hid, report->field[a], cdata, interrupt);
11881199
11891200 if (hid->claimed & HID_CLAIMED_INPUT)
11901201 hidinput_report_event(hid, report);
1202+out:
1203+ return ret;
11911204 }
11921205 EXPORT_SYMBOL_GPL(hid_report_raw_event);
11931206
@@ -1264,7 +1277,7 @@ nomem: · 70 unmodified lines
12641277 }
12651278 }
12661279
1267− hid_report_raw_event(hid, type, data, size, interrupt);
1280+ ret = hid_report_raw_event(hid, type, data, size, interrupt);
12681281
12691282 unlock:
12701283 up(&hid->driver_lock);
@@ -1496,6 +1509,7 @@ static const struct hid_device_id hid_have_special_driver[] = { · 225 unmodified lines
14961509 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO) },
14971510 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
14981511 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
1512+ { HID_USB_DEVICE(USB_VENDOR_ID_AUREAL, USB_DEVICE_ID_AUREAL_W01RN) },
14991513 { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) },
15001514 { HID_USB_DEVICE(USB_VENDOR_ID_BAANTO, USB_DEVICE_ID_BAANTO_MT_190W2), },
15011515 { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) },
@@ -1631,6 +1645,7 @@ static const struct hid_device_id hid_have_special_driver[] = { · 129 unmodified lines
16311645 { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U) },
16321646 { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U) },
16331647 { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP1062) },
1648+ { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850) },
16341649 { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) },
16351650 { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SUPER_JOY_BOX_3) },
16361651 { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD) },
drivers/hid/hid-ids.h+4−0
@@ -154,6 +154,9 @@ · 153 unmodified lines
154154 #define USB_DEVICE_ID_ATMEL_MULTITOUCH 0x211c
155155 #define USB_DEVICE_ID_ATMEL_MXT_DIGITIZER 0x2118
156156
157+#define USB_VENDOR_ID_AUREAL 0x0755
158+#define USB_DEVICE_ID_AUREAL_W01RN 0x2626
159+
157160 #define USB_VENDOR_ID_AVERMEDIA 0x07ca
158161 #define USB_DEVICE_ID_AVER_FM_MR800 0xb800
159162
@@ -729,6 +732,7 @@ · 569 unmodified lines
729732 #define USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U 0x0004
730733 #define USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U 0x0005
731734 #define USB_DEVICE_ID_UCLOGIC_TABLET_WP1062 0x0064
735+#define USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850 0x0522
732736
733737 #define USB_VENDOR_ID_UNITEC 0x227d
734738 #define USB_DEVICE_ID_UNITEC_USB_TOUCH_0709 0x0709
drivers/hid/hid-uclogic.c+141−0
@@ -14,6 +14,7 @@ · 13 unmodified lines
1414 #include <linux/device.h>
1515 #include <linux/hid.h>
1616 #include <linux/module.h>
17+#include <linux/usb.h>
1718
1819 #include "hid-ids.h"
1920
@@ -352,9 +353,125 @@ static __u8 pf1209_rdesc_fixed[] = { · 332 unmodified lines
352353 0xC0 /* End Collection */
353354 };
354355
356+/*
357+ * See TWHL850 description, device and HID report descriptors at
358+ * http://sf.net/apps/mediawiki/digimend/?title=UC-Logic_Wireless_Tablet_TWHL850
359+ */
360+
361+/* Size of the original descriptors of TWHL850 tablet */
362+#define TWHL850_RDESC_ORIG_SIZE0 182
363+#define TWHL850_RDESC_ORIG_SIZE1 161
364+#define TWHL850_RDESC_ORIG_SIZE2 92
365+
366+/* Fixed PID 0522 tablet report descriptor, interface 0 (stylus) */
367+static __u8 twhl850_rdesc_fixed0[] = {
368+ 0x05, 0x0D, /* Usage Page (Digitizer), */
369+ 0x09, 0x02, /* Usage (Pen), */
370+ 0xA1, 0x01, /* Collection (Application), */
371+ 0x85, 0x09, /* Report ID (9), */
372+ 0x09, 0x20, /* Usage (Stylus), */
373+ 0xA0, /* Collection (Physical), */
374+ 0x14, /* Logical Minimum (0), */
375+ 0x25, 0x01, /* Logical Maximum (1), */
376+ 0x75, 0x01, /* Report Size (1), */
377+ 0x95, 0x03, /* Report Count (3), */
378+ 0x09, 0x42, /* Usage (Tip Switch), */
379+ 0x09, 0x44, /* Usage (Barrel Switch), */
380+ 0x09, 0x46, /* Usage (Tablet Pick), */
381+ 0x81, 0x02, /* Input (Variable), */
382+ 0x81, 0x03, /* Input (Constant, Variable), */
383+ 0x95, 0x01, /* Report Count (1), */
384+ 0x09, 0x32, /* Usage (In Range), */
385+ 0x81, 0x02, /* Input (Variable), */
386+ 0x81, 0x03, /* Input (Constant, Variable), */
387+ 0x75, 0x10, /* Report Size (16), */
388+ 0xA4, /* Push, */
389+ 0x05, 0x01, /* Usage Page (Desktop), */
390+ 0x65, 0x13, /* Unit (Inch), */
391+ 0x55, 0xFD, /* Unit Exponent (-3), */
392+ 0x34, /* Physical Minimum (0), */
393+ 0x09, 0x30, /* Usage (X), */
394+ 0x46, 0x40, 0x1F, /* Physical Maximum (8000), */
395+ 0x26, 0x00, 0x7D, /* Logical Maximum (32000), */
396+ 0x81, 0x02, /* Input (Variable), */
397+ 0x09, 0x31, /* Usage (Y), */
398+ 0x46, 0x88, 0x13, /* Physical Maximum (5000), */
399+ 0x26, 0x20, 0x4E, /* Logical Maximum (20000), */
400+ 0x81, 0x02, /* Input (Variable), */
401+ 0xB4, /* Pop, */
402+ 0x09, 0x30, /* Usage (Tip Pressure), */
403+ 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */
404+ 0x81, 0x02, /* Input (Variable), */
405+ 0xC0, /* End Collection, */
406+ 0xC0 /* End Collection */
407+};
408+
409+/* Fixed PID 0522 tablet report descriptor, interface 1 (mouse) */
410+static __u8 twhl850_rdesc_fixed1[] = {
411+ 0x05, 0x01, /* Usage Page (Desktop), */
412+ 0x09, 0x02, /* Usage (Mouse), */
413+ 0xA1, 0x01, /* Collection (Application), */
414+ 0x85, 0x01, /* Report ID (1), */
415+ 0x09, 0x01, /* Usage (Pointer), */
416+ 0xA0, /* Collection (Physical), */
417+ 0x05, 0x09, /* Usage Page (Button), */
418+ 0x75, 0x01, /* Report Size (1), */
419+ 0x95, 0x03, /* Report Count (3), */
420+ 0x19, 0x01, /* Usage Minimum (01h), */
421+ 0x29, 0x03, /* Usage Maximum (03h), */
422+ 0x14, /* Logical Minimum (0), */
423+ 0x25, 0x01, /* Logical Maximum (1), */
424+ 0x81, 0x02, /* Input (Variable), */
425+ 0x95, 0x05, /* Report Count (5), */
426+ 0x81, 0x03, /* Input (Constant, Variable), */
427+ 0x05, 0x01, /* Usage Page (Desktop), */
428+ 0x09, 0x30, /* Usage (X), */
429+ 0x09, 0x31, /* Usage (Y), */
430+ 0x16, 0x00, 0x80, /* Logical Minimum (-32768), */
431+ 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */
432+ 0x75, 0x10, /* Report Size (16), */
433+ 0x95, 0x02, /* Report Count (2), */
434+ 0x81, 0x06, /* Input (Variable, Relative), */
435+ 0x09, 0x38, /* Usage (Wheel), */
436+ 0x15, 0xFF, /* Logical Minimum (-1), */
437+ 0x25, 0x01, /* Logical Maximum (1), */
438+ 0x95, 0x01, /* Report Count (1), */
439+ 0x75, 0x08, /* Report Size (8), */
440+ 0x81, 0x06, /* Input (Variable, Relative), */
441+ 0x81, 0x03, /* Input (Constant, Variable), */
442+ 0xC0, /* End Collection, */
443+ 0xC0 /* End Collection */
444+};
445+
446+/* Fixed PID 0522 tablet report descriptor, interface 2 (frame buttons) */
447+static __u8 twhl850_rdesc_fixed2[] = {
448+ 0x05, 0x01, /* Usage Page (Desktop), */
449+ 0x09, 0x06, /* Usage (Keyboard), */
450+ 0xA1, 0x01, /* Collection (Application), */
451+ 0x85, 0x03, /* Report ID (3), */
452+ 0x05, 0x07, /* Usage Page (Keyboard), */
453+ 0x14, /* Logical Minimum (0), */
454+ 0x19, 0xE0, /* Usage Minimum (KB Leftcontrol), */
455+ 0x29, 0xE7, /* Usage Maximum (KB Right GUI), */
456+ 0x25, 0x01, /* Logical Maximum (1), */
457+ 0x75, 0x01, /* Report Size (1), */
458+ 0x95, 0x08, /* Report Count (8), */
459+ 0x81, 0x02, /* Input (Variable), */
460+ 0x18, /* Usage Minimum (None), */
461+ 0x29, 0xFF, /* Usage Maximum (FFh), */
462+ 0x26, 0xFF, 0x00, /* Logical Maximum (255), */
463+ 0x75, 0x08, /* Report Size (8), */
464+ 0x95, 0x06, /* Report Count (6), */
465+ 0x80, /* Input, */
466+ 0xC0 /* End Collection */
467+};
468+
355469 static __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc,
356470 unsigned int *rsize)
357471 {
472+ struct usb_interface *iface = to_usb_interface(hdev->dev.parent);
473+ __u8 iface_num = iface->cur_altsetting->desc.bInterfaceNumber;
474+
358475 switch (hdev->product) {
359476 case USB_DEVICE_ID_UCLOGIC_TABLET_PF1209:
360477 if (*rsize == PF1209_RDESC_ORIG_SIZE) {
@@ -386,6 +503,28 @@ static __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc, · 25 unmodified lines
386503 *rsize = sizeof(wp1062_rdesc_fixed);
387504 }
388505 break;
506+ case USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850:
507+ switch (iface_num) {
508+ case 0:
509+ if (*rsize == TWHL850_RDESC_ORIG_SIZE0) {
510+ rdesc = twhl850_rdesc_fixed0;
511+ *rsize = sizeof(twhl850_rdesc_fixed0);
512+ }
513+ break;
514+ case 1:
515+ if (*rsize == TWHL850_RDESC_ORIG_SIZE1) {
516+ rdesc = twhl850_rdesc_fixed1;
517+ *rsize = sizeof(twhl850_rdesc_fixed1);
518+ }
519+ break;
520+ case 2:
521+ if (*rsize == TWHL850_RDESC_ORIG_SIZE2) {
522+ rdesc = twhl850_rdesc_fixed2;
523+ *rsize = sizeof(twhl850_rdesc_fixed2);
524+ }
525+ break;
526+ }
527+ break;
389528 }
390529
391530 return rdesc;
@@ -402,6 +541,8 @@ static const struct hid_device_id uclogic_devices[] = { · 10 unmodified lines
402541 USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U) },
403542 { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC,
404543 USB_DEVICE_ID_UCLOGIC_TABLET_WP1062) },
544+ { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC,
545+ USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850) },
405546 { }
406547 };
407548 MODULE_DEVICE_TABLE(hid, uclogic_devices);
drivers/hid/hidraw.c+13−6
@@ -87,11 +87,13 @@ static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count, · 86 unmodified lines
8787 len = list->buffer[list->tail].len > count ?
8888 count : list->buffer[list->tail].len;
8989
90− if (copy_to_user(buffer, list->buffer[list->tail].value, len)) {
91− ret = -EFAULT;
92− goto out;
90+ if (list->buffer[list->tail].value) {
91+ if (copy_to_user(buffer, list->buffer[list->tail].value, len)) {
92+ ret = -EFAULT;
93+ goto out;
94+ }
95+ ret = len;
9396 }
94− ret = len;
9597
9698 kfree(list->buffer[list->tail].value);
9799 list->tail = (list->tail + 1) & (HIDRAW_BUFFER_SIZE - 1);
@@ -437,19 +439,24 @@ static const struct file_operations hidraw_ops = { · 339 unmodified lines
437439 .llseek = noop_llseek,
438440 };
439441
440−void hidraw_report_event(struct hid_device *hid, u8 *data, int len)
442+int hidraw_report_event(struct hid_device *hid, u8 *data, int len)
441443 {
442444 struct hidraw *dev = hid->hidraw;
443445 struct hidraw_list *list;
446+ int ret = 0;
444447
445448 list_for_each_entry(list, &dev->list, node) {
446− list->buffer[list->head].value = kmemdup(data, len, GFP_ATOMIC);
449+ if (!(list->buffer[list->head].value = kmemdup(data, len, GFP_ATOMIC))) {
450+ ret = -ENOMEM;
451+ break;
452+ }
447453 list->buffer[list->head].len = len;
448454 list->head = (list->head + 1) & (HIDRAW_BUFFER_SIZE - 1);
449455 kill_fasync(&list->fasync, SIGIO, POLL_IN);
450456 }
451457
452458 wake_up_interruptible(&dev->wait);
459+ return ret;
453460 }
454461 EXPORT_SYMBOL_GPL(hidraw_report_event);
455462
drivers/hid/usbhid/hid-core.c+55−10
@@ -28,6 +28,7 @@ · 27 unmodified lines
2828 #include <linux/input.h>
2929 #include <linux/wait.h>
3030 #include <linux/workqueue.h>
31+#include <linux/string.h>
3132
3233 #include <linux/usb.h>
3334
@@ -86,8 +87,13 @@ static int hid_start_in(struct hid_device *hid) · 52 unmodified lines
8687 !test_bit(HID_REPORTED_IDLE, &usbhid->iofl) &&
8788 !test_and_set_bit(HID_IN_RUNNING, &usbhid->iofl)) {
8889 rc = usb_submit_urb(usbhid->urbin, GFP_ATOMIC);
89− if (rc != 0)
90+ if (rc != 0) {
9091 clear_bit(HID_IN_RUNNING, &usbhid->iofl);
92+ if (rc == -ENOSPC)
93+ set_bit(HID_NO_BANDWIDTH, &usbhid->iofl);
94+ } else {
95+ clear_bit(HID_NO_BANDWIDTH, &usbhid->iofl);
96+ }
9197 }
9298 spin_unlock_irqrestore(&usbhid->lock, flags);
9399 return rc;
@@ -173,8 +179,10 @@ static void hid_io_error(struct hid_device *hid) · 79 unmodified lines
173179
174180 if (time_after(jiffies, usbhid->stop_retry)) {
175181
176− /* Retries failed, so do a port reset */
177− if (!test_and_set_bit(HID_RESET_PENDING, &usbhid->iofl)) {
182+ /* Retries failed, so do a port reset unless we lack bandwidth*/
183+ if (test_bit(HID_NO_BANDWIDTH, &usbhid->iofl)
184+ && !test_and_set_bit(HID_RESET_PENDING, &usbhid->iofl)) {
185+
178186 schedule_work(&usbhid->reset_work);
179187 goto done;
180188 }
@@ -700,7 +708,7 @@ static int hid_get_class_descriptor(struct usb_device *dev, int ifnum, · 519 unmodified lines
700708 int usbhid_open(struct hid_device *hid)
701709 {
702710 struct usbhid_device *usbhid = hid->driver_data;
703− int res;
711+ int res = 0;
704712
705713 mutex_lock(&hid_open_mut);
706714 if (!hid->open++) {
@@ -708,17 +716,27 @@ int usbhid_open(struct hid_device *hid) · 1 unmodified line
708716 /* the device must be awake to reliably request remote wakeup */
709717 if (res < 0) {
710718 hid->open--;
711− mutex_unlock(&hid_open_mut);
712− return -EIO;
719+ res = -EIO;
720+ goto done;
713721 }
714722 usbhid->intf->needs_remote_wakeup = 1;
715− if (hid_start_in(hid))
716− hid_io_error(hid);
717−
723+ res = hid_start_in(hid);
724+ if (res) {
725+ if (res != -ENOSPC) {
726+ hid_io_error(hid);
727+ res = 0;
728+ } else {
729+ /* no use opening if resources are insufficient */
730+ hid->open--;
731+ res = -EBUSY;
732+ usbhid->intf->needs_remote_wakeup = 0;
733+ }
734+ }
718735 usb_autopm_put_interface(usbhid->intf);
719736 }
737+done:
720738 mutex_unlock(&hid_open_mut);
721− return 0;
739+ return res;
722740 }
723741
724742 void usbhid_close(struct hid_device *hid)
@@ -1347,7 +1365,34 @@ static int hid_post_reset(struct usb_interface *intf) · 622 unmodified lines
13471365 struct usb_device *dev = interface_to_usbdev (intf);
13481366 struct hid_device *hid = usb_get_intfdata(intf);
13491367 struct usbhid_device *usbhid = hid->driver_data;
1368+ struct usb_host_interface *interface = intf->cur_altsetting;
13501369 int status;
1370+ char *rdesc;
1371+
1372+ /* Fetch and examine the HID report descriptor. If this
1373+ * has changed, then rebind. Since usbcore's check of the
1374+ * configuration descriptors passed, we already know that
1375+ * the size of the HID report descriptor has not changed.
1376+ */
1377+ rdesc = kmalloc(hid->rsize, GFP_KERNEL);
1378+ if (!rdesc) {
1379+ dbg_hid("couldn't allocate rdesc memory (post_reset)\n");
1380+ return 1;
1381+ }
1382+ status = hid_get_class_descriptor(dev,
1383+ interface->desc.bInterfaceNumber,
1384+ HID_DT_REPORT, rdesc, hid->rsize);
1385+ if (status < 0) {
1386+ dbg_hid("reading report descriptor failed (post_reset)\n");
1387+ kfree(rdesc);
1388+ return 1;
1389+ }
1390+ status = memcmp(rdesc, hid->rdesc, hid->rsize);
1391+ kfree(rdesc);
1392+ if (status != 0) {
1393+ dbg_hid("report descriptor changed\n");
1394+ return 1;
1395+ }
13511396
13521397 spin_lock_irq(&usbhid->lock);
13531398 clear_bit(HID_RESET_PENDING, &usbhid->iofl);
drivers/hid/usbhid/hiddev.c+5−4
@@ -34,6 +34,7 @@ · 33 unmodified lines
3434 #include <linux/hid.h>
3535 #include <linux/hiddev.h>
3636 #include <linux/compat.h>
37+#include <linux/vmalloc.h>
3738 #include "usbhid.h"
3839
3940 #ifdef CONFIG_USB_DYNAMIC_MINORS
@@ -250,13 +251,13 @@ static int hiddev_release(struct inode * inode, struct file * file) · 210 unmodified lines
250251 } else {
251252 mutex_unlock(&list->hiddev->existancelock);
252253 kfree(list->hiddev);
253− kfree(list);
254+ vfree(list);
254255 return 0;
255256 }
256257 }
257258
258259 mutex_unlock(&list->hiddev->existancelock);
259− kfree(list);
260+ vfree(list);
260261
261262 return 0;
262263 }
@@ -278,7 +279,7 @@ static int hiddev_open(struct inode *inode, struct file *file) · 15 unmodified lines
278279 hid = usb_get_intfdata(intf);
279280 hiddev = hid->hiddev;
280281
281− if (!(list = kzalloc(sizeof(struct hiddev_list), GFP_KERNEL)))
282+ if (!(list = vzalloc(sizeof(struct hiddev_list))))
282283 return -ENOMEM;
283284 mutex_init(&list->thread_lock);
284285 list->hiddev = hiddev;
@@ -322,7 +323,7 @@ bail_unlock: · 37 unmodified lines
322323 mutex_unlock(&hiddev->existancelock);
323324 bail:
324325 file->private_data = NULL;
325− kfree(list);
326+ vfree(list);
326327 return res;
327328 }
328329
drivers/hid/usbhid/usbhid.h+1−0
@@ -55,6 +55,7 @@ struct usb_interface *usbhid_find_interface(int minor); · 54 unmodified lines
5555 #define HID_STARTED 8
5656 #define HID_REPORTED_IDLE 9
5757 #define HID_KEYS_PRESSED 10
58+#define HID_NO_BANDWIDTH 11
5859
5960 /*
6061 * USB-specific HID struct, to be pointed to
include/linux/hid.h+1−1
@@ -896,7 +896,7 @@ static inline int hid_hw_power(struct hid_device *hdev, int level) · 895 unmodified lines
896896 return hdev->ll_driver->power ? hdev->ll_driver->power(hdev, level) : 0;
897897 }
898898
899−void hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
899+int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
900900 int interrupt);
901901
902902 extern int hid_generic_init(void);
include/linux/hidraw.h+2−2
@@ -76,13 +76,13 @@ struct hidraw_list { · 75 unmodified lines
7676 #ifdef CONFIG_HIDRAW
7777 int hidraw_init(void);
7878 void hidraw_exit(void);
79−void hidraw_report_event(struct hid_device *, u8 *, int);
79+int hidraw_report_event(struct hid_device *, u8 *, int);
8080 int hidraw_connect(struct hid_device *);
8181 void hidraw_disconnect(struct hid_device *);
8282 #else
8383 static inline int hidraw_init(void) { return 0; }
8484 static inline void hidraw_exit(void) { }
85−static inline void hidraw_report_event(struct hid_device *hid, u8 *data, int len) { }
85+static inline int hidraw_report_event(struct hid_device *hid, u8 *data, int len) { return 0; }
8686 static inline int hidraw_connect(struct hid_device *hid) { return -1; }
8787 static inline void hidraw_disconnect(struct hid_device *hid) { }
8888 #endif

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t