diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-21 13:51:03 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-21 13:51:03 -0400 |
commit | 8b108c609adefd98577c35f0a41497a610041a6c (patch) | |
tree | f1552fdc5bf0ebcc484a88f01cd3864113adf25c /drivers/hid/usbhid | |
parent | 7ce1418f95e918cfc5ad36e3ec3431145c768cd0 (diff) | |
parent | 73d5e8f77e88a4d3a154dfdbb4ed2cf461b7bf21 (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: (59 commits)
HID: fix up 'EMBEDDED' mess in Kconfig
HID: roccat: cleanup preprocessor macros
HID: roccat: refactor special event handling
HID: roccat: fix special button support
HID: roccat: Correctly mark init and exit functions
HID: hidraw: Use Interrupt Endpoint for OUT Transfers if Available
HID: hid-samsung: remove redundant key mappings
HID: add omitted hid-zydacron.c file
HID: hid-samsung: add support for Creative Desktop Wireless 6000
HID: picolcd: Eliminate use after free
HID: Zydacron Remote Control driver
HID: Use kmemdup
HID: magicmouse: fix input registration
HID: make Prodikeys driver standalone config option
HID: Prodikeys PC-MIDI HID Driver
HID: hidraw: fix indentation
HID: ntrig: add filtering module parameters
HID: ntrig: add sysfs access to filter parameters
HID: ntrig: add sensitivity and responsiveness support
HID: add multi-input quirk for eGalax Touchcontroller
...
Diffstat (limited to 'drivers/hid/usbhid')
-rw-r--r-- | drivers/hid/usbhid/hid-core.c | 73 | ||||
-rw-r--r-- | drivers/hid/usbhid/hid-quirks.c | 1 | ||||
-rw-r--r-- | drivers/hid/usbhid/hiddev.c | 19 | ||||
-rw-r--r-- | drivers/hid/usbhid/usbkbd.c | 1 |
4 files changed, 79 insertions, 15 deletions
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index df619756b7ae..1ebd3244eb85 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c | |||
@@ -623,6 +623,7 @@ int usbhid_wait_io(struct hid_device *hid) | |||
623 | 623 | ||
624 | return 0; | 624 | return 0; |
625 | } | 625 | } |
626 | EXPORT_SYMBOL_GPL(usbhid_wait_io); | ||
626 | 627 | ||
627 | static int hid_set_idle(struct usb_device *dev, int ifnum, int report, int idle) | 628 | static int hid_set_idle(struct usb_device *dev, int ifnum, int report, int idle) |
628 | { | 629 | { |
@@ -806,16 +807,36 @@ static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t co | |||
806 | struct usb_host_interface *interface = intf->cur_altsetting; | 807 | struct usb_host_interface *interface = intf->cur_altsetting; |
807 | int ret; | 808 | int ret; |
808 | 809 | ||
809 | ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | 810 | if (usbhid->urbout) { |
810 | HID_REQ_SET_REPORT, | 811 | int actual_length; |
811 | USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, | 812 | int skipped_report_id = 0; |
812 | ((report_type + 1) << 8) | *buf, | 813 | if (buf[0] == 0x0) { |
813 | interface->desc.bInterfaceNumber, buf + 1, count - 1, | 814 | /* Don't send the Report ID */ |
814 | USB_CTRL_SET_TIMEOUT); | 815 | buf++; |
815 | 816 | count--; | |
816 | /* count also the report id */ | 817 | skipped_report_id = 1; |
817 | if (ret > 0) | 818 | } |
818 | ret++; | 819 | ret = usb_interrupt_msg(dev, usbhid->urbout->pipe, |
820 | buf, count, &actual_length, | ||
821 | USB_CTRL_SET_TIMEOUT); | ||
822 | /* return the number of bytes transferred */ | ||
823 | if (ret == 0) { | ||
824 | ret = actual_length; | ||
825 | /* count also the report id */ | ||
826 | if (skipped_report_id) | ||
827 | ret++; | ||
828 | } | ||
829 | } else { | ||
830 | ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | ||
831 | HID_REQ_SET_REPORT, | ||
832 | USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, | ||
833 | ((report_type + 1) << 8) | *buf, | ||
834 | interface->desc.bInterfaceNumber, buf + 1, count - 1, | ||
835 | USB_CTRL_SET_TIMEOUT); | ||
836 | /* count also the report id */ | ||
837 | if (ret > 0) | ||
838 | ret++; | ||
839 | } | ||
819 | 840 | ||
820 | return ret; | 841 | return ret; |
821 | } | 842 | } |
@@ -1017,12 +1038,15 @@ static int usbhid_start(struct hid_device *hid) | |||
1017 | /* Some keyboards don't work until their LEDs have been set. | 1038 | /* Some keyboards don't work until their LEDs have been set. |
1018 | * Since BIOSes do set the LEDs, it must be safe for any device | 1039 | * Since BIOSes do set the LEDs, it must be safe for any device |
1019 | * that supports the keyboard boot protocol. | 1040 | * that supports the keyboard boot protocol. |
1041 | * In addition, enable remote wakeup by default for all keyboard | ||
1042 | * devices supporting the boot protocol. | ||
1020 | */ | 1043 | */ |
1021 | if (interface->desc.bInterfaceSubClass == USB_INTERFACE_SUBCLASS_BOOT && | 1044 | if (interface->desc.bInterfaceSubClass == USB_INTERFACE_SUBCLASS_BOOT && |
1022 | interface->desc.bInterfaceProtocol == | 1045 | interface->desc.bInterfaceProtocol == |
1023 | USB_INTERFACE_PROTOCOL_KEYBOARD) | 1046 | USB_INTERFACE_PROTOCOL_KEYBOARD) { |
1024 | usbhid_set_leds(hid); | 1047 | usbhid_set_leds(hid); |
1025 | 1048 | device_set_wakeup_enable(&dev->dev, 1); | |
1049 | } | ||
1026 | return 0; | 1050 | return 0; |
1027 | 1051 | ||
1028 | fail: | 1052 | fail: |
@@ -1131,6 +1155,7 @@ static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id * | |||
1131 | hid->vendor = le16_to_cpu(dev->descriptor.idVendor); | 1155 | hid->vendor = le16_to_cpu(dev->descriptor.idVendor); |
1132 | hid->product = le16_to_cpu(dev->descriptor.idProduct); | 1156 | hid->product = le16_to_cpu(dev->descriptor.idProduct); |
1133 | hid->name[0] = 0; | 1157 | hid->name[0] = 0; |
1158 | hid->quirks = usbhid_lookup_quirk(hid->vendor, hid->product); | ||
1134 | if (intf->cur_altsetting->desc.bInterfaceProtocol == | 1159 | if (intf->cur_altsetting->desc.bInterfaceProtocol == |
1135 | USB_INTERFACE_PROTOCOL_MOUSE) | 1160 | USB_INTERFACE_PROTOCOL_MOUSE) |
1136 | hid->type = HID_TYPE_USBMOUSE; | 1161 | hid->type = HID_TYPE_USBMOUSE; |
@@ -1287,6 +1312,11 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message) | |||
1287 | { | 1312 | { |
1288 | set_bit(HID_REPORTED_IDLE, &usbhid->iofl); | 1313 | set_bit(HID_REPORTED_IDLE, &usbhid->iofl); |
1289 | spin_unlock_irq(&usbhid->lock); | 1314 | spin_unlock_irq(&usbhid->lock); |
1315 | if (hid->driver && hid->driver->suspend) { | ||
1316 | status = hid->driver->suspend(hid, message); | ||
1317 | if (status < 0) | ||
1318 | return status; | ||
1319 | } | ||
1290 | } else { | 1320 | } else { |
1291 | usbhid_mark_busy(usbhid); | 1321 | usbhid_mark_busy(usbhid); |
1292 | spin_unlock_irq(&usbhid->lock); | 1322 | spin_unlock_irq(&usbhid->lock); |
@@ -1294,6 +1324,11 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message) | |||
1294 | } | 1324 | } |
1295 | 1325 | ||
1296 | } else { | 1326 | } else { |
1327 | if (hid->driver && hid->driver->suspend) { | ||
1328 | status = hid->driver->suspend(hid, message); | ||
1329 | if (status < 0) | ||
1330 | return status; | ||
1331 | } | ||
1297 | spin_lock_irq(&usbhid->lock); | 1332 | spin_lock_irq(&usbhid->lock); |
1298 | set_bit(HID_REPORTED_IDLE, &usbhid->iofl); | 1333 | set_bit(HID_REPORTED_IDLE, &usbhid->iofl); |
1299 | spin_unlock_irq(&usbhid->lock); | 1334 | spin_unlock_irq(&usbhid->lock); |
@@ -1348,6 +1383,11 @@ static int hid_resume(struct usb_interface *intf) | |||
1348 | hid_io_error(hid); | 1383 | hid_io_error(hid); |
1349 | usbhid_restart_queues(usbhid); | 1384 | usbhid_restart_queues(usbhid); |
1350 | 1385 | ||
1386 | if (status >= 0 && hid->driver && hid->driver->resume) { | ||
1387 | int ret = hid->driver->resume(hid); | ||
1388 | if (ret < 0) | ||
1389 | status = ret; | ||
1390 | } | ||
1351 | dev_dbg(&intf->dev, "resume status %d\n", status); | 1391 | dev_dbg(&intf->dev, "resume status %d\n", status); |
1352 | return 0; | 1392 | return 0; |
1353 | } | 1393 | } |
@@ -1356,9 +1396,16 @@ static int hid_reset_resume(struct usb_interface *intf) | |||
1356 | { | 1396 | { |
1357 | struct hid_device *hid = usb_get_intfdata(intf); | 1397 | struct hid_device *hid = usb_get_intfdata(intf); |
1358 | struct usbhid_device *usbhid = hid->driver_data; | 1398 | struct usbhid_device *usbhid = hid->driver_data; |
1399 | int status; | ||
1359 | 1400 | ||
1360 | clear_bit(HID_REPORTED_IDLE, &usbhid->iofl); | 1401 | clear_bit(HID_REPORTED_IDLE, &usbhid->iofl); |
1361 | return hid_post_reset(intf); | 1402 | status = hid_post_reset(intf); |
1403 | if (status >= 0 && hid->driver && hid->driver->reset_resume) { | ||
1404 | int ret = hid->driver->reset_resume(hid); | ||
1405 | if (ret < 0) | ||
1406 | status = ret; | ||
1407 | } | ||
1408 | return status; | ||
1362 | } | 1409 | } |
1363 | 1410 | ||
1364 | #endif /* CONFIG_PM */ | 1411 | #endif /* CONFIG_PM */ |
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 1152f9b5fd44..5ff8d327f33a 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c | |||
@@ -33,6 +33,7 @@ static const struct hid_blacklist { | |||
33 | { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_PREDATOR, HID_QUIRK_BADPAD }, | 33 | { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_PREDATOR, HID_QUIRK_BADPAD }, |
34 | { USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD }, | 34 | { USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD }, |
35 | { USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD }, | 35 | { USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD }, |
36 | { USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH, HID_QUIRK_MULTI_INPUT }, | ||
36 | { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, | 37 | { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, |
37 | { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, | 38 | { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, |
38 | { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, | 39 | { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, |
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index 433602aed468..c24d2fa3e3b6 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c | |||
@@ -267,6 +267,7 @@ static int hiddev_open(struct inode *inode, struct file *file) | |||
267 | struct hiddev_list *list; | 267 | struct hiddev_list *list; |
268 | int res, i; | 268 | int res, i; |
269 | 269 | ||
270 | /* See comment in hiddev_connect() for BKL explanation */ | ||
270 | lock_kernel(); | 271 | lock_kernel(); |
271 | i = iminor(inode) - HIDDEV_MINOR_BASE; | 272 | i = iminor(inode) - HIDDEV_MINOR_BASE; |
272 | 273 | ||
@@ -894,8 +895,22 @@ int hiddev_connect(struct hid_device *hid, unsigned int force) | |||
894 | hiddev->hid = hid; | 895 | hiddev->hid = hid; |
895 | hiddev->exist = 1; | 896 | hiddev->exist = 1; |
896 | 897 | ||
897 | /* when lock_kernel() usage is fixed in usb_open(), | 898 | /* |
898 | * we could also fix it here */ | 899 | * BKL here is used to avoid race after usb_register_dev(). |
900 | * Once the device node has been created, open() could happen on it. | ||
901 | * The code below will then fail, as hiddev_table hasn't been | ||
902 | * updated. | ||
903 | * | ||
904 | * The obvious fix -- introducing mutex to guard hiddev_table[] | ||
905 | * doesn't work, as usb_open() and usb_register_dev() both take | ||
906 | * minor_rwsem, thus we'll have ABBA deadlock. | ||
907 | * | ||
908 | * Before BKL pushdown, usb_open() had been acquiring it in right | ||
909 | * order, so _open() was safe to use it to protect from this race. | ||
910 | * Now the order is different, but AB-BA deadlock still doesn't occur | ||
911 | * as BKL is dropped on schedule() (i.e. while sleeping on | ||
912 | * minor_rwsem). Fugly. | ||
913 | */ | ||
899 | lock_kernel(); | 914 | lock_kernel(); |
900 | retval = usb_register_dev(usbhid->intf, &hiddev_class); | 915 | retval = usb_register_dev(usbhid->intf, &hiddev_class); |
901 | if (retval) { | 916 | if (retval) { |
diff --git a/drivers/hid/usbhid/usbkbd.c b/drivers/hid/usbhid/usbkbd.c index bb14c8270af3..a948605564fb 100644 --- a/drivers/hid/usbhid/usbkbd.c +++ b/drivers/hid/usbhid/usbkbd.c | |||
@@ -311,6 +311,7 @@ static int usb_kbd_probe(struct usb_interface *iface, | |||
311 | goto fail2; | 311 | goto fail2; |
312 | 312 | ||
313 | usb_set_intfdata(iface, kbd); | 313 | usb_set_intfdata(iface, kbd); |
314 | device_set_wakeup_enable(&dev->dev, 1); | ||
314 | return 0; | 315 | return 0; |
315 | 316 | ||
316 | fail2: | 317 | fail2: |