diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-22 22:21:48 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-22 22:21:48 -0400 |
commit | 3c2c4b73aa79e4a1b601710b59e092441175f4bb (patch) | |
tree | fbd08c3e18517871b25fe9c886caae423947d578 /drivers/hid/usbhid/hid-core.c | |
parent | f08b9c2f8af0d61faa1170aeae4fbca1eff6a504 (diff) | |
parent | 99ce58ddc4eadec8c35d9a1d64ff57703fdcfacc (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
Pull HID subsystem updates from Jiri Kosina:
"Apart from various driver updates and added support for a number of
new devices (mostly multitouch ones, but not limited to), there is one
change that is worth pointing out explicitly: creation of HID device
groups and proper autoloading of hid-multitouch, implemented by Henrik
Rydberg."
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid: (50 commits)
HID: wacom: fix build breakage without CONFIG_LEDS_CLASS
HID: waltop: Extend barrel button fix
HID: hyperv: Set the hid drvdata correctly
HID: wacom: Unify speed setting
HID: wacom: Add speed setting for Intuos4 WL
HID: wacom: Move Graphire raport header check.
HID: uclogic: Add support for UC-Logic TWHL850
HID: explain the signed/unsigned handling in hid_add_field()
HID: handle logical min/max signedness properly in parser
HID: logitech: read all 32 bits of report type bitfield
HID: wacom: Add LED selector control for Wacom Intuos4 WL
HID: hid-multitouch: fix wrong protocol detection
HID: wiimote: Fix IR data parser
HID: wacom: Add tilt reporting for Intuos4 WL
HID: multitouch: MT interface matching for Baanto
HID: hid-multitouch: Only match MT interfaces
HID: Create a common generic driver
HID: hid-multitouch: Switch to device groups
HID: Create a generic device group
HID: Allow bus wildcard matching
...
Diffstat (limited to 'drivers/hid/usbhid/hid-core.c')
-rw-r--r-- | drivers/hid/usbhid/hid-core.c | 81 |
1 files changed, 55 insertions, 26 deletions
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 340d6ae646ed..482f936fc29b 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c | |||
@@ -28,6 +28,7 @@ | |||
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) | |||
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) | |||
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 | } |
@@ -749,7 +757,7 @@ static int hid_get_class_descriptor(struct usb_device *dev, int ifnum, | |||
749 | int usbhid_open(struct hid_device *hid) | 757 | int usbhid_open(struct hid_device *hid) |
750 | { | 758 | { |
751 | struct usbhid_device *usbhid = hid->driver_data; | 759 | struct usbhid_device *usbhid = hid->driver_data; |
752 | int res; | 760 | int res = 0; |
753 | 761 | ||
754 | mutex_lock(&hid_open_mut); | 762 | mutex_lock(&hid_open_mut); |
755 | if (!hid->open++) { | 763 | if (!hid->open++) { |
@@ -757,17 +765,27 @@ int usbhid_open(struct hid_device *hid) | |||
757 | /* the device must be awake to reliably request remote wakeup */ | 765 | /* the device must be awake to reliably request remote wakeup */ |
758 | if (res < 0) { | 766 | if (res < 0) { |
759 | hid->open--; | 767 | hid->open--; |
760 | mutex_unlock(&hid_open_mut); | 768 | res = -EIO; |
761 | return -EIO; | 769 | goto done; |
762 | } | 770 | } |
763 | usbhid->intf->needs_remote_wakeup = 1; | 771 | usbhid->intf->needs_remote_wakeup = 1; |
764 | if (hid_start_in(hid)) | 772 | res = hid_start_in(hid); |
765 | hid_io_error(hid); | 773 | if (res) { |
766 | 774 | if (res != -ENOSPC) { | |
775 | hid_io_error(hid); | ||
776 | res = 0; | ||
777 | } else { | ||
778 | /* no use opening if resources are insufficient */ | ||
779 | hid->open--; | ||
780 | res = -EBUSY; | ||
781 | usbhid->intf->needs_remote_wakeup = 0; | ||
782 | } | ||
783 | } | ||
767 | usb_autopm_put_interface(usbhid->intf); | 784 | usb_autopm_put_interface(usbhid->intf); |
768 | } | 785 | } |
786 | done: | ||
769 | mutex_unlock(&hid_open_mut); | 787 | mutex_unlock(&hid_open_mut); |
770 | return 0; | 788 | return res; |
771 | } | 789 | } |
772 | 790 | ||
773 | void usbhid_close(struct hid_device *hid) | 791 | void usbhid_close(struct hid_device *hid) |
@@ -1396,7 +1414,34 @@ static int hid_post_reset(struct usb_interface *intf) | |||
1396 | struct usb_device *dev = interface_to_usbdev (intf); | 1414 | struct usb_device *dev = interface_to_usbdev (intf); |
1397 | struct hid_device *hid = usb_get_intfdata(intf); | 1415 | struct hid_device *hid = usb_get_intfdata(intf); |
1398 | struct usbhid_device *usbhid = hid->driver_data; | 1416 | struct usbhid_device *usbhid = hid->driver_data; |
1417 | struct usb_host_interface *interface = intf->cur_altsetting; | ||
1399 | int status; | 1418 | int status; |
1419 | char *rdesc; | ||
1420 | |||
1421 | /* Fetch and examine the HID report descriptor. If this | ||
1422 | * has changed, then rebind. Since usbcore's check of the | ||
1423 | * configuration descriptors passed, we already know that | ||
1424 | * the size of the HID report descriptor has not changed. | ||
1425 | */ | ||
1426 | rdesc = kmalloc(hid->rsize, GFP_KERNEL); | ||
1427 | if (!rdesc) { | ||
1428 | dbg_hid("couldn't allocate rdesc memory (post_reset)\n"); | ||
1429 | return 1; | ||
1430 | } | ||
1431 | status = hid_get_class_descriptor(dev, | ||
1432 | interface->desc.bInterfaceNumber, | ||
1433 | HID_DT_REPORT, rdesc, hid->rsize); | ||
1434 | if (status < 0) { | ||
1435 | dbg_hid("reading report descriptor failed (post_reset)\n"); | ||
1436 | kfree(rdesc); | ||
1437 | return 1; | ||
1438 | } | ||
1439 | status = memcmp(rdesc, hid->rdesc, hid->rsize); | ||
1440 | kfree(rdesc); | ||
1441 | if (status != 0) { | ||
1442 | dbg_hid("report descriptor changed\n"); | ||
1443 | return 1; | ||
1444 | } | ||
1400 | 1445 | ||
1401 | spin_lock_irq(&usbhid->lock); | 1446 | spin_lock_irq(&usbhid->lock); |
1402 | clear_bit(HID_RESET_PENDING, &usbhid->iofl); | 1447 | clear_bit(HID_RESET_PENDING, &usbhid->iofl); |
@@ -1553,28 +1598,15 @@ static struct usb_driver hid_driver = { | |||
1553 | .supports_autosuspend = 1, | 1598 | .supports_autosuspend = 1, |
1554 | }; | 1599 | }; |
1555 | 1600 | ||
1556 | static const struct hid_device_id hid_usb_table[] = { | ||
1557 | { HID_USB_DEVICE(HID_ANY_ID, HID_ANY_ID) }, | ||
1558 | { } | ||
1559 | }; | ||
1560 | |||
1561 | struct usb_interface *usbhid_find_interface(int minor) | 1601 | struct usb_interface *usbhid_find_interface(int minor) |
1562 | { | 1602 | { |
1563 | return usb_find_interface(&hid_driver, minor); | 1603 | return usb_find_interface(&hid_driver, minor); |
1564 | } | 1604 | } |
1565 | 1605 | ||
1566 | static struct hid_driver hid_usb_driver = { | ||
1567 | .name = "generic-usb", | ||
1568 | .id_table = hid_usb_table, | ||
1569 | }; | ||
1570 | |||
1571 | static int __init hid_init(void) | 1606 | static int __init hid_init(void) |
1572 | { | 1607 | { |
1573 | int retval = -ENOMEM; | 1608 | int retval = -ENOMEM; |
1574 | 1609 | ||
1575 | retval = hid_register_driver(&hid_usb_driver); | ||
1576 | if (retval) | ||
1577 | goto hid_register_fail; | ||
1578 | retval = usbhid_quirks_init(quirks_param); | 1610 | retval = usbhid_quirks_init(quirks_param); |
1579 | if (retval) | 1611 | if (retval) |
1580 | goto usbhid_quirks_init_fail; | 1612 | goto usbhid_quirks_init_fail; |
@@ -1587,8 +1619,6 @@ static int __init hid_init(void) | |||
1587 | usb_register_fail: | 1619 | usb_register_fail: |
1588 | usbhid_quirks_exit(); | 1620 | usbhid_quirks_exit(); |
1589 | usbhid_quirks_init_fail: | 1621 | usbhid_quirks_init_fail: |
1590 | hid_unregister_driver(&hid_usb_driver); | ||
1591 | hid_register_fail: | ||
1592 | return retval; | 1622 | return retval; |
1593 | } | 1623 | } |
1594 | 1624 | ||
@@ -1596,7 +1626,6 @@ static void __exit hid_exit(void) | |||
1596 | { | 1626 | { |
1597 | usb_deregister(&hid_driver); | 1627 | usb_deregister(&hid_driver); |
1598 | usbhid_quirks_exit(); | 1628 | usbhid_quirks_exit(); |
1599 | hid_unregister_driver(&hid_usb_driver); | ||
1600 | } | 1629 | } |
1601 | 1630 | ||
1602 | module_init(hid_init); | 1631 | module_init(hid_init); |