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