This patch adds a usb quirk to support devices with bInterval values
expressed as microframes. The quirk causes the parse endpoint function
to modify the reported bInterval to a standards conforming value.

There is currently code in the endpoint parser that checks for
bIntervals that are outside of the valid range (1-16 for USB 2+).
In this case, the code assumes the bInterval is being reported in
1ms frames. As well, the correction is only applied if the original
bInterval value is out of the 1-16 range.

With this quirk applied to the device, the bInterval will be
accurately adjusted from microframes to an exponent.

Signed-off-by: James P Michels III <james.p.mich...@gmail.com>
---
 drivers/usb/core/config.c  | 9 +++++++++
 drivers/usb/core/quirks.c  | 4 ++++
 include/linux/usb/quirks.h | 9 +++++++++
 3 files changed, 22 insertions(+)

diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
index 1ab4df1..191ce69 100644
--- a/drivers/usb/core/config.c
+++ b/drivers/usb/core/config.c
@@ -199,6 +199,15 @@ static int usb_parse_endpoint(struct device *ddev, int 
cfgno, int inum,
                        if (n == 0)
                                n = 9;  /* 32 ms = 2^(9-1) uframes */
                        j = 16;
+
+                       /* Adjust bInterval for quirked devices.
+                        * This quirk fixes bIntervals reported in
+                        * linear microframes. */
+                       if (to_usb_device(ddev)->quirks &
+                               USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL) {
+                               n = clamp(fls(d->bInterval), i, j);
+                               i = j = n;
+                               }
                        break;
                default:                /* USB_SPEED_FULL or _LOW */
                        /* For low-speed, 10 ms is the official minimum.
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
index 739ee8e..33c42de 100644
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -145,6 +145,10 @@ static const struct usb_device_id usb_quirk_list[] = {
        /* SKYMEDI USB_DRIVE */
        { USB_DEVICE(0x1516, 0x8628), .driver_info = USB_QUIRK_RESET_RESUME },
 
+       /* Razer - Razer Blade Keyboard */
+       { USB_DEVICE(0x1532, 0x0116), .driver_info =
+                       USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL },
+
        /* BUILDWIN Photo Frame */
        { USB_DEVICE(0x1908, 0x1315), .driver_info =
                        USB_QUIRK_HONOR_BNUMINTERFACES },
diff --git a/include/linux/usb/quirks.h b/include/linux/usb/quirks.h
index 52f944d..9219995 100644
--- a/include/linux/usb/quirks.h
+++ b/include/linux/usb/quirks.h
@@ -30,4 +30,13 @@
    descriptor */
 #define USB_QUIRK_DELAY_INIT           0x00000040
 
+/* The USB 2.0 and USB 3.0 spec require the interval in microframes
+   (1 microframe = 125 microseconds) to be calculated as
+   interval = 2 ^ (bInterval -1).
+
+   Devices with this quirk report their bInterval as the result of
+   this calculation instead of the exponent variable used in the
+   calculation */
+#define USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL 0x00000080
+
 #endif /* __LINUX_USB_QUIRKS_H */
-- 
1.9.1

--
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