aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-11-15 22:02:48 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2008-11-15 22:02:48 -0500
commitb42ccbc521f2acad48eb96b32883efe2f3e16b45 (patch)
tree85f45ef13f3c409850431a52fd5e04ff3e826e0c /drivers
parentd659fc14cbd39fef625072819c6968044975fda7 (diff)
parent131d3a7a009d56a96cc7117b4e9d0c90c2e2a1dc (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: don't grab devices with no input HID: fix radio-mr800 hidquirks HID: fix kworld fm700 radio hidquirks HID: fix start/stop cycle in usbhid driver HID: use single threaded work queue for hid_compat HID: map macbook keys for "Expose" and "Dashboard" HID: support for new unibody macbooks HID: fix locking in hidraw_open()
Diffstat (limited to 'drivers')
-rw-r--r--drivers/hid/hid-apple.c11
-rw-r--r--drivers/hid/hid-core.c12
-rw-r--r--drivers/hid/hid-ids.h3
-rw-r--r--drivers/hid/hidraw.c30
-rw-r--r--drivers/hid/usbhid/hid-core.c25
5 files changed, 56 insertions, 25 deletions
diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c
index c6ab4ba60c52..9b97795e45ad 100644
--- a/drivers/hid/hid-apple.c
+++ b/drivers/hid/hid-apple.c
@@ -55,10 +55,11 @@ struct apple_key_translation {
55 55
56static struct apple_key_translation apple_fn_keys[] = { 56static struct apple_key_translation apple_fn_keys[] = {
57 { KEY_BACKSPACE, KEY_DELETE }, 57 { KEY_BACKSPACE, KEY_DELETE },
58 { KEY_ENTER, KEY_INSERT },
58 { KEY_F1, KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY }, 59 { KEY_F1, KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY },
59 { KEY_F2, KEY_BRIGHTNESSUP, APPLE_FLAG_FKEY }, 60 { KEY_F2, KEY_BRIGHTNESSUP, APPLE_FLAG_FKEY },
60 { KEY_F3, KEY_FN_F5, APPLE_FLAG_FKEY }, /* Exposé */ 61 { KEY_F3, KEY_SCALE, APPLE_FLAG_FKEY },
61 { KEY_F4, KEY_FN_F4, APPLE_FLAG_FKEY }, /* Dashboard */ 62 { KEY_F4, KEY_DASHBOARD, APPLE_FLAG_FKEY },
62 { KEY_F5, KEY_KBDILLUMDOWN, APPLE_FLAG_FKEY }, 63 { KEY_F5, KEY_KBDILLUMDOWN, APPLE_FLAG_FKEY },
63 { KEY_F6, KEY_KBDILLUMUP, APPLE_FLAG_FKEY }, 64 { KEY_F6, KEY_KBDILLUMUP, APPLE_FLAG_FKEY },
64 { KEY_F7, KEY_PREVIOUSSONG, APPLE_FLAG_FKEY }, 65 { KEY_F7, KEY_PREVIOUSSONG, APPLE_FLAG_FKEY },
@@ -418,6 +419,12 @@ static const struct hid_device_id apple_devices[] = {
418 .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, 419 .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
419 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS), 420 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS),
420 .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, 421 .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
422 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI),
423 .driver_data = APPLE_HAS_FN },
424 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO),
425 .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
426 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS),
427 .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
421 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY), 428 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY),
422 .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, 429 .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
423 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY), 430 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY),
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index d3671b4049c0..147ec591a806 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1250,9 +1250,11 @@ static const struct hid_device_id hid_blacklist[] = {
1250 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI) }, 1250 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI) },
1251 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO) }, 1251 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO) },
1252 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS) }, 1252 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS) },
1253 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI) },
1254 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO) },
1255 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS) },
1253 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, 1256 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
1254 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, 1257 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
1255 { HID_USB_DEVICE(USB_VENDOR_ID_AVERMEDIA, USB_DEVICE_ID_AVER_FM_MR800) },
1256 { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) }, 1258 { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) },
1257 { HID_USB_DEVICE(USB_VENDOR_ID_BRIGHT, USB_DEVICE_ID_BRIGHT_ABNT2) }, 1259 { HID_USB_DEVICE(USB_VENDOR_ID_BRIGHT, USB_DEVICE_ID_BRIGHT_ABNT2) },
1258 { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) }, 1260 { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) },
@@ -1265,7 +1267,6 @@ static const struct hid_device_id hid_blacklist[] = {
1265 { HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) }, 1267 { 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) }, 1268 { HID_USB_DEVICE(USB_VENDOR_ID_GENERIC_13BA, USB_DEVICE_ID_GENERIC_13BA_KBD_MOUSE) },
1267 { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) }, 1269 { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) },
1268 { HID_USB_DEVICE(USB_VENDOR_ID_KWORLD, USB_DEVICE_ID_KWORLD_RADIO_FM700) },
1269 { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) }, 1270 { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) },
1270 { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) }, 1271 { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) },
1271 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) }, 1272 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) },
@@ -1409,6 +1410,7 @@ static const struct hid_device_id hid_ignore_list[] = {
1409 { HID_USB_DEVICE(USB_VENDOR_ID_ALCOR, USB_DEVICE_ID_ALCOR_USBRS232) }, 1410 { HID_USB_DEVICE(USB_VENDOR_ID_ALCOR, USB_DEVICE_ID_ALCOR_USBRS232) },
1410 { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM)}, 1411 { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM)},
1411 { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM2)}, 1412 { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM2)},
1413 { HID_USB_DEVICE(USB_VENDOR_ID_AVERMEDIA, USB_DEVICE_ID_AVER_FM_MR800) },
1412 { HID_USB_DEVICE(USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD) }, 1414 { HID_USB_DEVICE(USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD) },
1413 { HID_USB_DEVICE(USB_VENDOR_ID_CIDC, 0x0103) }, 1415 { HID_USB_DEVICE(USB_VENDOR_ID_CIDC, 0x0103) },
1414 { HID_USB_DEVICE(USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_RADIO_SI470X) }, 1416 { HID_USB_DEVICE(USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_RADIO_SI470X) },
@@ -1486,6 +1488,7 @@ static const struct hid_device_id hid_ignore_list[] = {
1486 { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1007) }, 1488 { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1007) },
1487 { HID_USB_DEVICE(USB_VENDOR_ID_IMATION, USB_DEVICE_ID_DISC_STAKKA) }, 1489 { HID_USB_DEVICE(USB_VENDOR_ID_IMATION, USB_DEVICE_ID_DISC_STAKKA) },
1488 { HID_USB_DEVICE(USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO) }, 1490 { HID_USB_DEVICE(USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO) },
1491 { HID_USB_DEVICE(USB_VENDOR_ID_KWORLD, USB_DEVICE_ID_KWORLD_RADIO_FM700) },
1489 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_GPEN_560) }, 1492 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_GPEN_560) },
1490 { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY) }, 1493 { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY) },
1491 { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POCKETCASSY) }, 1494 { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POCKETCASSY) },
@@ -1573,6 +1576,9 @@ static const struct hid_device_id hid_mouse_ignore_list[] = {
1573 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI) }, 1576 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI) },
1574 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO) }, 1577 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO) },
1575 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS) }, 1578 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS) },
1579 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI) },
1580 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO) },
1581 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS) },
1576 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, 1582 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
1577 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, 1583 { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
1578 { } 1584 { }
@@ -1730,7 +1736,7 @@ static int __init hid_init(void)
1730 goto err_bus; 1736 goto err_bus;
1731 1737
1732#ifdef CONFIG_HID_COMPAT 1738#ifdef CONFIG_HID_COMPAT
1733 hid_compat_wq = create_workqueue("hid_compat"); 1739 hid_compat_wq = create_singlethread_workqueue("hid_compat");
1734 if (!hid_compat_wq) { 1740 if (!hid_compat_wq) {
1735 hidraw_exit(); 1741 hidraw_exit();
1736 goto err; 1742 goto err;
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index f05bcbbbb0d5..d70075dd3d81 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -82,6 +82,9 @@
82#define USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI 0x0230 82#define USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI 0x0230
83#define USB_DEVICE_ID_APPLE_WELLSPRING2_ISO 0x0231 83#define USB_DEVICE_ID_APPLE_WELLSPRING2_ISO 0x0231
84#define USB_DEVICE_ID_APPLE_WELLSPRING2_JIS 0x0232 84#define USB_DEVICE_ID_APPLE_WELLSPRING2_JIS 0x0232
85#define USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI 0x0236
86#define USB_DEVICE_ID_APPLE_WELLSPRING3_ISO 0x0237
87#define USB_DEVICE_ID_APPLE_WELLSPRING3_JIS 0x0238
85#define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a 88#define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a
86#define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b 89#define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b
87#define USB_DEVICE_ID_APPLE_ATV_IRCONTROL 0x8241 90#define USB_DEVICE_ID_APPLE_ATV_IRCONTROL 0x8241
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index 894d52e05bf9..7685ae6808c4 100644
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -38,7 +38,7 @@ static int hidraw_major;
38static struct cdev hidraw_cdev; 38static struct cdev hidraw_cdev;
39static struct class *hidraw_class; 39static struct class *hidraw_class;
40static struct hidraw *hidraw_table[HIDRAW_MAX_DEVICES]; 40static struct hidraw *hidraw_table[HIDRAW_MAX_DEVICES];
41static DEFINE_SPINLOCK(minors_lock); 41static DEFINE_MUTEX(minors_lock);
42 42
43static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) 43static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
44{ 44{
@@ -159,13 +159,13 @@ static int hidraw_open(struct inode *inode, struct file *file)
159 struct hidraw_list *list; 159 struct hidraw_list *list;
160 int err = 0; 160 int err = 0;
161 161
162 lock_kernel();
163 if (!(list = kzalloc(sizeof(struct hidraw_list), GFP_KERNEL))) { 162 if (!(list = kzalloc(sizeof(struct hidraw_list), GFP_KERNEL))) {
164 err = -ENOMEM; 163 err = -ENOMEM;
165 goto out; 164 goto out;
166 } 165 }
167 166
168 spin_lock(&minors_lock); 167 lock_kernel();
168 mutex_lock(&minors_lock);
169 if (!hidraw_table[minor]) { 169 if (!hidraw_table[minor]) {
170 printk(KERN_EMERG "hidraw device with minor %d doesn't exist\n", 170 printk(KERN_EMERG "hidraw device with minor %d doesn't exist\n",
171 minor); 171 minor);
@@ -180,13 +180,16 @@ static int hidraw_open(struct inode *inode, struct file *file)
180 file->private_data = list; 180 file->private_data = list;
181 181
182 dev = hidraw_table[minor]; 182 dev = hidraw_table[minor];
183 if (!dev->open++) 183 if (!dev->open++) {
184 dev->hid->ll_driver->open(dev->hid); 184 err = dev->hid->ll_driver->open(dev->hid);
185 if (err < 0)
186 dev->open--;
187 }
185 188
186out_unlock: 189out_unlock:
187 spin_unlock(&minors_lock); 190 mutex_unlock(&minors_lock);
188out:
189 unlock_kernel(); 191 unlock_kernel();
192out:
190 return err; 193 return err;
191 194
192} 195}
@@ -310,7 +313,7 @@ int hidraw_connect(struct hid_device *hid)
310 313
311 result = -EINVAL; 314 result = -EINVAL;
312 315
313 spin_lock(&minors_lock); 316 mutex_lock(&minors_lock);
314 317
315 for (minor = 0; minor < HIDRAW_MAX_DEVICES; minor++) { 318 for (minor = 0; minor < HIDRAW_MAX_DEVICES; minor++) {
316 if (hidraw_table[minor]) 319 if (hidraw_table[minor])
@@ -320,9 +323,8 @@ int hidraw_connect(struct hid_device *hid)
320 break; 323 break;
321 } 324 }
322 325
323 spin_unlock(&minors_lock);
324
325 if (result) { 326 if (result) {
327 mutex_unlock(&minors_lock);
326 kfree(dev); 328 kfree(dev);
327 goto out; 329 goto out;
328 } 330 }
@@ -331,14 +333,14 @@ int hidraw_connect(struct hid_device *hid)
331 NULL, "%s%d", "hidraw", minor); 333 NULL, "%s%d", "hidraw", minor);
332 334
333 if (IS_ERR(dev->dev)) { 335 if (IS_ERR(dev->dev)) {
334 spin_lock(&minors_lock);
335 hidraw_table[minor] = NULL; 336 hidraw_table[minor] = NULL;
336 spin_unlock(&minors_lock); 337 mutex_unlock(&minors_lock);
337 result = PTR_ERR(dev->dev); 338 result = PTR_ERR(dev->dev);
338 kfree(dev); 339 kfree(dev);
339 goto out; 340 goto out;
340 } 341 }
341 342
343 mutex_unlock(&minors_lock);
342 init_waitqueue_head(&dev->wait); 344 init_waitqueue_head(&dev->wait);
343 INIT_LIST_HEAD(&dev->list); 345 INIT_LIST_HEAD(&dev->list);
344 346
@@ -360,9 +362,9 @@ void hidraw_disconnect(struct hid_device *hid)
360 362
361 hidraw->exist = 0; 363 hidraw->exist = 0;
362 364
363 spin_lock(&minors_lock); 365 mutex_lock(&minors_lock);
364 hidraw_table[hidraw->minor] = NULL; 366 hidraw_table[hidraw->minor] = NULL;
365 spin_unlock(&minors_lock); 367 mutex_unlock(&minors_lock);
366 368
367 device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor)); 369 device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor));
368 370
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 18e5ddd722cd..d746bf8284dd 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -781,6 +781,8 @@ static int usbhid_start(struct hid_device *hid)
781 unsigned int n, insize = 0; 781 unsigned int n, insize = 0;
782 int ret; 782 int ret;
783 783
784 clear_bit(HID_DISCONNECTED, &usbhid->iofl);
785
784 usbhid->bufsize = HID_MIN_BUFFER_SIZE; 786 usbhid->bufsize = HID_MIN_BUFFER_SIZE;
785 hid_find_max_report(hid, HID_INPUT_REPORT, &usbhid->bufsize); 787 hid_find_max_report(hid, HID_INPUT_REPORT, &usbhid->bufsize);
786 hid_find_max_report(hid, HID_OUTPUT_REPORT, &usbhid->bufsize); 788 hid_find_max_report(hid, HID_OUTPUT_REPORT, &usbhid->bufsize);
@@ -847,12 +849,6 @@ static int usbhid_start(struct hid_device *hid)
847 } 849 }
848 } 850 }
849 851
850 if (!usbhid->urbin) {
851 err_hid("couldn't find an input interrupt endpoint");
852 ret = -ENODEV;
853 goto fail;
854 }
855
856 init_waitqueue_head(&usbhid->wait); 852 init_waitqueue_head(&usbhid->wait);
857 INIT_WORK(&usbhid->reset_work, hid_reset); 853 INIT_WORK(&usbhid->reset_work, hid_reset);
858 setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid); 854 setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid);
@@ -888,6 +884,9 @@ fail:
888 usb_free_urb(usbhid->urbin); 884 usb_free_urb(usbhid->urbin);
889 usb_free_urb(usbhid->urbout); 885 usb_free_urb(usbhid->urbout);
890 usb_free_urb(usbhid->urbctrl); 886 usb_free_urb(usbhid->urbctrl);
887 usbhid->urbin = NULL;
888 usbhid->urbout = NULL;
889 usbhid->urbctrl = NULL;
891 hid_free_buffers(dev, hid); 890 hid_free_buffers(dev, hid);
892 mutex_unlock(&usbhid->setup); 891 mutex_unlock(&usbhid->setup);
893 return ret; 892 return ret;
@@ -924,6 +923,9 @@ static void usbhid_stop(struct hid_device *hid)
924 usb_free_urb(usbhid->urbin); 923 usb_free_urb(usbhid->urbin);
925 usb_free_urb(usbhid->urbctrl); 924 usb_free_urb(usbhid->urbctrl);
926 usb_free_urb(usbhid->urbout); 925 usb_free_urb(usbhid->urbout);
926 usbhid->urbin = NULL; /* don't mess up next start */
927 usbhid->urbctrl = NULL;
928 usbhid->urbout = NULL;
927 929
928 hid_free_buffers(hid_to_usb_dev(hid), hid); 930 hid_free_buffers(hid_to_usb_dev(hid), hid);
929 mutex_unlock(&usbhid->setup); 931 mutex_unlock(&usbhid->setup);
@@ -940,15 +942,26 @@ static struct hid_ll_driver usb_hid_driver = {
940 942
941static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id) 943static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
942{ 944{
945 struct usb_host_interface *interface = intf->cur_altsetting;
943 struct usb_device *dev = interface_to_usbdev(intf); 946 struct usb_device *dev = interface_to_usbdev(intf);
944 struct usbhid_device *usbhid; 947 struct usbhid_device *usbhid;
945 struct hid_device *hid; 948 struct hid_device *hid;
949 unsigned int n, has_in = 0;
946 size_t len; 950 size_t len;
947 int ret; 951 int ret;
948 952
949 dbg_hid("HID probe called for ifnum %d\n", 953 dbg_hid("HID probe called for ifnum %d\n",
950 intf->altsetting->desc.bInterfaceNumber); 954 intf->altsetting->desc.bInterfaceNumber);
951 955
956 for (n = 0; n < interface->desc.bNumEndpoints; n++)
957 if (usb_endpoint_is_int_in(&interface->endpoint[n].desc))
958 has_in++;
959 if (!has_in) {
960 dev_err(&intf->dev, "couldn't find an input interrupt "
961 "endpoint\n");
962 return -ENODEV;
963 }
964
952 hid = hid_allocate_device(); 965 hid = hid_allocate_device();
953 if (IS_ERR(hid)) 966 if (IS_ERR(hid))
954 return PTR_ERR(hid); 967 return PTR_ERR(hid);