Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'upstream' into for-linus

Conflicts:
drivers/hid/hid-core.c

+307 -32
+6
drivers/hid/Kconfig
··· 104 104 Say Y here if you want support for keyboards of Apple iBooks, PowerBooks, 105 105 MacBooks, MacBook Pros and Apple Aluminum. 106 106 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 + 107 113 config HID_BELKIN 108 114 tristate "Belkin Flip KVM and Wireless keyboard" if EXPERT 109 115 depends on USB_HID
+1
drivers/hid/Makefile
··· 38 38 obj-$(CONFIG_HID_A4TECH) += hid-a4tech.o 39 39 obj-$(CONFIG_HID_ACRUX) += hid-axff.o 40 40 obj-$(CONFIG_HID_APPLE) += hid-apple.o 41 + obj-$(CONFIG_HID_AUREAL) += hid-aureal.o 41 42 obj-$(CONFIG_HID_BELKIN) += hid-belkin.o 42 43 obj-$(CONFIG_HID_CHERRY) += hid-cherry.o 43 44 obj-$(CONFIG_HID_CHICONY) += hid-chicony.o
+1 -1
drivers/hid/hid-apple.c
··· 234 234 } 235 235 } 236 236 237 - if (iso_layout) { 237 + if (iso_layout) { 238 238 if (asc->quirks & APPLE_ISO_KEYBOARD) { 239 239 trans = apple_find_translation(apple_iso_keyboard, usage->code); 240 240 if (trans) {
+54
drivers/hid/hid-aureal.c
··· 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");
+23 -8
drivers/hid/hid-core.c
··· 230 230 return -1; 231 231 } 232 232 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); 236 243 return -1; 237 244 } 238 245 ··· 1156 1149 return report; 1157 1150 } 1158 1151 1159 - void hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size, 1152 + int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size, 1160 1153 int interrupt) 1161 1154 { 1162 1155 struct hid_report_enum *report_enum = hid->report_enum + type; ··· 1164 1157 unsigned int a; 1165 1158 int rsize, csize = size; 1166 1159 u8 *cdata = data; 1160 + int ret = 0; 1167 1161 1168 1162 report = hid_get_report(report_enum, data); 1169 1163 if (!report) 1170 - return; 1164 + goto out; 1171 1165 1172 1166 if (report_enum->numbered) { 1173 1167 cdata++; ··· 1188 1180 1189 1181 if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_report_event) 1190 1182 hid->hiddev_report_event(hid, report); 1191 - if (hid->claimed & HID_CLAIMED_HIDRAW) 1192 - hidraw_report_event(hid, data, size); 1183 + if (hid->claimed & HID_CLAIMED_HIDRAW) { 1184 + ret = hidraw_report_event(hid, data, size); 1185 + if (ret) 1186 + goto out; 1187 + } 1193 1188 1194 1189 for (a = 0; a < report->maxfield; a++) 1195 1190 hid_input_field(hid, report->field[a], cdata, interrupt); 1196 1191 1197 1192 if (hid->claimed & HID_CLAIMED_INPUT) 1198 1193 hidinput_report_event(hid, report); 1194 + out: 1195 + return ret; 1199 1196 } 1200 1197 EXPORT_SYMBOL_GPL(hid_report_raw_event); 1201 1198 ··· 1277 1264 } 1278 1265 } 1279 1266 1280 - hid_report_raw_event(hid, type, data, size, interrupt); 1267 + ret = hid_report_raw_event(hid, type, data, size, interrupt); 1281 1268 1282 1269 unlock: 1283 1270 up(&hid->driver_lock); ··· 1509 1496 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO) }, 1510 1497 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, 1511 1498 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, 1499 + { HID_USB_DEVICE(USB_VENDOR_ID_AUREAL, USB_DEVICE_ID_AUREAL_W01RN) }, 1512 1500 { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) }, 1513 1501 { HID_USB_DEVICE(USB_VENDOR_ID_BAANTO, USB_DEVICE_ID_BAANTO_MT_190W2), }, 1514 1502 { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) }, ··· 1645 1631 { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U) }, 1646 1632 { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U) }, 1647 1633 { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP1062) }, 1634 + { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850) }, 1648 1635 { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) }, 1649 1636 { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SUPER_JOY_BOX_3) }, 1650 1637 { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD) },
+4
drivers/hid/hid-ids.h
··· 154 154 #define USB_DEVICE_ID_ATMEL_MULTITOUCH 0x211c 155 155 #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 160 #define USB_VENDOR_ID_AVERMEDIA 0x07ca 158 161 #define USB_DEVICE_ID_AVER_FM_MR800 0xb800 159 162 ··· 732 729 #define USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U 0x0004 733 730 #define USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U 0x0005 734 731 #define USB_DEVICE_ID_UCLOGIC_TABLET_WP1062 0x0064 732 + #define USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850 0x0522 735 733 736 734 #define USB_VENDOR_ID_UNITEC 0x227d 737 735 #define USB_DEVICE_ID_UNITEC_USB_TOUCH_0709 0x0709
+141
drivers/hid/hid-uclogic.c
··· 14 14 #include <linux/device.h> 15 15 #include <linux/hid.h> 16 16 #include <linux/module.h> 17 + #include <linux/usb.h> 17 18 18 19 #include "hid-ids.h" 19 20 ··· 353 352 0xC0 /* End Collection */ 354 353 }; 355 354 355 + /* 356 + * See TWHL850 description, device and HID report descriptors at 357 + * http://sf.net/apps/mediawiki/digimend/?title=UC-Logic_Wireless_Tablet_TWHL850 358 + */ 359 + 360 + /* Size of the original descriptors of TWHL850 tablet */ 361 + #define TWHL850_RDESC_ORIG_SIZE0 182 362 + #define TWHL850_RDESC_ORIG_SIZE1 161 363 + #define TWHL850_RDESC_ORIG_SIZE2 92 364 + 365 + /* Fixed PID 0522 tablet report descriptor, interface 0 (stylus) */ 366 + static __u8 twhl850_rdesc_fixed0[] = { 367 + 0x05, 0x0D, /* Usage Page (Digitizer), */ 368 + 0x09, 0x02, /* Usage (Pen), */ 369 + 0xA1, 0x01, /* Collection (Application), */ 370 + 0x85, 0x09, /* Report ID (9), */ 371 + 0x09, 0x20, /* Usage (Stylus), */ 372 + 0xA0, /* Collection (Physical), */ 373 + 0x14, /* Logical Minimum (0), */ 374 + 0x25, 0x01, /* Logical Maximum (1), */ 375 + 0x75, 0x01, /* Report Size (1), */ 376 + 0x95, 0x03, /* Report Count (3), */ 377 + 0x09, 0x42, /* Usage (Tip Switch), */ 378 + 0x09, 0x44, /* Usage (Barrel Switch), */ 379 + 0x09, 0x46, /* Usage (Tablet Pick), */ 380 + 0x81, 0x02, /* Input (Variable), */ 381 + 0x81, 0x03, /* Input (Constant, Variable), */ 382 + 0x95, 0x01, /* Report Count (1), */ 383 + 0x09, 0x32, /* Usage (In Range), */ 384 + 0x81, 0x02, /* Input (Variable), */ 385 + 0x81, 0x03, /* Input (Constant, Variable), */ 386 + 0x75, 0x10, /* Report Size (16), */ 387 + 0xA4, /* Push, */ 388 + 0x05, 0x01, /* Usage Page (Desktop), */ 389 + 0x65, 0x13, /* Unit (Inch), */ 390 + 0x55, 0xFD, /* Unit Exponent (-3), */ 391 + 0x34, /* Physical Minimum (0), */ 392 + 0x09, 0x30, /* Usage (X), */ 393 + 0x46, 0x40, 0x1F, /* Physical Maximum (8000), */ 394 + 0x26, 0x00, 0x7D, /* Logical Maximum (32000), */ 395 + 0x81, 0x02, /* Input (Variable), */ 396 + 0x09, 0x31, /* Usage (Y), */ 397 + 0x46, 0x88, 0x13, /* Physical Maximum (5000), */ 398 + 0x26, 0x20, 0x4E, /* Logical Maximum (20000), */ 399 + 0x81, 0x02, /* Input (Variable), */ 400 + 0xB4, /* Pop, */ 401 + 0x09, 0x30, /* Usage (Tip Pressure), */ 402 + 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ 403 + 0x81, 0x02, /* Input (Variable), */ 404 + 0xC0, /* End Collection, */ 405 + 0xC0 /* End Collection */ 406 + }; 407 + 408 + /* Fixed PID 0522 tablet report descriptor, interface 1 (mouse) */ 409 + static __u8 twhl850_rdesc_fixed1[] = { 410 + 0x05, 0x01, /* Usage Page (Desktop), */ 411 + 0x09, 0x02, /* Usage (Mouse), */ 412 + 0xA1, 0x01, /* Collection (Application), */ 413 + 0x85, 0x01, /* Report ID (1), */ 414 + 0x09, 0x01, /* Usage (Pointer), */ 415 + 0xA0, /* Collection (Physical), */ 416 + 0x05, 0x09, /* Usage Page (Button), */ 417 + 0x75, 0x01, /* Report Size (1), */ 418 + 0x95, 0x03, /* Report Count (3), */ 419 + 0x19, 0x01, /* Usage Minimum (01h), */ 420 + 0x29, 0x03, /* Usage Maximum (03h), */ 421 + 0x14, /* Logical Minimum (0), */ 422 + 0x25, 0x01, /* Logical Maximum (1), */ 423 + 0x81, 0x02, /* Input (Variable), */ 424 + 0x95, 0x05, /* Report Count (5), */ 425 + 0x81, 0x03, /* Input (Constant, Variable), */ 426 + 0x05, 0x01, /* Usage Page (Desktop), */ 427 + 0x09, 0x30, /* Usage (X), */ 428 + 0x09, 0x31, /* Usage (Y), */ 429 + 0x16, 0x00, 0x80, /* Logical Minimum (-32768), */ 430 + 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ 431 + 0x75, 0x10, /* Report Size (16), */ 432 + 0x95, 0x02, /* Report Count (2), */ 433 + 0x81, 0x06, /* Input (Variable, Relative), */ 434 + 0x09, 0x38, /* Usage (Wheel), */ 435 + 0x15, 0xFF, /* Logical Minimum (-1), */ 436 + 0x25, 0x01, /* Logical Maximum (1), */ 437 + 0x95, 0x01, /* Report Count (1), */ 438 + 0x75, 0x08, /* Report Size (8), */ 439 + 0x81, 0x06, /* Input (Variable, Relative), */ 440 + 0x81, 0x03, /* Input (Constant, Variable), */ 441 + 0xC0, /* End Collection, */ 442 + 0xC0 /* End Collection */ 443 + }; 444 + 445 + /* Fixed PID 0522 tablet report descriptor, interface 2 (frame buttons) */ 446 + static __u8 twhl850_rdesc_fixed2[] = { 447 + 0x05, 0x01, /* Usage Page (Desktop), */ 448 + 0x09, 0x06, /* Usage (Keyboard), */ 449 + 0xA1, 0x01, /* Collection (Application), */ 450 + 0x85, 0x03, /* Report ID (3), */ 451 + 0x05, 0x07, /* Usage Page (Keyboard), */ 452 + 0x14, /* Logical Minimum (0), */ 453 + 0x19, 0xE0, /* Usage Minimum (KB Leftcontrol), */ 454 + 0x29, 0xE7, /* Usage Maximum (KB Right GUI), */ 455 + 0x25, 0x01, /* Logical Maximum (1), */ 456 + 0x75, 0x01, /* Report Size (1), */ 457 + 0x95, 0x08, /* Report Count (8), */ 458 + 0x81, 0x02, /* Input (Variable), */ 459 + 0x18, /* Usage Minimum (None), */ 460 + 0x29, 0xFF, /* Usage Maximum (FFh), */ 461 + 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 462 + 0x75, 0x08, /* Report Size (8), */ 463 + 0x95, 0x06, /* Report Count (6), */ 464 + 0x80, /* Input, */ 465 + 0xC0 /* End Collection */ 466 + }; 467 + 356 468 static __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc, 357 469 unsigned int *rsize) 358 470 { 471 + struct usb_interface *iface = to_usb_interface(hdev->dev.parent); 472 + __u8 iface_num = iface->cur_altsetting->desc.bInterfaceNumber; 473 + 359 474 switch (hdev->product) { 360 475 case USB_DEVICE_ID_UCLOGIC_TABLET_PF1209: 361 476 if (*rsize == PF1209_RDESC_ORIG_SIZE) { ··· 503 386 *rsize = sizeof(wp1062_rdesc_fixed); 504 387 } 505 388 break; 389 + case USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850: 390 + switch (iface_num) { 391 + case 0: 392 + if (*rsize == TWHL850_RDESC_ORIG_SIZE0) { 393 + rdesc = twhl850_rdesc_fixed0; 394 + *rsize = sizeof(twhl850_rdesc_fixed0); 395 + } 396 + break; 397 + case 1: 398 + if (*rsize == TWHL850_RDESC_ORIG_SIZE1) { 399 + rdesc = twhl850_rdesc_fixed1; 400 + *rsize = sizeof(twhl850_rdesc_fixed1); 401 + } 402 + break; 403 + case 2: 404 + if (*rsize == TWHL850_RDESC_ORIG_SIZE2) { 405 + rdesc = twhl850_rdesc_fixed2; 406 + *rsize = sizeof(twhl850_rdesc_fixed2); 407 + } 408 + break; 409 + } 410 + break; 506 411 } 507 412 508 413 return rdesc; ··· 541 402 USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U) }, 542 403 { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, 543 404 USB_DEVICE_ID_UCLOGIC_TABLET_WP1062) }, 405 + { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, 406 + USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850) }, 544 407 { } 545 408 }; 546 409 MODULE_DEVICE_TABLE(hid, uclogic_devices);
+13 -6
drivers/hid/hidraw.c
··· 87 87 len = list->buffer[list->tail].len > count ? 88 88 count : list->buffer[list->tail].len; 89 89 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; 93 96 } 94 - ret = len; 95 97 96 98 kfree(list->buffer[list->tail].value); 97 99 list->tail = (list->tail + 1) & (HIDRAW_BUFFER_SIZE - 1); ··· 439 437 .llseek = noop_llseek, 440 438 }; 441 439 442 - void hidraw_report_event(struct hid_device *hid, u8 *data, int len) 440 + int hidraw_report_event(struct hid_device *hid, u8 *data, int len) 443 441 { 444 442 struct hidraw *dev = hid->hidraw; 445 443 struct hidraw_list *list; 444 + int ret = 0; 446 445 447 446 list_for_each_entry(list, &dev->list, node) { 448 - list->buffer[list->head].value = kmemdup(data, len, GFP_ATOMIC); 447 + if (!(list->buffer[list->head].value = kmemdup(data, len, GFP_ATOMIC))) { 448 + ret = -ENOMEM; 449 + break; 450 + } 449 451 list->buffer[list->head].len = len; 450 452 list->head = (list->head + 1) & (HIDRAW_BUFFER_SIZE - 1); 451 453 kill_fasync(&list->fasync, SIGIO, POLL_IN); 452 454 } 453 455 454 456 wake_up_interruptible(&dev->wait); 457 + return ret; 455 458 } 456 459 EXPORT_SYMBOL_GPL(hidraw_report_event); 457 460
+55 -10
drivers/hid/usbhid/hid-core.c
··· 28 28 #include <linux/input.h> 29 29 #include <linux/wait.h> 30 30 #include <linux/workqueue.h> 31 + #include <linux/string.h> 31 32 32 33 #include <linux/usb.h> 33 34 ··· 87 86 !test_bit(HID_REPORTED_IDLE, &usbhid->iofl) && 88 87 !test_and_set_bit(HID_IN_RUNNING, &usbhid->iofl)) { 89 88 rc = usb_submit_urb(usbhid->urbin, GFP_ATOMIC); 90 - if (rc != 0) 89 + if (rc != 0) { 91 90 clear_bit(HID_IN_RUNNING, &usbhid->iofl); 91 + if (rc == -ENOSPC) 92 + set_bit(HID_NO_BANDWIDTH, &usbhid->iofl); 93 + } else { 94 + clear_bit(HID_NO_BANDWIDTH, &usbhid->iofl); 95 + } 92 96 } 93 97 spin_unlock_irqrestore(&usbhid->lock, flags); 94 98 return rc; ··· 179 173 180 174 if (time_after(jiffies, usbhid->stop_retry)) { 181 175 182 - /* Retries failed, so do a port reset */ 183 - if (!test_and_set_bit(HID_RESET_PENDING, &usbhid->iofl)) { 176 + /* Retries failed, so do a port reset unless we lack bandwidth*/ 177 + if (test_bit(HID_NO_BANDWIDTH, &usbhid->iofl) 178 + && !test_and_set_bit(HID_RESET_PENDING, &usbhid->iofl)) { 179 + 184 180 schedule_work(&usbhid->reset_work); 185 181 goto done; 186 182 } ··· 708 700 int usbhid_open(struct hid_device *hid) 709 701 { 710 702 struct usbhid_device *usbhid = hid->driver_data; 711 - int res; 703 + int res = 0; 712 704 713 705 mutex_lock(&hid_open_mut); 714 706 if (!hid->open++) { ··· 716 708 /* the device must be awake to reliably request remote wakeup */ 717 709 if (res < 0) { 718 710 hid->open--; 719 - mutex_unlock(&hid_open_mut); 720 - return -EIO; 711 + res = -EIO; 712 + goto done; 721 713 } 722 714 usbhid->intf->needs_remote_wakeup = 1; 723 - if (hid_start_in(hid)) 724 - hid_io_error(hid); 725 - 715 + res = hid_start_in(hid); 716 + if (res) { 717 + if (res != -ENOSPC) { 718 + hid_io_error(hid); 719 + res = 0; 720 + } else { 721 + /* no use opening if resources are insufficient */ 722 + hid->open--; 723 + res = -EBUSY; 724 + usbhid->intf->needs_remote_wakeup = 0; 725 + } 726 + } 726 727 usb_autopm_put_interface(usbhid->intf); 727 728 } 729 + done: 728 730 mutex_unlock(&hid_open_mut); 729 - return 0; 731 + return res; 730 732 } 731 733 732 734 void usbhid_close(struct hid_device *hid) ··· 1365 1347 struct usb_device *dev = interface_to_usbdev (intf); 1366 1348 struct hid_device *hid = usb_get_intfdata(intf); 1367 1349 struct usbhid_device *usbhid = hid->driver_data; 1350 + struct usb_host_interface *interface = intf->cur_altsetting; 1368 1351 int status; 1352 + char *rdesc; 1353 + 1354 + /* Fetch and examine the HID report descriptor. If this 1355 + * has changed, then rebind. Since usbcore's check of the 1356 + * configuration descriptors passed, we already know that 1357 + * the size of the HID report descriptor has not changed. 1358 + */ 1359 + rdesc = kmalloc(hid->rsize, GFP_KERNEL); 1360 + if (!rdesc) { 1361 + dbg_hid("couldn't allocate rdesc memory (post_reset)\n"); 1362 + return 1; 1363 + } 1364 + status = hid_get_class_descriptor(dev, 1365 + interface->desc.bInterfaceNumber, 1366 + HID_DT_REPORT, rdesc, hid->rsize); 1367 + if (status < 0) { 1368 + dbg_hid("reading report descriptor failed (post_reset)\n"); 1369 + kfree(rdesc); 1370 + return 1; 1371 + } 1372 + status = memcmp(rdesc, hid->rdesc, hid->rsize); 1373 + kfree(rdesc); 1374 + if (status != 0) { 1375 + dbg_hid("report descriptor changed\n"); 1376 + return 1; 1377 + } 1369 1378 1370 1379 spin_lock_irq(&usbhid->lock); 1371 1380 clear_bit(HID_RESET_PENDING, &usbhid->iofl);
+5 -4
drivers/hid/usbhid/hiddev.c
··· 34 34 #include <linux/hid.h> 35 35 #include <linux/hiddev.h> 36 36 #include <linux/compat.h> 37 + #include <linux/vmalloc.h> 37 38 #include "usbhid.h" 38 39 39 40 #ifdef CONFIG_USB_DYNAMIC_MINORS ··· 251 250 } else { 252 251 mutex_unlock(&list->hiddev->existancelock); 253 252 kfree(list->hiddev); 254 - kfree(list); 253 + vfree(list); 255 254 return 0; 256 255 } 257 256 } 258 257 259 258 mutex_unlock(&list->hiddev->existancelock); 260 - kfree(list); 259 + vfree(list); 261 260 262 261 return 0; 263 262 } ··· 279 278 hid = usb_get_intfdata(intf); 280 279 hiddev = hid->hiddev; 281 280 282 - if (!(list = kzalloc(sizeof(struct hiddev_list), GFP_KERNEL))) 281 + if (!(list = vzalloc(sizeof(struct hiddev_list)))) 283 282 return -ENOMEM; 284 283 mutex_init(&list->thread_lock); 285 284 list->hiddev = hiddev; ··· 323 322 mutex_unlock(&hiddev->existancelock); 324 323 bail: 325 324 file->private_data = NULL; 326 - kfree(list); 325 + vfree(list); 327 326 return res; 328 327 } 329 328
+1
drivers/hid/usbhid/usbhid.h
··· 55 55 #define HID_STARTED 8 56 56 #define HID_REPORTED_IDLE 9 57 57 #define HID_KEYS_PRESSED 10 58 + #define HID_NO_BANDWIDTH 11 58 59 59 60 /* 60 61 * USB-specific HID struct, to be pointed to
+1 -1
include/linux/hid.h
··· 896 896 return hdev->ll_driver->power ? hdev->ll_driver->power(hdev, level) : 0; 897 897 } 898 898 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, 900 900 int interrupt); 901 901 902 902 extern int hid_generic_init(void);
+2 -2
include/linux/hidraw.h
··· 76 76 #ifdef CONFIG_HIDRAW 77 77 int hidraw_init(void); 78 78 void hidraw_exit(void); 79 - void hidraw_report_event(struct hid_device *, u8 *, int); 79 + int hidraw_report_event(struct hid_device *, u8 *, int); 80 80 int hidraw_connect(struct hid_device *); 81 81 void hidraw_disconnect(struct hid_device *); 82 82 #else 83 83 static inline int hidraw_init(void) { return 0; } 84 84 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; } 86 86 static inline int hidraw_connect(struct hid_device *hid) { return -1; } 87 87 static inline void hidraw_disconnect(struct hid_device *hid) { } 88 88 #endif