On Thu, 2014-09-04 at 13:36 +0200, Johan Hovold wrote: > I got side-tracked with other stuff, but I should be able to submit the > patch this week (just want to look through it once more first). > > Not sure the mark-last-busy needs to be moved, though. The device has > already been woken up, and might as well stay unsuspended for a while > longer should further events occur. Hi, on second thought I think that your moving of remote_wakeup is not good. If we'd discard input anyway, we don't need to wake up devices for them. So here's a version that does it that way. Regards Oliver >From 46f2bba084c543922d6c67782d5ba47e663dbc37 Mon Sep 17 00:00:00 2001 From: Oliver Neukum <oneukum@xxxxxxx> Date: Wed, 3 Sep 2014 15:26:39 +0200 Subject: [PATCH] usbhid: Johan's patch for devices that need constant polling Some devices need constant polling or they crash. So move the start of IO from open() to start() Signed-off-by: Oliver Neukum <oneukum@xxxxxxx> --- drivers/hid/hid-ids.h | 1 + drivers/hid/usbhid/hid-core.c | 33 +++++++++++++++++++++++++++------ drivers/hid/usbhid/hid-quirks.c | 1 + include/linux/hid.h | 1 + 4 files changed, 30 insertions(+), 6 deletions(-) diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 25cd674..b303a62 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -733,6 +733,7 @@ #define USB_DEVICE_ID_PI_ENGINEERING_VEC_USB_FOOTPEDAL 0xff #define USB_VENDOR_ID_PIXART 0x093a +#define USB_DEVICE_ID_PIXART_USB_OPTICAL_MOUSE 0x2510 #define USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN 0x8001 #define USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1 0x8002 #define USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2 0x8003 diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 79cf503..b214d1e 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) struct usbhid_device *usbhid = hid->driver_data; spin_lock_irqsave(&usbhid->lock, flags); - if (hid->open > 0 && + if ((hid->open > 0 || hid->quirks & HID_QUIRK_ALWAYS_POLL) && !test_bit(HID_DISCONNECTED, &usbhid->iofl) && !test_bit(HID_SUSPENDED, &usbhid->iofl) && !test_and_set_bit(HID_IN_RUNNING, &usbhid->iofl)) { @@ -290,11 +290,17 @@ static void hid_irq_in(struct urb *urb) switch (urb->status) { case 0: /* success */ - usbhid_mark_busy(usbhid); usbhid->retry_delay = 0; - hid_input_report(urb->context, HID_INPUT_REPORT, - urb->transfer_buffer, - urb->actual_length, 1); + /* + * do not not report unrequested data + * neither should it count for autosuspend + */ + if (hid->open) { + usbhid_mark_busy(usbhid); + hid_input_report(urb->context, HID_INPUT_REPORT, + urb->transfer_buffer, + urb->actual_length, 1); + } /* * autosuspend refused while keys are pressed * because most keyboards don't wake up when @@ -735,7 +741,8 @@ void usbhid_close(struct hid_device *hid) if (!--hid->open) { spin_unlock_irq(&usbhid->lock); hid_cancel_delayed_stuff(usbhid); - usb_kill_urb(usbhid->urbin); + if (!(hid->quirks & HID_QUIRK_ALWAYS_POLL)) + usb_kill_urb(usbhid->urbin); usbhid->intf->needs_remote_wakeup = 0; } else { spin_unlock_irq(&usbhid->lock); @@ -1134,6 +1141,18 @@ static int usbhid_start(struct hid_device *hid) set_bit(HID_STARTED, &usbhid->iofl); + if (hid->quirks & HID_QUIRK_ALWAYS_POLL) { + ret = usb_autopm_get_interface(usbhid->intf); + if (ret) + goto fail; + ret = hid_start_in(hid); + if (ret) { + dev_err(&hid->dev, + "failed to start in urb: %d\n", ret); + } + usb_autopm_put_interface(usbhid->intf); + } + /* Some keyboards don't work until their LEDs have been set. * Since BIOSes do set the LEDs, it must be safe for any device * that supports the keyboard boot protocol. @@ -1166,6 +1185,8 @@ static void usbhid_stop(struct hid_device *hid) if (WARN_ON(!usbhid)) return; + usbhid->intf->needs_remote_wakeup = 0; + clear_bit(HID_STARTED, &usbhid->iofl); spin_lock_irq(&usbhid->lock); /* Sync with error and led handlers */ set_bit(HID_DISCONNECTED, &usbhid->iofl); diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 15225f3..79f94ae 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -79,6 +79,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_NOVATEK, USB_DEVICE_ID_NOVATEK_MOUSE, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_1610, HID_QUIRK_NOGET }, { USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_1640, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_USB_OPTICAL_MOUSE, HID_QUIRK_ALWAYS_POLL }, { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2, HID_QUIRK_NO_INIT_REPORTS }, diff --git a/include/linux/hid.h b/include/linux/hid.h index f53c4a9..26ee25f 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -287,6 +287,7 @@ struct hid_item { #define HID_QUIRK_HIDINPUT_FORCE 0x00000080 #define HID_QUIRK_NO_EMPTY_INPUT 0x00000100 #define HID_QUIRK_NO_INIT_INPUT_REPORTS 0x00000200 +#define HID_QUIRK_ALWAYS_POLL 0x00000400 #define HID_QUIRK_SKIP_OUTPUT_REPORTS 0x00010000 #define HID_QUIRK_SKIP_OUTPUT_REPORT_ID 0x00020000 #define HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP 0x00040000 -- 1.8.4.5 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html