aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid/usbhid
diff options
context:
space:
mode:
authorJohan Hovold <johan@kernel.org>2014-09-05 12:08:47 -0400
committerJiri Kosina <jkosina@suse.cz>2014-09-08 03:29:15 -0400
commit0b750b3baa2d64f1b77aecc10f20deeb28efe60d (patch)
tree1d60afffd83b736b23f9ca6fcec482bcd89c13fe /drivers/hid/usbhid
parentff0c57ac70434bc936cb0110eaf033a0a1a62e52 (diff)
HID: usbhid: add always-poll quirk
Add quirk to make sure that a device is always polled for input events even if it hasn't been opened. This is needed for devices that disconnects from the bus unless the interrupt endpoint has been polled at least once or when not responding to an input event (e.g. after having shut down X). Signed-off-by: Johan Hovold <johan@kernel.org> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid/usbhid')
-rw-r--r--drivers/hid/usbhid/hid-core.c26
1 files changed, 23 insertions, 3 deletions
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 79cf503e37bf..ddd547ad6d7e 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -82,7 +82,7 @@ static int hid_start_in(struct hid_device *hid)
82 struct usbhid_device *usbhid = hid->driver_data; 82 struct usbhid_device *usbhid = hid->driver_data;
83 83
84 spin_lock_irqsave(&usbhid->lock, flags); 84 spin_lock_irqsave(&usbhid->lock, flags);
85 if (hid->open > 0 && 85 if ((hid->open > 0 || hid->quirks & HID_QUIRK_ALWAYS_POLL) &&
86 !test_bit(HID_DISCONNECTED, &usbhid->iofl) && 86 !test_bit(HID_DISCONNECTED, &usbhid->iofl) &&
87 !test_bit(HID_SUSPENDED, &usbhid->iofl) && 87 !test_bit(HID_SUSPENDED, &usbhid->iofl) &&
88 !test_and_set_bit(HID_IN_RUNNING, &usbhid->iofl)) { 88 !test_and_set_bit(HID_IN_RUNNING, &usbhid->iofl)) {
@@ -292,6 +292,8 @@ static void hid_irq_in(struct urb *urb)
292 case 0: /* success */ 292 case 0: /* success */
293 usbhid_mark_busy(usbhid); 293 usbhid_mark_busy(usbhid);
294 usbhid->retry_delay = 0; 294 usbhid->retry_delay = 0;
295 if ((hid->quirks & HID_QUIRK_ALWAYS_POLL) && !hid->open)
296 break;
295 hid_input_report(urb->context, HID_INPUT_REPORT, 297 hid_input_report(urb->context, HID_INPUT_REPORT,
296 urb->transfer_buffer, 298 urb->transfer_buffer,
297 urb->actual_length, 1); 299 urb->actual_length, 1);
@@ -735,8 +737,10 @@ void usbhid_close(struct hid_device *hid)
735 if (!--hid->open) { 737 if (!--hid->open) {
736 spin_unlock_irq(&usbhid->lock); 738 spin_unlock_irq(&usbhid->lock);
737 hid_cancel_delayed_stuff(usbhid); 739 hid_cancel_delayed_stuff(usbhid);
738 usb_kill_urb(usbhid->urbin); 740 if (!(hid->quirks & HID_QUIRK_ALWAYS_POLL)) {
739 usbhid->intf->needs_remote_wakeup = 0; 741 usb_kill_urb(usbhid->urbin);
742 usbhid->intf->needs_remote_wakeup = 0;
743 }
740 } else { 744 } else {
741 spin_unlock_irq(&usbhid->lock); 745 spin_unlock_irq(&usbhid->lock);
742 } 746 }
@@ -1134,6 +1138,19 @@ static int usbhid_start(struct hid_device *hid)
1134 1138
1135 set_bit(HID_STARTED, &usbhid->iofl); 1139 set_bit(HID_STARTED, &usbhid->iofl);
1136 1140
1141 if (hid->quirks & HID_QUIRK_ALWAYS_POLL) {
1142 ret = usb_autopm_get_interface(usbhid->intf);
1143 if (ret)
1144 goto fail;
1145 usbhid->intf->needs_remote_wakeup = 1;
1146 ret = hid_start_in(hid);
1147 if (ret) {
1148 dev_err(&hid->dev,
1149 "failed to start in urb: %d\n", ret);
1150 }
1151 usb_autopm_put_interface(usbhid->intf);
1152 }
1153
1137 /* Some keyboards don't work until their LEDs have been set. 1154 /* Some keyboards don't work until their LEDs have been set.
1138 * Since BIOSes do set the LEDs, it must be safe for any device 1155 * Since BIOSes do set the LEDs, it must be safe for any device
1139 * that supports the keyboard boot protocol. 1156 * that supports the keyboard boot protocol.
@@ -1166,6 +1183,9 @@ static void usbhid_stop(struct hid_device *hid)
1166 if (WARN_ON(!usbhid)) 1183 if (WARN_ON(!usbhid))
1167 return; 1184 return;
1168 1185
1186 if (hid->quirks & HID_QUIRK_ALWAYS_POLL)
1187 usbhid->intf->needs_remote_wakeup = 0;
1188
1169 clear_bit(HID_STARTED, &usbhid->iofl); 1189 clear_bit(HID_STARTED, &usbhid->iofl);
1170 spin_lock_irq(&usbhid->lock); /* Sync with error and led handlers */ 1190 spin_lock_irq(&usbhid->lock); /* Sync with error and led handlers */
1171 set_bit(HID_DISCONNECTED, &usbhid->iofl); 1191 set_bit(HID_DISCONNECTED, &usbhid->iofl);