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 <oneu...@suse.de>
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 <oneu...@suse.de>
---
 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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to