diff options
Diffstat (limited to 'drivers/hid/usbhid/hid-core.c')
-rw-r--r-- | drivers/hid/usbhid/hid-core.c | 42 |
1 files changed, 33 insertions, 9 deletions
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index e2997a8d5e1b..56d06cd8075b 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c | |||
@@ -5,7 +5,7 @@ | |||
5 | * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> | 5 | * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> |
6 | * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc | 6 | * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc |
7 | * Copyright (c) 2007-2008 Oliver Neukum | 7 | * Copyright (c) 2007-2008 Oliver Neukum |
8 | * Copyright (c) 2006-2009 Jiri Kosina | 8 | * Copyright (c) 2006-2010 Jiri Kosina |
9 | */ | 9 | */ |
10 | 10 | ||
11 | /* | 11 | /* |
@@ -316,6 +316,7 @@ static int hid_submit_out(struct hid_device *hid) | |||
316 | err_hid("usb_submit_urb(out) failed"); | 316 | err_hid("usb_submit_urb(out) failed"); |
317 | return -1; | 317 | return -1; |
318 | } | 318 | } |
319 | usbhid->last_out = jiffies; | ||
319 | } else { | 320 | } else { |
320 | /* | 321 | /* |
321 | * queue work to wake up the device. | 322 | * queue work to wake up the device. |
@@ -377,6 +378,7 @@ static int hid_submit_ctrl(struct hid_device *hid) | |||
377 | err_hid("usb_submit_urb(ctrl) failed"); | 378 | err_hid("usb_submit_urb(ctrl) failed"); |
378 | return -1; | 379 | return -1; |
379 | } | 380 | } |
381 | usbhid->last_ctrl = jiffies; | ||
380 | } else { | 382 | } else { |
381 | /* | 383 | /* |
382 | * queue work to wake up the device. | 384 | * queue work to wake up the device. |
@@ -512,9 +514,20 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re | |||
512 | usbhid->out[usbhid->outhead].report = report; | 514 | usbhid->out[usbhid->outhead].report = report; |
513 | usbhid->outhead = head; | 515 | usbhid->outhead = head; |
514 | 516 | ||
515 | if (!test_and_set_bit(HID_OUT_RUNNING, &usbhid->iofl)) | 517 | if (!test_and_set_bit(HID_OUT_RUNNING, &usbhid->iofl)) { |
516 | if (hid_submit_out(hid)) | 518 | if (hid_submit_out(hid)) |
517 | clear_bit(HID_OUT_RUNNING, &usbhid->iofl); | 519 | clear_bit(HID_OUT_RUNNING, &usbhid->iofl); |
520 | } else { | ||
521 | /* | ||
522 | * the queue is known to run | ||
523 | * but an earlier request may be stuck | ||
524 | * we may need to time out | ||
525 | * no race because this is called under | ||
526 | * spinlock | ||
527 | */ | ||
528 | if (time_after(jiffies, usbhid->last_out + HZ * 5)) | ||
529 | usb_unlink_urb(usbhid->urbout); | ||
530 | } | ||
518 | return; | 531 | return; |
519 | } | 532 | } |
520 | 533 | ||
@@ -535,9 +548,20 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re | |||
535 | usbhid->ctrl[usbhid->ctrlhead].dir = dir; | 548 | usbhid->ctrl[usbhid->ctrlhead].dir = dir; |
536 | usbhid->ctrlhead = head; | 549 | usbhid->ctrlhead = head; |
537 | 550 | ||
538 | if (!test_and_set_bit(HID_CTRL_RUNNING, &usbhid->iofl)) | 551 | if (!test_and_set_bit(HID_CTRL_RUNNING, &usbhid->iofl)) { |
539 | if (hid_submit_ctrl(hid)) | 552 | if (hid_submit_ctrl(hid)) |
540 | clear_bit(HID_CTRL_RUNNING, &usbhid->iofl); | 553 | clear_bit(HID_CTRL_RUNNING, &usbhid->iofl); |
554 | } else { | ||
555 | /* | ||
556 | * the queue is known to run | ||
557 | * but an earlier request may be stuck | ||
558 | * we may need to time out | ||
559 | * no race because this is called under | ||
560 | * spinlock | ||
561 | */ | ||
562 | if (time_after(jiffies, usbhid->last_ctrl + HZ * 5)) | ||
563 | usb_unlink_urb(usbhid->urbctrl); | ||
564 | } | ||
541 | } | 565 | } |
542 | 566 | ||
543 | void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir) | 567 | void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir) |
@@ -774,7 +798,8 @@ static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid) | |||
774 | return 0; | 798 | return 0; |
775 | } | 799 | } |
776 | 800 | ||
777 | static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t count) | 801 | static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t count, |
802 | unsigned char report_type) | ||
778 | { | 803 | { |
779 | struct usbhid_device *usbhid = hid->driver_data; | 804 | struct usbhid_device *usbhid = hid->driver_data; |
780 | struct usb_device *dev = hid_to_usb_dev(hid); | 805 | struct usb_device *dev = hid_to_usb_dev(hid); |
@@ -785,7 +810,7 @@ static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t co | |||
785 | ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | 810 | ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), |
786 | HID_REQ_SET_REPORT, | 811 | HID_REQ_SET_REPORT, |
787 | USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, | 812 | USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, |
788 | ((HID_OUTPUT_REPORT + 1) << 8) | *buf, | 813 | ((report_type + 1) << 8) | *buf, |
789 | interface->desc.bInterfaceNumber, buf + 1, count - 1, | 814 | interface->desc.bInterfaceNumber, buf + 1, count - 1, |
790 | USB_CTRL_SET_TIMEOUT); | 815 | USB_CTRL_SET_TIMEOUT); |
791 | 816 | ||
@@ -981,9 +1006,6 @@ static int usbhid_start(struct hid_device *hid) | |||
981 | 1006 | ||
982 | spin_lock_init(&usbhid->lock); | 1007 | spin_lock_init(&usbhid->lock); |
983 | 1008 | ||
984 | usbhid->intf = intf; | ||
985 | usbhid->ifnum = interface->desc.bInterfaceNumber; | ||
986 | |||
987 | usbhid->urbctrl = usb_alloc_urb(0, GFP_KERNEL); | 1009 | usbhid->urbctrl = usb_alloc_urb(0, GFP_KERNEL); |
988 | if (!usbhid->urbctrl) { | 1010 | if (!usbhid->urbctrl) { |
989 | ret = -ENOMEM; | 1011 | ret = -ENOMEM; |
@@ -1154,6 +1176,8 @@ static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id * | |||
1154 | 1176 | ||
1155 | hid->driver_data = usbhid; | 1177 | hid->driver_data = usbhid; |
1156 | usbhid->hid = hid; | 1178 | usbhid->hid = hid; |
1179 | usbhid->intf = intf; | ||
1180 | usbhid->ifnum = interface->desc.bInterfaceNumber; | ||
1157 | 1181 | ||
1158 | ret = hid_add_device(hid); | 1182 | ret = hid_add_device(hid); |
1159 | if (ret) { | 1183 | if (ret) { |
@@ -1342,7 +1366,7 @@ static int hid_reset_resume(struct usb_interface *intf) | |||
1342 | 1366 | ||
1343 | #endif /* CONFIG_PM */ | 1367 | #endif /* CONFIG_PM */ |
1344 | 1368 | ||
1345 | static struct usb_device_id hid_usb_ids [] = { | 1369 | static const struct usb_device_id hid_usb_ids[] = { |
1346 | { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS, | 1370 | { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS, |
1347 | .bInterfaceClass = USB_INTERFACE_CLASS_HID }, | 1371 | .bInterfaceClass = USB_INTERFACE_CLASS_HID }, |
1348 | { } /* Terminating entry */ | 1372 | { } /* Terminating entry */ |