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
104 Say Y here if you want support for keyboards of Apple iBooks, PowerBooks,104 Say Y here if you want support for keyboards of Apple iBooks, PowerBooks,
105 MacBooks, MacBook Pros and Apple Aluminum.105 MacBooks, MacBook Pros and Apple Aluminum.
106 106
107config 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
107config HID_BELKIN113config HID_BELKIN
108 tristate "Belkin Flip KVM and Wireless keyboard" if EXPERT114 tristate "Belkin Flip KVM and Wireless keyboard" if EXPERT
109 depends on USB_HID115 depends on USB_HID
drivers/hid/Makefile+1−0
@@ -38,6 +38,7 @@ endif · 37 unmodified lines
38obj-$(CONFIG_HID_A4TECH) += hid-a4tech.o38obj-$(CONFIG_HID_A4TECH) += hid-a4tech.o
39obj-$(CONFIG_HID_ACRUX) += hid-axff.o39obj-$(CONFIG_HID_ACRUX) += hid-axff.o
40obj-$(CONFIG_HID_APPLE) += hid-apple.o40obj-$(CONFIG_HID_APPLE) += hid-apple.o
41obj-$(CONFIG_HID_AUREAL) += hid-aureal.o
41obj-$(CONFIG_HID_BELKIN) += hid-belkin.o42obj-$(CONFIG_HID_BELKIN) += hid-belkin.o
42obj-$(CONFIG_HID_CHERRY) += hid-cherry.o43obj-$(CONFIG_HID_CHERRY) += hid-cherry.o
43obj-$(CONFIG_HID_CHICONY) += hid-chicony.o44obj-$(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
234 }234 }
235 }235 }
236 236
237 if (iso_layout) {237 if (iso_layout) {
238 if (asc->quirks & APPLE_ISO_KEYBOARD) {238 if (asc->quirks & APPLE_ISO_KEYBOARD) {
239 trans = apple_find_translation(apple_iso_keyboard, usage->code);239 trans = apple_find_translation(apple_iso_keyboard, usage->code);
240 if (trans) {240 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
21static __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
30static const struct hid_device_id aureal_devices[] = {
31 { HID_USB_DEVICE(USB_VENDOR_ID_AUREAL, USB_DEVICE_ID_AUREAL_W01RN) },
32 { }
33};
34MODULE_DEVICE_TABLE(hid, aureal_devices);
35
36static struct hid_driver aureal_driver = {
37 .name = "aureal",
38 .id_table = aureal_devices,
39 .report_fixup = aureal_report_fixup,
40};
41
42static int __init aureal_init(void)
43{
44 return hid_register_driver(&aureal_driver);
45}
46
47static void __exit aureal_exit(void)
48{
49 hid_unregister_driver(&aureal_driver);
50}
51
52module_init(aureal_init);
53module_exit(aureal_exit);
54MODULE_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
230 return -1;230 return -1;
231 }231 }
232 232
233 if (parser->global.logical_maximum < parser->global.logical_minimum) {233 /* Handle both signed and unsigned cases properly */
234 hid_err(parser->device, "logical range invalid %d %d\n",234 if ((parser->global.logical_minimum < 0 &&
235 parser->global.logical_minimum, parser->global.logical_maximum);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);
236 return -1;243 return -1;
237 }244 }
238 245
@@ -1149,7 +1156,7 @@ static struct hid_report *hid_get_report(struct hid_report_enum *report_enum, · 910 unmodified lines
1149 return report;1156 return report;
1150}1157}
1151 1158
1152void hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,1159int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
1153 int interrupt)1160 int interrupt)
1154{1161{
1155 struct hid_report_enum *report_enum = hid->report_enum + type;1162 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
1157 unsigned int a;1164 unsigned int a;
1158 int rsize, csize = size;1165 int rsize, csize = size;
1159 u8 *cdata = data;1166 u8 *cdata = data;
1167 int ret = 0;
1160 1168
1161 report = hid_get_report(report_enum, data);1169 report = hid_get_report(report_enum, data);
1162 if (!report)1170 if (!report)
1163 return;1171 goto out;
1164 1172
1165 if (report_enum->numbered) {1173 if (report_enum->numbered) {
1166 cdata++;1174 cdata++;
@@ -1180,14 +1188,19 @@ void hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size, · 13 unmodified lines
1180 1188
1181 if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_report_event)1189 if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_report_event)
1182 hid->hiddev_report_event(hid, report);1190 hid->hiddev_report_event(hid, report);
1183 if (hid->claimed & HID_CLAIMED_HIDRAW)1191 if (hid->claimed & HID_CLAIMED_HIDRAW) {
1184 hidraw_report_event(hid, data, size);1192 ret = hidraw_report_event(hid, data, size);
1193 if (ret)
1194 goto out;
1195 }
1185 1196
1186 for (a = 0; a < report->maxfield; a++)1197 for (a = 0; a < report->maxfield; a++)
1187 hid_input_field(hid, report->field[a], cdata, interrupt);1198 hid_input_field(hid, report->field[a], cdata, interrupt);
1188 1199
1189 if (hid->claimed & HID_CLAIMED_INPUT)1200 if (hid->claimed & HID_CLAIMED_INPUT)
1190 hidinput_report_event(hid, report);1201 hidinput_report_event(hid, report);
1202out:
1203 return ret;
1191}1204}
1192EXPORT_SYMBOL_GPL(hid_report_raw_event);1205EXPORT_SYMBOL_GPL(hid_report_raw_event);
1193 1206
@@ -1264,7 +1277,7 @@ nomem: · 70 unmodified lines
1264 }1277 }
1265 }1278 }
1266 1279
1267 hid_report_raw_event(hid, type, data, size, interrupt);1280 ret = hid_report_raw_event(hid, type, data, size, interrupt);
1268 1281
1269unlock:1282unlock:
1270 up(&hid->driver_lock);1283 up(&hid->driver_lock);
@@ -1496,6 +1509,7 @@ static const struct hid_device_id hid_have_special_driver[] = { · 225 unmodified lines
1496 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO) },1509 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO) },
1497 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },1510 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
1498 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },1511 { 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) },
1499 { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) },1513 { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) },
1500 { HID_USB_DEVICE(USB_VENDOR_ID_BAANTO, USB_DEVICE_ID_BAANTO_MT_190W2), },1514 { HID_USB_DEVICE(USB_VENDOR_ID_BAANTO, USB_DEVICE_ID_BAANTO_MT_190W2), },
1501 { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) },1515 { 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
1631 { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U) },1645 { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U) },
1632 { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U) },1646 { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U) },
1633 { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP1062) },1647 { 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) },
1634 { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) },1649 { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) },
1635 { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SUPER_JOY_BOX_3) },1650 { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SUPER_JOY_BOX_3) },
1636 { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD) },1651 { 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
154#define USB_DEVICE_ID_ATMEL_MULTITOUCH 0x211c154#define USB_DEVICE_ID_ATMEL_MULTITOUCH 0x211c
155#define USB_DEVICE_ID_ATMEL_MXT_DIGITIZER 0x2118155#define USB_DEVICE_ID_ATMEL_MXT_DIGITIZER 0x2118
156 156
157#define USB_VENDOR_ID_AUREAL 0x0755
158#define USB_DEVICE_ID_AUREAL_W01RN 0x2626
159
157#define USB_VENDOR_ID_AVERMEDIA 0x07ca160#define USB_VENDOR_ID_AVERMEDIA 0x07ca
158#define USB_DEVICE_ID_AVER_FM_MR800 0xb800161#define USB_DEVICE_ID_AVER_FM_MR800 0xb800
159 162
@@ -729,6 +732,7 @@ · 569 unmodified lines
729#define USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U 0x0004732#define USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U 0x0004
730#define USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U 0x0005733#define USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U 0x0005
731#define USB_DEVICE_ID_UCLOGIC_TABLET_WP1062 0x0064734#define USB_DEVICE_ID_UCLOGIC_TABLET_WP1062 0x0064
735#define USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850 0x0522
732 736
733#define USB_VENDOR_ID_UNITEC 0x227d737#define USB_VENDOR_ID_UNITEC 0x227d
734#define USB_DEVICE_ID_UNITEC_USB_TOUCH_0709 0x0709738#define USB_DEVICE_ID_UNITEC_USB_TOUCH_0709 0x0709
drivers/hid/hid-uclogic.c+141−0
@@ -14,6 +14,7 @@ · 13 unmodified lines
14#include <linux/device.h>14#include <linux/device.h>
15#include <linux/hid.h>15#include <linux/hid.h>
16#include <linux/module.h>16#include <linux/module.h>
17#include <linux/usb.h>
17 18
18#include "hid-ids.h"19#include "hid-ids.h"
19 20
@@ -352,9 +353,125 @@ static __u8 pf1209_rdesc_fixed[] = { · 332 unmodified lines
352 0xC0 /* End Collection */353 0xC0 /* End Collection */
353};354};
354 355
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) */
367static __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) */
410static __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) */
447static __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
355static __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc,469static __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc,
356 unsigned int *rsize)470 unsigned int *rsize)
357{471{
472 struct usb_interface *iface = to_usb_interface(hdev->dev.parent);
473 __u8 iface_num = iface->cur_altsetting->desc.bInterfaceNumber;
474
358 switch (hdev->product) {475 switch (hdev->product) {
359 case USB_DEVICE_ID_UCLOGIC_TABLET_PF1209:476 case USB_DEVICE_ID_UCLOGIC_TABLET_PF1209:
360 if (*rsize == PF1209_RDESC_ORIG_SIZE) {477 if (*rsize == PF1209_RDESC_ORIG_SIZE) {
@@ -386,6 +503,28 @@ static __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc, · 25 unmodified lines
386 *rsize = sizeof(wp1062_rdesc_fixed);503 *rsize = sizeof(wp1062_rdesc_fixed);
387 }504 }
388 break;505 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;
389 }528 }
390 529
391 return rdesc;530 return rdesc;
@@ -402,6 +541,8 @@ static const struct hid_device_id uclogic_devices[] = { · 10 unmodified lines
402 USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U) },541 USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U) },
403 { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC,542 { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC,
404 USB_DEVICE_ID_UCLOGIC_TABLET_WP1062) },543 USB_DEVICE_ID_UCLOGIC_TABLET_WP1062) },
544 { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC,
545 USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850) },
405 { }546 { }
406};547};
407MODULE_DEVICE_TABLE(hid, uclogic_devices);548MODULE_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
87 len = list->buffer[list->tail].len > count ?87 len = list->buffer[list->tail].len > count ?
88 count : list->buffer[list->tail].len;88 count : list->buffer[list->tail].len;
89 89
90 if (copy_to_user(buffer, list->buffer[list->tail].value, len)) {90 if (list->buffer[list->tail].value) {
91 ret = -EFAULT;91 if (copy_to_user(buffer, list->buffer[list->tail].value, len)) {
92 goto out;92 ret = -EFAULT;
93 goto out;
94 }
95 ret = len;
93 }96 }
94 ret = len;
95 97
96 kfree(list->buffer[list->tail].value);98 kfree(list->buffer[list->tail].value);
97 list->tail = (list->tail + 1) & (HIDRAW_BUFFER_SIZE - 1);99 list->tail = (list->tail + 1) & (HIDRAW_BUFFER_SIZE - 1);
@@ -437,19 +439,24 @@ static const struct file_operations hidraw_ops = { · 339 unmodified lines
437 .llseek = noop_llseek,439 .llseek = noop_llseek,
438};440};
439 441
440void hidraw_report_event(struct hid_device *hid, u8 *data, int len)442int hidraw_report_event(struct hid_device *hid, u8 *data, int len)
441{443{
442 struct hidraw *dev = hid->hidraw;444 struct hidraw *dev = hid->hidraw;
443 struct hidraw_list *list;445 struct hidraw_list *list;
446 int ret = 0;
444 447
445 list_for_each_entry(list, &dev->list, node) {448 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 }
447 list->buffer[list->head].len = len;453 list->buffer[list->head].len = len;
448 list->head = (list->head + 1) & (HIDRAW_BUFFER_SIZE - 1);454 list->head = (list->head + 1) & (HIDRAW_BUFFER_SIZE - 1);
449 kill_fasync(&list->fasync, SIGIO, POLL_IN);455 kill_fasync(&list->fasync, SIGIO, POLL_IN);
450 }456 }
451 457
452 wake_up_interruptible(&dev->wait);458 wake_up_interruptible(&dev->wait);
459 return ret;
453}460}
454EXPORT_SYMBOL_GPL(hidraw_report_event);461EXPORT_SYMBOL_GPL(hidraw_report_event);
455 462
drivers/hid/usbhid/hid-core.c+55−10
@@ -28,6 +28,7 @@ · 27 unmodified lines
28#include <linux/input.h>28#include <linux/input.h>
29#include <linux/wait.h>29#include <linux/wait.h>
30#include <linux/workqueue.h>30#include <linux/workqueue.h>
31#include <linux/string.h>
31 32
32#include <linux/usb.h>33#include <linux/usb.h>
33 34
@@ -86,8 +87,13 @@ static int hid_start_in(struct hid_device *hid) · 52 unmodified lines
86 !test_bit(HID_REPORTED_IDLE, &usbhid->iofl) &&87 !test_bit(HID_REPORTED_IDLE, &usbhid->iofl) &&
87 !test_and_set_bit(HID_IN_RUNNING, &usbhid->iofl)) {88 !test_and_set_bit(HID_IN_RUNNING, &usbhid->iofl)) {
88 rc = usb_submit_urb(usbhid->urbin, GFP_ATOMIC);89 rc = usb_submit_urb(usbhid->urbin, GFP_ATOMIC);
89 if (rc != 0)90 if (rc != 0) {
90 clear_bit(HID_IN_RUNNING, &usbhid->iofl);91 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 }
91 }97 }
92 spin_unlock_irqrestore(&usbhid->lock, flags);98 spin_unlock_irqrestore(&usbhid->lock, flags);
93 return rc;99 return rc;
@@ -173,8 +179,10 @@ static void hid_io_error(struct hid_device *hid) · 79 unmodified lines
173 179
174 if (time_after(jiffies, usbhid->stop_retry)) {180 if (time_after(jiffies, usbhid->stop_retry)) {
175 181
176 /* Retries failed, so do a port reset */182 /* Retries failed, so do a port reset unless we lack bandwidth*/
177 if (!test_and_set_bit(HID_RESET_PENDING, &usbhid->iofl)) {183 if (test_bit(HID_NO_BANDWIDTH, &usbhid->iofl)
184 && !test_and_set_bit(HID_RESET_PENDING, &usbhid->iofl)) {
185
178 schedule_work(&usbhid->reset_work);186 schedule_work(&usbhid->reset_work);
179 goto done;187 goto done;
180 }188 }
@@ -700,7 +708,7 @@ static int hid_get_class_descriptor(struct usb_device *dev, int ifnum, · 519 unmodified lines
700int usbhid_open(struct hid_device *hid)708int usbhid_open(struct hid_device *hid)
701{709{
702 struct usbhid_device *usbhid = hid->driver_data;710 struct usbhid_device *usbhid = hid->driver_data;
703 int res;711 int res = 0;
704 712
705 mutex_lock(&hid_open_mut);713 mutex_lock(&hid_open_mut);
706 if (!hid->open++) {714 if (!hid->open++) {
@@ -708,17 +716,27 @@ int usbhid_open(struct hid_device *hid) · 1 unmodified line
708 /* the device must be awake to reliably request remote wakeup */716 /* the device must be awake to reliably request remote wakeup */
709 if (res < 0) {717 if (res < 0) {
710 hid->open--;718 hid->open--;
711 mutex_unlock(&hid_open_mut);719 res = -EIO;
712 return -EIO;720 goto done;
713 }721 }
714 usbhid->intf->needs_remote_wakeup = 1;722 usbhid->intf->needs_remote_wakeup = 1;
715 if (hid_start_in(hid))723 res = hid_start_in(hid);
716 hid_io_error(hid);724 if (res) {
717 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 }
718 usb_autopm_put_interface(usbhid->intf);735 usb_autopm_put_interface(usbhid->intf);
719 }736 }
737done:
720 mutex_unlock(&hid_open_mut);738 mutex_unlock(&hid_open_mut);
721 return 0;739 return res;
722}740}
723 741
724void usbhid_close(struct hid_device *hid)742void usbhid_close(struct hid_device *hid)
@@ -1347,7 +1365,34 @@ static int hid_post_reset(struct usb_interface *intf) · 622 unmodified lines
1347 struct usb_device *dev = interface_to_usbdev (intf);1365 struct usb_device *dev = interface_to_usbdev (intf);
1348 struct hid_device *hid = usb_get_intfdata(intf);1366 struct hid_device *hid = usb_get_intfdata(intf);
1349 struct usbhid_device *usbhid = hid->driver_data;1367 struct usbhid_device *usbhid = hid->driver_data;
1368 struct usb_host_interface *interface = intf->cur_altsetting;
1350 int status;1369 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 }
1351 1396
1352 spin_lock_irq(&usbhid->lock);1397 spin_lock_irq(&usbhid->lock);
1353 clear_bit(HID_RESET_PENDING, &usbhid->iofl);1398 clear_bit(HID_RESET_PENDING, &usbhid->iofl);
drivers/hid/usbhid/hiddev.c+5−4
@@ -34,6 +34,7 @@ · 33 unmodified lines
34#include <linux/hid.h>34#include <linux/hid.h>
35#include <linux/hiddev.h>35#include <linux/hiddev.h>
36#include <linux/compat.h>36#include <linux/compat.h>
37#include <linux/vmalloc.h>
37#include "usbhid.h"38#include "usbhid.h"
38 39
39#ifdef CONFIG_USB_DYNAMIC_MINORS40#ifdef CONFIG_USB_DYNAMIC_MINORS
@@ -250,13 +251,13 @@ static int hiddev_release(struct inode * inode, struct file * file) · 210 unmodified lines
250 } else {251 } else {
251 mutex_unlock(&list->hiddev->existancelock);252 mutex_unlock(&list->hiddev->existancelock);
252 kfree(list->hiddev);253 kfree(list->hiddev);
253 kfree(list);254 vfree(list);
254 return 0;255 return 0;
255 }256 }
256 }257 }
257 258
258 mutex_unlock(&list->hiddev->existancelock);259 mutex_unlock(&list->hiddev->existancelock);
259 kfree(list);260 vfree(list);
260 261
261 return 0;262 return 0;
262}263}
@@ -278,7 +279,7 @@ static int hiddev_open(struct inode *inode, struct file *file) · 15 unmodified lines
278 hid = usb_get_intfdata(intf);279 hid = usb_get_intfdata(intf);
279 hiddev = hid->hiddev;280 hiddev = hid->hiddev;
280 281
281 if (!(list = kzalloc(sizeof(struct hiddev_list), GFP_KERNEL)))282 if (!(list = vzalloc(sizeof(struct hiddev_list))))
282 return -ENOMEM;283 return -ENOMEM;
283 mutex_init(&list->thread_lock);284 mutex_init(&list->thread_lock);
284 list->hiddev = hiddev;285 list->hiddev = hiddev;
@@ -322,7 +323,7 @@ bail_unlock: · 37 unmodified lines
322 mutex_unlock(&hiddev->existancelock);323 mutex_unlock(&hiddev->existancelock);
323bail:324bail:
324 file->private_data = NULL;325 file->private_data = NULL;
325 kfree(list);326 vfree(list);
326 return res;327 return res;
327}328}
328 329
drivers/hid/usbhid/usbhid.h+1−0
@@ -55,6 +55,7 @@ struct usb_interface *usbhid_find_interface(int minor); · 54 unmodified lines
55#define HID_STARTED 855#define HID_STARTED 8
56#define HID_REPORTED_IDLE 956#define HID_REPORTED_IDLE 9
57#define HID_KEYS_PRESSED 1057#define HID_KEYS_PRESSED 10
58#define HID_NO_BANDWIDTH 11
58 59
59/*60/*
60 * USB-specific HID struct, to be pointed to61 * 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
896 return hdev->ll_driver->power ? hdev->ll_driver->power(hdev, level) : 0;896 return hdev->ll_driver->power ? hdev->ll_driver->power(hdev, level) : 0;
897}897}
898 898
899void hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,899int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
900 int interrupt);900 int interrupt);
901 901
902extern int hid_generic_init(void);902extern int hid_generic_init(void);
include/linux/hidraw.h+2−2
@@ -76,13 +76,13 @@ struct hidraw_list { · 75 unmodified lines
76#ifdef CONFIG_HIDRAW76#ifdef CONFIG_HIDRAW
77int hidraw_init(void);77int hidraw_init(void);
78void hidraw_exit(void);78void hidraw_exit(void);
79void hidraw_report_event(struct hid_device *, u8 *, int);79int hidraw_report_event(struct hid_device *, u8 *, int);
80int hidraw_connect(struct hid_device *);80int hidraw_connect(struct hid_device *);
81void hidraw_disconnect(struct hid_device *);81void hidraw_disconnect(struct hid_device *);
82#else82#else
83static inline int hidraw_init(void) { return 0; }83static inline int hidraw_init(void) { return 0; }
84static inline void hidraw_exit(void) { }84static inline void hidraw_exit(void) { }
85static inline void hidraw_report_event(struct hid_device *hid, u8 *data, int len) { }85static inline int hidraw_report_event(struct hid_device *hid, u8 *data, int len) { return 0; }
86static inline int hidraw_connect(struct hid_device *hid) { return -1; }86static inline int hidraw_connect(struct hid_device *hid) { return -1; }
87static inline void hidraw_disconnect(struct hid_device *hid) { }87static inline void hidraw_disconnect(struct hid_device *hid) { }
88#endif88#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