| From 08c5cd37480f59ea39682f4585d92269be6b1424 Mon Sep 17 00:00:00 2001 |
| From: Alan Stern <stern@rowland.harvard.edu> |
| Date: Fri, 16 Sep 2016 10:24:26 -0400 |
| Subject: USB: change bInterval default to 10 ms |
| |
| From: Alan Stern <stern@rowland.harvard.edu> |
| |
| commit 08c5cd37480f59ea39682f4585d92269be6b1424 upstream. |
| |
| Some full-speed mceusb infrared transceivers contain invalid endpoint |
| descriptors for their interrupt endpoints, with bInterval set to 0. |
| In the past they have worked out okay with the mceusb driver, because |
| the driver sets the bInterval field in the descriptor to 1, |
| overwriting whatever value may have been there before. However, this |
| approach was never sanctioned by the USB core, and in fact it does not |
| work with xHCI controllers, because they use the bInterval value that |
| was present when the configuration was installed. |
| |
| Currently usbcore uses 32 ms as the default interval if the value in |
| the endpoint descriptor is invalid. It turns out that these IR |
| transceivers don't work properly unless the interval is set to 10 ms |
| or below. To work around this mceusb problem, this patch changes the |
| endpoint-descriptor parsing routine, making the default interval value |
| be 10 ms rather than 32 ms. |
| |
| Signed-off-by: Alan Stern <stern@rowland.harvard.edu> |
| Tested-by: Wade Berrier <wberrier@gmail.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/usb/core/config.c | 28 +++++++++++++++++----------- |
| 1 file changed, 17 insertions(+), 11 deletions(-) |
| |
| --- a/drivers/usb/core/config.c |
| +++ b/drivers/usb/core/config.c |
| @@ -211,8 +211,10 @@ static int usb_parse_endpoint(struct dev |
| memcpy(&endpoint->desc, d, n); |
| INIT_LIST_HEAD(&endpoint->urb_list); |
| |
| - /* Fix up bInterval values outside the legal range. Use 32 ms if no |
| - * proper value can be guessed. */ |
| + /* |
| + * Fix up bInterval values outside the legal range. |
| + * Use 10 or 8 ms if no proper value can be guessed. |
| + */ |
| i = 0; /* i = min, j = max, n = default */ |
| j = 255; |
| if (usb_endpoint_xfer_int(d)) { |
| @@ -221,13 +223,15 @@ static int usb_parse_endpoint(struct dev |
| case USB_SPEED_SUPER_PLUS: |
| case USB_SPEED_SUPER: |
| case USB_SPEED_HIGH: |
| - /* Many device manufacturers are using full-speed |
| + /* |
| + * Many device manufacturers are using full-speed |
| * bInterval values in high-speed interrupt endpoint |
| - * descriptors. Try to fix those and fall back to a |
| - * 32 ms default value otherwise. */ |
| + * descriptors. Try to fix those and fall back to an |
| + * 8-ms default value otherwise. |
| + */ |
| n = fls(d->bInterval*8); |
| if (n == 0) |
| - n = 9; /* 32 ms = 2^(9-1) uframes */ |
| + n = 7; /* 8 ms = 2^(7-1) uframes */ |
| j = 16; |
| |
| /* |
| @@ -242,10 +246,12 @@ static int usb_parse_endpoint(struct dev |
| } |
| break; |
| default: /* USB_SPEED_FULL or _LOW */ |
| - /* For low-speed, 10 ms is the official minimum. |
| + /* |
| + * For low-speed, 10 ms is the official minimum. |
| * But some "overclocked" devices might want faster |
| - * polling so we'll allow it. */ |
| - n = 32; |
| + * polling so we'll allow it. |
| + */ |
| + n = 10; |
| break; |
| } |
| } else if (usb_endpoint_xfer_isoc(d)) { |
| @@ -253,10 +259,10 @@ static int usb_parse_endpoint(struct dev |
| j = 16; |
| switch (to_usb_device(ddev)->speed) { |
| case USB_SPEED_HIGH: |
| - n = 9; /* 32 ms = 2^(9-1) uframes */ |
| + n = 7; /* 8 ms = 2^(7-1) uframes */ |
| break; |
| default: /* USB_SPEED_FULL */ |
| - n = 6; /* 32 ms = 2^(6-1) frames */ |
| + n = 4; /* 8 ms = 2^(4-1) frames */ |
| break; |
| } |
| } |