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 | |
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')
-rw-r--r-- | drivers/hid/usbhid/hid-core.c | 81 | ||||
-rw-r--r-- | drivers/hid/usbhid/hid-quirks.c | 1 | ||||
-rw-r--r-- | drivers/hid/usbhid/hiddev.c | 9 | ||||
-rw-r--r-- | drivers/hid/usbhid/usbhid.h | 1 |
4 files changed, 62 insertions, 30 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); |
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 782c63955f29..0597ee604f6e 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c | |||
@@ -88,6 +88,7 @@ static const struct hid_blacklist { | |||
88 | { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U, HID_QUIRK_MULTI_INPUT }, | 88 | { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U, HID_QUIRK_MULTI_INPUT }, |
89 | { USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH, HID_QUIRK_MULTI_INPUT }, | 89 | { USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH, HID_QUIRK_MULTI_INPUT }, |
90 | { USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH, HID_QUIRK_MULTI_INPUT }, | 90 | { USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH, HID_QUIRK_MULTI_INPUT }, |
91 | { USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET, HID_QUIRK_MULTI_INPUT }, | ||
91 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, | 92 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, |
92 | 93 | ||
93 | { USB_VENDOR_ID_WISEGROUP_LTD2, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, | 94 | { USB_VENDOR_ID_WISEGROUP_LTD2, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, |
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index b1ec0e2aeb57..14599e256791 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c | |||
@@ -34,6 +34,7 @@ | |||
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_MINORS | 40 | #ifdef CONFIG_USB_DYNAMIC_MINORS |
@@ -250,13 +251,13 @@ static int hiddev_release(struct inode * inode, struct file * file) | |||
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) | |||
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: | |||
322 | mutex_unlock(&hiddev->existancelock); | 323 | mutex_unlock(&hiddev->existancelock); |
323 | bail: | 324 | bail: |
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 | ||
diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h index cb8f703efde5..1883d7b94870 100644 --- a/drivers/hid/usbhid/usbhid.h +++ b/drivers/hid/usbhid/usbhid.h | |||
@@ -55,6 +55,7 @@ struct usb_interface *usbhid_find_interface(int minor); | |||
55 | #define HID_STARTED 8 | 55 | #define HID_STARTED 8 |
56 | #define HID_REPORTED_IDLE 9 | 56 | #define HID_REPORTED_IDLE 9 |
57 | #define HID_KEYS_PRESSED 10 | 57 | #define HID_KEYS_PRESSED 10 |
58 | #define HID_NO_BANDWIDTH 11 | ||
58 | 59 | ||
59 | /* | 60 | /* |
60 | * USB-specific HID struct, to be pointed to | 61 | * USB-specific HID struct, to be pointed to |