diff options
| -rw-r--r-- | drivers/hid/usbhid/hid-core.c | 26 | ||||
| -rw-r--r-- | include/linux/hid.h | 1 |
2 files changed, 24 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); |
diff --git a/include/linux/hid.h b/include/linux/hid.h index f53c4a9cca1d..26ee25fced27 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h | |||
| @@ -287,6 +287,7 @@ struct hid_item { | |||
| 287 | #define HID_QUIRK_HIDINPUT_FORCE 0x00000080 | 287 | #define HID_QUIRK_HIDINPUT_FORCE 0x00000080 |
| 288 | #define HID_QUIRK_NO_EMPTY_INPUT 0x00000100 | 288 | #define HID_QUIRK_NO_EMPTY_INPUT 0x00000100 |
| 289 | #define HID_QUIRK_NO_INIT_INPUT_REPORTS 0x00000200 | 289 | #define HID_QUIRK_NO_INIT_INPUT_REPORTS 0x00000200 |
| 290 | #define HID_QUIRK_ALWAYS_POLL 0x00000400 | ||
| 290 | #define HID_QUIRK_SKIP_OUTPUT_REPORTS 0x00010000 | 291 | #define HID_QUIRK_SKIP_OUTPUT_REPORTS 0x00010000 |
| 291 | #define HID_QUIRK_SKIP_OUTPUT_REPORT_ID 0x00020000 | 292 | #define HID_QUIRK_SKIP_OUTPUT_REPORT_ID 0x00020000 |
| 292 | #define HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP 0x00040000 | 293 | #define HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP 0x00040000 |
