diff options
| -rw-r--r-- | drivers/usb/core/config.c | 42 |
1 files changed, 41 insertions, 1 deletions
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c index 2d4fd530e5e4..dd3482328ad2 100644 --- a/drivers/usb/core/config.c +++ b/drivers/usb/core/config.c | |||
| @@ -1,4 +1,5 @@ | |||
| 1 | #include <linux/usb.h> | 1 | #include <linux/usb.h> |
| 2 | #include <linux/usb/ch9.h> | ||
| 2 | #include <linux/module.h> | 3 | #include <linux/module.h> |
| 3 | #include <linux/init.h> | 4 | #include <linux/init.h> |
| 4 | #include <linux/slab.h> | 5 | #include <linux/slab.h> |
| @@ -49,7 +50,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum, | |||
| 49 | unsigned char *buffer0 = buffer; | 50 | unsigned char *buffer0 = buffer; |
| 50 | struct usb_endpoint_descriptor *d; | 51 | struct usb_endpoint_descriptor *d; |
| 51 | struct usb_host_endpoint *endpoint; | 52 | struct usb_host_endpoint *endpoint; |
| 52 | int n, i; | 53 | int n, i, j; |
| 53 | 54 | ||
| 54 | d = (struct usb_endpoint_descriptor *) buffer; | 55 | d = (struct usb_endpoint_descriptor *) buffer; |
| 55 | buffer += d->bLength; | 56 | buffer += d->bLength; |
| @@ -84,6 +85,45 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum, | |||
| 84 | memcpy(&endpoint->desc, d, n); | 85 | memcpy(&endpoint->desc, d, n); |
| 85 | INIT_LIST_HEAD(&endpoint->urb_list); | 86 | INIT_LIST_HEAD(&endpoint->urb_list); |
| 86 | 87 | ||
| 88 | /* If the bInterval value is outside the legal range, | ||
| 89 | * set it to a default value: 32 ms */ | ||
| 90 | i = 0; /* i = min, j = max, n = default */ | ||
| 91 | j = 255; | ||
| 92 | if (usb_endpoint_xfer_int(d)) { | ||
| 93 | i = 1; | ||
| 94 | switch (to_usb_device(ddev)->speed) { | ||
| 95 | case USB_SPEED_HIGH: | ||
| 96 | n = 9; /* 32 ms = 2^(9-1) uframes */ | ||
| 97 | j = 16; | ||
| 98 | break; | ||
| 99 | default: /* USB_SPEED_FULL or _LOW */ | ||
| 100 | /* For low-speed, 10 ms is the official minimum. | ||
| 101 | * But some "overclocked" devices might want faster | ||
| 102 | * polling so we'll allow it. */ | ||
| 103 | n = 32; | ||
| 104 | break; | ||
| 105 | } | ||
| 106 | } else if (usb_endpoint_xfer_isoc(d)) { | ||
| 107 | i = 1; | ||
| 108 | j = 16; | ||
| 109 | switch (to_usb_device(ddev)->speed) { | ||
| 110 | case USB_SPEED_HIGH: | ||
| 111 | n = 9; /* 32 ms = 2^(9-1) uframes */ | ||
| 112 | break; | ||
| 113 | default: /* USB_SPEED_FULL */ | ||
| 114 | n = 6; /* 32 ms = 2^(6-1) frames */ | ||
| 115 | break; | ||
| 116 | } | ||
| 117 | } | ||
| 118 | if (d->bInterval < i || d->bInterval > j) { | ||
| 119 | dev_warn(ddev, "config %d interface %d altsetting %d " | ||
| 120 | "endpoint 0x%X has an invalid bInterval %d, " | ||
| 121 | "changing to %d\n", | ||
| 122 | cfgno, inum, asnum, | ||
| 123 | d->bEndpointAddress, d->bInterval, n); | ||
| 124 | endpoint->desc.bInterval = n; | ||
| 125 | } | ||
| 126 | |||
| 87 | /* Skip over any Class Specific or Vendor Specific descriptors; | 127 | /* Skip over any Class Specific or Vendor Specific descriptors; |
| 88 | * find the next endpoint or interface descriptor */ | 128 | * find the next endpoint or interface descriptor */ |
| 89 | endpoint->extra = buffer; | 129 | endpoint->extra = buffer; |
