diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-30 14:51:43 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-30 14:51:43 -0400 |
| commit | cdcba02a5f64f4df20b6749a0169124e38ecb733 (patch) | |
| tree | bea066c2ddb66038a5e775708dc6e0949375f106 | |
| parent | 53387b0151260f6c3513adeca77f05ed052d6217 (diff) | |
| parent | fa157bdfe87c5ea98a80b96cb08f1ab509e21a52 (diff) | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid:
HID: add quirk entry for no-name keyboard (0x13ba/0x0017)
HID: fix hid_device_id for cross compiling
HID: sync on deleted io_retry timer in usbhid driver
HID: fix oops during suspend of unbound HID devices
| -rw-r--r-- | drivers/hid/hid-core.c | 1 | ||||
| -rw-r--r-- | drivers/hid/hid-dell.c | 1 | ||||
| -rw-r--r-- | drivers/hid/hid-ids.h | 3 | ||||
| -rw-r--r-- | drivers/hid/usbhid/hid-core.c | 60 | ||||
| -rw-r--r-- | drivers/hid/usbhid/usbhid.h | 2 | ||||
| -rw-r--r-- | include/linux/hid.h | 1 | ||||
| -rw-r--r-- | include/linux/mod_devicetable.h | 1 |
7 files changed, 51 insertions, 18 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 743e6f8cb202..1903e7515650 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
| @@ -1263,6 +1263,7 @@ static const struct hid_device_id hid_blacklist[] = { | |||
| 1263 | { HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658) }, | 1263 | { HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658) }, |
| 1264 | { HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_SK8115) }, | 1264 | { HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_SK8115) }, |
| 1265 | { HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) }, | 1265 | { HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) }, |
| 1266 | { HID_USB_DEVICE(USB_VENDOR_ID_GENERIC_13BA, USB_DEVICE_ID_GENERIC_13BA_KBD_MOUSE) }, | ||
| 1266 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) }, | 1267 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) }, |
| 1267 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) }, | 1268 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) }, |
| 1268 | { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) }, | 1269 | { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) }, |
diff --git a/drivers/hid/hid-dell.c b/drivers/hid/hid-dell.c index 1a0d0dfc62fc..f5474300b83a 100644 --- a/drivers/hid/hid-dell.c +++ b/drivers/hid/hid-dell.c | |||
| @@ -48,6 +48,7 @@ err_free: | |||
| 48 | static const struct hid_device_id dell_devices[] = { | 48 | static const struct hid_device_id dell_devices[] = { |
| 49 | { HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658) }, | 49 | { HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658) }, |
| 50 | { HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_SK8115) }, | 50 | { HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_SK8115) }, |
| 51 | { HID_USB_DEVICE(USB_VENDOR_ID_GENERIC_13BA, USB_DEVICE_ID_GENERIC_13BA_KBD_MOUSE) }, | ||
| 51 | { } | 52 | { } |
| 52 | }; | 53 | }; |
| 53 | MODULE_DEVICE_TABLE(hid, dell_devices); | 54 | MODULE_DEVICE_TABLE(hid, dell_devices); |
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index a0d6a6cb1842..5cc404291736 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h | |||
| @@ -163,6 +163,9 @@ | |||
| 163 | 163 | ||
| 164 | #define USB_VENDOR_ID_GENERAL_TOUCH 0x0dfc | 164 | #define USB_VENDOR_ID_GENERAL_TOUCH 0x0dfc |
| 165 | 165 | ||
| 166 | #define USB_VENDOR_ID_GENERIC_13BA 0x13ba | ||
| 167 | #define USB_DEVICE_ID_GENERIC_13BA_KBD_MOUSE 0x0017 | ||
| 168 | |||
| 166 | #define USB_VENDOR_ID_GLAB 0x06c2 | 169 | #define USB_VENDOR_ID_GLAB 0x06c2 |
| 167 | #define USB_DEVICE_ID_4_PHIDGETSERVO_30 0x0038 | 170 | #define USB_DEVICE_ID_4_PHIDGETSERVO_30 0x0038 |
| 168 | #define USB_DEVICE_ID_1_PHIDGETSERVO_30 0x0039 | 171 | #define USB_DEVICE_ID_1_PHIDGETSERVO_30 0x0039 |
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 42bdd83444c1..18e5ddd722cd 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
| 21 | #include <linux/list.h> | 21 | #include <linux/list.h> |
| 22 | #include <linux/mm.h> | 22 | #include <linux/mm.h> |
| 23 | #include <linux/mutex.h> | ||
| 23 | #include <linux/smp_lock.h> | 24 | #include <linux/smp_lock.h> |
| 24 | #include <linux/spinlock.h> | 25 | #include <linux/spinlock.h> |
| 25 | #include <asm/unaligned.h> | 26 | #include <asm/unaligned.h> |
| @@ -776,21 +777,10 @@ static int usbhid_start(struct hid_device *hid) | |||
| 776 | struct usb_interface *intf = to_usb_interface(hid->dev.parent); | 777 | struct usb_interface *intf = to_usb_interface(hid->dev.parent); |
| 777 | struct usb_host_interface *interface = intf->cur_altsetting; | 778 | struct usb_host_interface *interface = intf->cur_altsetting; |
| 778 | struct usb_device *dev = interface_to_usbdev(intf); | 779 | struct usb_device *dev = interface_to_usbdev(intf); |
| 779 | struct usbhid_device *usbhid; | 780 | struct usbhid_device *usbhid = hid->driver_data; |
| 780 | unsigned int n, insize = 0; | 781 | unsigned int n, insize = 0; |
| 781 | int ret; | 782 | int ret; |
| 782 | 783 | ||
| 783 | WARN_ON(hid->driver_data); | ||
| 784 | |||
| 785 | usbhid = kzalloc(sizeof(struct usbhid_device), GFP_KERNEL); | ||
| 786 | if (usbhid == NULL) { | ||
| 787 | ret = -ENOMEM; | ||
| 788 | goto err; | ||
| 789 | } | ||
| 790 | |||
| 791 | hid->driver_data = usbhid; | ||
| 792 | usbhid->hid = hid; | ||
| 793 | |||
| 794 | usbhid->bufsize = HID_MIN_BUFFER_SIZE; | 784 | usbhid->bufsize = HID_MIN_BUFFER_SIZE; |
| 795 | hid_find_max_report(hid, HID_INPUT_REPORT, &usbhid->bufsize); | 785 | hid_find_max_report(hid, HID_INPUT_REPORT, &usbhid->bufsize); |
| 796 | hid_find_max_report(hid, HID_OUTPUT_REPORT, &usbhid->bufsize); | 786 | hid_find_max_report(hid, HID_OUTPUT_REPORT, &usbhid->bufsize); |
| @@ -804,6 +794,7 @@ static int usbhid_start(struct hid_device *hid) | |||
| 804 | if (insize > HID_MAX_BUFFER_SIZE) | 794 | if (insize > HID_MAX_BUFFER_SIZE) |
| 805 | insize = HID_MAX_BUFFER_SIZE; | 795 | insize = HID_MAX_BUFFER_SIZE; |
| 806 | 796 | ||
| 797 | mutex_lock(&usbhid->setup); | ||
| 807 | if (hid_alloc_buffers(dev, hid)) { | 798 | if (hid_alloc_buffers(dev, hid)) { |
| 808 | ret = -ENOMEM; | 799 | ret = -ENOMEM; |
| 809 | goto fail; | 800 | goto fail; |
| @@ -888,6 +879,9 @@ static int usbhid_start(struct hid_device *hid) | |||
| 888 | usbhid_init_reports(hid); | 879 | usbhid_init_reports(hid); |
| 889 | hid_dump_device(hid); | 880 | hid_dump_device(hid); |
| 890 | 881 | ||
| 882 | set_bit(HID_STARTED, &usbhid->iofl); | ||
| 883 | mutex_unlock(&usbhid->setup); | ||
| 884 | |||
| 891 | return 0; | 885 | return 0; |
| 892 | 886 | ||
| 893 | fail: | 887 | fail: |
| @@ -895,8 +889,7 @@ fail: | |||
| 895 | usb_free_urb(usbhid->urbout); | 889 | usb_free_urb(usbhid->urbout); |
| 896 | usb_free_urb(usbhid->urbctrl); | 890 | usb_free_urb(usbhid->urbctrl); |
| 897 | hid_free_buffers(dev, hid); | 891 | hid_free_buffers(dev, hid); |
| 898 | kfree(usbhid); | 892 | mutex_unlock(&usbhid->setup); |
| 899 | err: | ||
| 900 | return ret; | 893 | return ret; |
| 901 | } | 894 | } |
| 902 | 895 | ||
| @@ -907,6 +900,8 @@ static void usbhid_stop(struct hid_device *hid) | |||
| 907 | if (WARN_ON(!usbhid)) | 900 | if (WARN_ON(!usbhid)) |
| 908 | return; | 901 | return; |
| 909 | 902 | ||
| 903 | mutex_lock(&usbhid->setup); | ||
| 904 | clear_bit(HID_STARTED, &usbhid->iofl); | ||
| 910 | spin_lock_irq(&usbhid->inlock); /* Sync with error handler */ | 905 | spin_lock_irq(&usbhid->inlock); /* Sync with error handler */ |
| 911 | set_bit(HID_DISCONNECTED, &usbhid->iofl); | 906 | set_bit(HID_DISCONNECTED, &usbhid->iofl); |
| 912 | spin_unlock_irq(&usbhid->inlock); | 907 | spin_unlock_irq(&usbhid->inlock); |
| @@ -931,8 +926,7 @@ static void usbhid_stop(struct hid_device *hid) | |||
| 931 | usb_free_urb(usbhid->urbout); | 926 | usb_free_urb(usbhid->urbout); |
| 932 | 927 | ||
| 933 | hid_free_buffers(hid_to_usb_dev(hid), hid); | 928 | hid_free_buffers(hid_to_usb_dev(hid), hid); |
| 934 | kfree(usbhid); | 929 | mutex_unlock(&usbhid->setup); |
| 935 | hid->driver_data = NULL; | ||
| 936 | } | 930 | } |
| 937 | 931 | ||
| 938 | static struct hid_ll_driver usb_hid_driver = { | 932 | static struct hid_ll_driver usb_hid_driver = { |
| @@ -947,6 +941,7 @@ static struct hid_ll_driver usb_hid_driver = { | |||
| 947 | static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id) | 941 | static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id) |
| 948 | { | 942 | { |
| 949 | struct usb_device *dev = interface_to_usbdev(intf); | 943 | struct usb_device *dev = interface_to_usbdev(intf); |
| 944 | struct usbhid_device *usbhid; | ||
| 950 | struct hid_device *hid; | 945 | struct hid_device *hid; |
| 951 | size_t len; | 946 | size_t len; |
| 952 | int ret; | 947 | int ret; |
| @@ -1000,14 +995,26 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id) | |||
| 1000 | if (usb_string(dev, dev->descriptor.iSerialNumber, hid->uniq, 64) <= 0) | 995 | if (usb_string(dev, dev->descriptor.iSerialNumber, hid->uniq, 64) <= 0) |
| 1001 | hid->uniq[0] = 0; | 996 | hid->uniq[0] = 0; |
| 1002 | 997 | ||
| 998 | usbhid = kzalloc(sizeof(*usbhid), GFP_KERNEL); | ||
| 999 | if (usbhid == NULL) { | ||
| 1000 | ret = -ENOMEM; | ||
| 1001 | goto err; | ||
| 1002 | } | ||
| 1003 | |||
| 1004 | hid->driver_data = usbhid; | ||
| 1005 | usbhid->hid = hid; | ||
| 1006 | mutex_init(&usbhid->setup); /* needed on suspend/resume */ | ||
| 1007 | |||
| 1003 | ret = hid_add_device(hid); | 1008 | ret = hid_add_device(hid); |
| 1004 | if (ret) { | 1009 | if (ret) { |
| 1005 | if (ret != -ENODEV) | 1010 | if (ret != -ENODEV) |
| 1006 | dev_err(&intf->dev, "can't add hid device: %d\n", ret); | 1011 | dev_err(&intf->dev, "can't add hid device: %d\n", ret); |
| 1007 | goto err; | 1012 | goto err_free; |
| 1008 | } | 1013 | } |
| 1009 | 1014 | ||
| 1010 | return 0; | 1015 | return 0; |
| 1016 | err_free: | ||
| 1017 | kfree(usbhid); | ||
| 1011 | err: | 1018 | err: |
| 1012 | hid_destroy_device(hid); | 1019 | hid_destroy_device(hid); |
| 1013 | return ret; | 1020 | return ret; |
| @@ -1016,11 +1023,14 @@ err: | |||
| 1016 | static void hid_disconnect(struct usb_interface *intf) | 1023 | static void hid_disconnect(struct usb_interface *intf) |
| 1017 | { | 1024 | { |
| 1018 | struct hid_device *hid = usb_get_intfdata(intf); | 1025 | struct hid_device *hid = usb_get_intfdata(intf); |
| 1026 | struct usbhid_device *usbhid; | ||
| 1019 | 1027 | ||
| 1020 | if (WARN_ON(!hid)) | 1028 | if (WARN_ON(!hid)) |
| 1021 | return; | 1029 | return; |
| 1022 | 1030 | ||
| 1031 | usbhid = hid->driver_data; | ||
| 1023 | hid_destroy_device(hid); | 1032 | hid_destroy_device(hid); |
| 1033 | kfree(usbhid); | ||
| 1024 | } | 1034 | } |
| 1025 | 1035 | ||
| 1026 | static int hid_suspend(struct usb_interface *intf, pm_message_t message) | 1036 | static int hid_suspend(struct usb_interface *intf, pm_message_t message) |
| @@ -1028,11 +1038,18 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message) | |||
| 1028 | struct hid_device *hid = usb_get_intfdata (intf); | 1038 | struct hid_device *hid = usb_get_intfdata (intf); |
| 1029 | struct usbhid_device *usbhid = hid->driver_data; | 1039 | struct usbhid_device *usbhid = hid->driver_data; |
| 1030 | 1040 | ||
| 1041 | mutex_lock(&usbhid->setup); | ||
| 1042 | if (!test_bit(HID_STARTED, &usbhid->iofl)) { | ||
| 1043 | mutex_unlock(&usbhid->setup); | ||
| 1044 | return 0; | ||
| 1045 | } | ||
| 1046 | |||
| 1031 | spin_lock_irq(&usbhid->inlock); /* Sync with error handler */ | 1047 | spin_lock_irq(&usbhid->inlock); /* Sync with error handler */ |
| 1032 | set_bit(HID_SUSPENDED, &usbhid->iofl); | 1048 | set_bit(HID_SUSPENDED, &usbhid->iofl); |
| 1033 | spin_unlock_irq(&usbhid->inlock); | 1049 | spin_unlock_irq(&usbhid->inlock); |
| 1034 | del_timer(&usbhid->io_retry); | 1050 | del_timer_sync(&usbhid->io_retry); |
| 1035 | usb_kill_urb(usbhid->urbin); | 1051 | usb_kill_urb(usbhid->urbin); |
| 1052 | mutex_unlock(&usbhid->setup); | ||
| 1036 | dev_dbg(&intf->dev, "suspend\n"); | 1053 | dev_dbg(&intf->dev, "suspend\n"); |
| 1037 | return 0; | 1054 | return 0; |
| 1038 | } | 1055 | } |
| @@ -1043,9 +1060,16 @@ static int hid_resume(struct usb_interface *intf) | |||
| 1043 | struct usbhid_device *usbhid = hid->driver_data; | 1060 | struct usbhid_device *usbhid = hid->driver_data; |
| 1044 | int status; | 1061 | int status; |
| 1045 | 1062 | ||
| 1063 | mutex_lock(&usbhid->setup); | ||
| 1064 | if (!test_bit(HID_STARTED, &usbhid->iofl)) { | ||
| 1065 | mutex_unlock(&usbhid->setup); | ||
| 1066 | return 0; | ||
| 1067 | } | ||
| 1068 | |||
| 1046 | clear_bit(HID_SUSPENDED, &usbhid->iofl); | 1069 | clear_bit(HID_SUSPENDED, &usbhid->iofl); |
| 1047 | usbhid->retry_delay = 0; | 1070 | usbhid->retry_delay = 0; |
| 1048 | status = hid_start_in(hid); | 1071 | status = hid_start_in(hid); |
| 1072 | mutex_unlock(&usbhid->setup); | ||
| 1049 | dev_dbg(&intf->dev, "resume status %d\n", status); | 1073 | dev_dbg(&intf->dev, "resume status %d\n", status); |
| 1050 | return status; | 1074 | return status; |
| 1051 | } | 1075 | } |
diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h index abedb13c623e..55973ff54008 100644 --- a/drivers/hid/usbhid/usbhid.h +++ b/drivers/hid/usbhid/usbhid.h | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #include <linux/types.h> | 27 | #include <linux/types.h> |
| 28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
| 29 | #include <linux/list.h> | 29 | #include <linux/list.h> |
| 30 | #include <linux/mutex.h> | ||
| 30 | #include <linux/timer.h> | 31 | #include <linux/timer.h> |
| 31 | #include <linux/wait.h> | 32 | #include <linux/wait.h> |
| 32 | #include <linux/workqueue.h> | 33 | #include <linux/workqueue.h> |
| @@ -73,6 +74,7 @@ struct usbhid_device { | |||
| 73 | dma_addr_t outbuf_dma; /* Output buffer dma */ | 74 | dma_addr_t outbuf_dma; /* Output buffer dma */ |
| 74 | spinlock_t outlock; /* Output fifo spinlock */ | 75 | spinlock_t outlock; /* Output fifo spinlock */ |
| 75 | 76 | ||
| 77 | struct mutex setup; | ||
| 76 | unsigned long iofl; /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */ | 78 | unsigned long iofl; /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */ |
| 77 | struct timer_list io_retry; /* Retry timer */ | 79 | struct timer_list io_retry; /* Retry timer */ |
| 78 | unsigned long stop_retry; /* Time to give up, in jiffies */ | 80 | unsigned long stop_retry; /* Time to give up, in jiffies */ |
diff --git a/include/linux/hid.h b/include/linux/hid.h index 5355ca4b939e..e5780f8c934a 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h | |||
| @@ -410,6 +410,7 @@ struct hid_output_fifo { | |||
| 410 | #define HID_SUSPENDED 5 | 410 | #define HID_SUSPENDED 5 |
| 411 | #define HID_CLEAR_HALT 6 | 411 | #define HID_CLEAR_HALT 6 |
| 412 | #define HID_DISCONNECTED 7 | 412 | #define HID_DISCONNECTED 7 |
| 413 | #define HID_STARTED 8 | ||
| 413 | 414 | ||
| 414 | struct hid_input { | 415 | struct hid_input { |
| 415 | struct list_head list; | 416 | struct list_head list; |
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h index eb71b45fdf5a..97b91d1abb43 100644 --- a/include/linux/mod_devicetable.h +++ b/include/linux/mod_devicetable.h | |||
| @@ -135,6 +135,7 @@ struct usb_device_id { | |||
| 135 | 135 | ||
| 136 | struct hid_device_id { | 136 | struct hid_device_id { |
| 137 | __u16 bus; | 137 | __u16 bus; |
| 138 | __u16 pad1; | ||
| 138 | __u32 vendor; | 139 | __u32 vendor; |
| 139 | __u32 product; | 140 | __u32 product; |
| 140 | kernel_ulong_t driver_data | 141 | kernel_ulong_t driver_data |
