blob: 568244c99bdc0f5d7b0e03d2177d1153e9d49d49 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001#include <linux/usb.h>
Alan Stern615ae112007-06-08 15:23:27 -04002#include <linux/usb/ch9.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -07003#include <linux/module.h>
4#include <linux/init.h>
5#include <linux/slab.h>
6#include <linux/device.h>
7#include <asm/byteorder.h>
Greg KH6d5e8252005-04-18 17:39:24 -07008#include "usb.h"
9#include "hcd.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070010
11#define USB_MAXALTSETTING 128 /* Hard limit */
12#define USB_MAXENDPOINTS 30 /* Hard limit */
13
14#define USB_MAXCONFIG 8 /* Arbitrary limit */
15
16
17static inline const char *plural(int n)
18{
19 return (n == 1 ? "" : "s");
20}
21
22static int find_next_descriptor(unsigned char *buffer, int size,
23 int dt1, int dt2, int *num_skipped)
24{
25 struct usb_descriptor_header *h;
26 int n = 0;
27 unsigned char *buffer0 = buffer;
28
29 /* Find the next descriptor of type dt1 or dt2 */
30 while (size > 0) {
31 h = (struct usb_descriptor_header *) buffer;
32 if (h->bDescriptorType == dt1 || h->bDescriptorType == dt2)
33 break;
34 buffer += h->bLength;
35 size -= h->bLength;
36 ++n;
37 }
38
39 /* Store the number of descriptors skipped and return the
40 * number of bytes skipped */
41 if (num_skipped)
42 *num_skipped = n;
43 return buffer - buffer0;
44}
45
46static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
47 int asnum, struct usb_host_interface *ifp, int num_ep,
48 unsigned char *buffer, int size)
49{
50 unsigned char *buffer0 = buffer;
51 struct usb_endpoint_descriptor *d;
52 struct usb_host_endpoint *endpoint;
Alan Stern615ae112007-06-08 15:23:27 -040053 int n, i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -070054
55 d = (struct usb_endpoint_descriptor *) buffer;
56 buffer += d->bLength;
57 size -= d->bLength;
58
59 if (d->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE)
60 n = USB_DT_ENDPOINT_AUDIO_SIZE;
61 else if (d->bLength >= USB_DT_ENDPOINT_SIZE)
62 n = USB_DT_ENDPOINT_SIZE;
63 else {
64 dev_warn(ddev, "config %d interface %d altsetting %d has an "
65 "invalid endpoint descriptor of length %d, skipping\n",
66 cfgno, inum, asnum, d->bLength);
67 goto skip_to_next_endpoint_or_interface_descriptor;
68 }
69
70 i = d->bEndpointAddress & ~USB_ENDPOINT_DIR_MASK;
71 if (i >= 16 || i == 0) {
72 dev_warn(ddev, "config %d interface %d altsetting %d has an "
73 "invalid endpoint with address 0x%X, skipping\n",
74 cfgno, inum, asnum, d->bEndpointAddress);
75 goto skip_to_next_endpoint_or_interface_descriptor;
76 }
77
78 /* Only store as many endpoints as we have room for */
79 if (ifp->desc.bNumEndpoints >= num_ep)
80 goto skip_to_next_endpoint_or_interface_descriptor;
81
82 endpoint = &ifp->endpoint[ifp->desc.bNumEndpoints];
83 ++ifp->desc.bNumEndpoints;
84
85 memcpy(&endpoint->desc, d, n);
86 INIT_LIST_HEAD(&endpoint->urb_list);
87
Laurent Pinchart300871c2007-06-12 21:47:17 +020088 /* Fix up bInterval values outside the legal range. Use 32 ms if no
89 * proper value can be guessed. */
Alan Stern615ae112007-06-08 15:23:27 -040090 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:
Laurent Pinchart300871c2007-06-12 21:47:17 +020096 /* Many device manufacturers are using full-speed
97 * bInterval values in high-speed interrupt endpoint
98 * descriptors. Try to fix those and fall back to a
99 * 32 ms default value otherwise. */
100 n = fls(d->bInterval*8);
101 if (n == 0)
102 n = 9; /* 32 ms = 2^(9-1) uframes */
Alan Stern615ae112007-06-08 15:23:27 -0400103 j = 16;
104 break;
105 default: /* USB_SPEED_FULL or _LOW */
106 /* For low-speed, 10 ms is the official minimum.
107 * But some "overclocked" devices might want faster
108 * polling so we'll allow it. */
109 n = 32;
110 break;
111 }
112 } else if (usb_endpoint_xfer_isoc(d)) {
113 i = 1;
114 j = 16;
115 switch (to_usb_device(ddev)->speed) {
116 case USB_SPEED_HIGH:
117 n = 9; /* 32 ms = 2^(9-1) uframes */
118 break;
119 default: /* USB_SPEED_FULL */
120 n = 6; /* 32 ms = 2^(6-1) frames */
121 break;
122 }
123 }
124 if (d->bInterval < i || d->bInterval > j) {
125 dev_warn(ddev, "config %d interface %d altsetting %d "
126 "endpoint 0x%X has an invalid bInterval %d, "
127 "changing to %d\n",
128 cfgno, inum, asnum,
129 d->bEndpointAddress, d->bInterval, n);
130 endpoint->desc.bInterval = n;
131 }
132
Alan Stern60aac1e2007-06-08 15:25:02 -0400133 /* Some buggy low-speed devices have Bulk endpoints, which is
134 * explicitly forbidden by the USB spec. In an attempt to make
135 * them usable, we will try treating them as Interrupt endpoints.
136 */
137 if (to_usb_device(ddev)->speed == USB_SPEED_LOW &&
138 usb_endpoint_xfer_bulk(d)) {
139 dev_warn(ddev, "config %d interface %d altsetting %d "
140 "endpoint 0x%X is Bulk; changing to Interrupt\n",
141 cfgno, inum, asnum, d->bEndpointAddress);
142 endpoint->desc.bmAttributes = USB_ENDPOINT_XFER_INT;
143 endpoint->desc.bInterval = 1;
144 if (le16_to_cpu(endpoint->desc.wMaxPacketSize) > 8)
145 endpoint->desc.wMaxPacketSize = cpu_to_le16(8);
146 }
147
David Brownellcaa9ef62008-02-08 15:08:44 -0800148 /*
149 * Some buggy high speed devices have bulk endpoints using
150 * maxpacket sizes other than 512. High speed HCDs may not
151 * be able to handle that particular bug, so let's warn...
152 */
153 if (to_usb_device(ddev)->speed == USB_SPEED_HIGH
154 && usb_endpoint_xfer_bulk(d)) {
155 unsigned maxp;
156
157 maxp = le16_to_cpu(endpoint->desc.wMaxPacketSize) & 0x07ff;
158 if (maxp != 512)
159 dev_warn(ddev, "config %d interface %d altsetting %d "
160 "bulk endpoint 0x%X has invalid maxpacket %d\n",
161 cfgno, inum, asnum, d->bEndpointAddress,
162 maxp);
163 }
164
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165 /* Skip over any Class Specific or Vendor Specific descriptors;
166 * find the next endpoint or interface descriptor */
167 endpoint->extra = buffer;
168 i = find_next_descriptor(buffer, size, USB_DT_ENDPOINT,
169 USB_DT_INTERFACE, &n);
170 endpoint->extralen = i;
171 if (n > 0)
172 dev_dbg(ddev, "skipped %d descriptor%s after %s\n",
173 n, plural(n), "endpoint");
174 return buffer - buffer0 + i;
175
176skip_to_next_endpoint_or_interface_descriptor:
177 i = find_next_descriptor(buffer, size, USB_DT_ENDPOINT,
178 USB_DT_INTERFACE, NULL);
179 return buffer - buffer0 + i;
180}
181
182void usb_release_interface_cache(struct kref *ref)
183{
184 struct usb_interface_cache *intfc = ref_to_usb_interface_cache(ref);
185 int j;
186
Alan Stern4f62efe2005-10-24 16:24:14 -0400187 for (j = 0; j < intfc->num_altsetting; j++) {
188 struct usb_host_interface *alt = &intfc->altsetting[j];
189
190 kfree(alt->endpoint);
191 kfree(alt->string);
192 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193 kfree(intfc);
194}
195
196static int usb_parse_interface(struct device *ddev, int cfgno,
197 struct usb_host_config *config, unsigned char *buffer, int size,
198 u8 inums[], u8 nalts[])
199{
200 unsigned char *buffer0 = buffer;
201 struct usb_interface_descriptor *d;
202 int inum, asnum;
203 struct usb_interface_cache *intfc;
204 struct usb_host_interface *alt;
205 int i, n;
206 int len, retval;
207 int num_ep, num_ep_orig;
208
209 d = (struct usb_interface_descriptor *) buffer;
210 buffer += d->bLength;
211 size -= d->bLength;
212
213 if (d->bLength < USB_DT_INTERFACE_SIZE)
214 goto skip_to_next_interface_descriptor;
215
216 /* Which interface entry is this? */
217 intfc = NULL;
218 inum = d->bInterfaceNumber;
219 for (i = 0; i < config->desc.bNumInterfaces; ++i) {
220 if (inums[i] == inum) {
221 intfc = config->intf_cache[i];
222 break;
223 }
224 }
225 if (!intfc || intfc->num_altsetting >= nalts[i])
226 goto skip_to_next_interface_descriptor;
227
228 /* Check for duplicate altsetting entries */
229 asnum = d->bAlternateSetting;
230 for ((i = 0, alt = &intfc->altsetting[0]);
231 i < intfc->num_altsetting;
232 (++i, ++alt)) {
233 if (alt->desc.bAlternateSetting == asnum) {
234 dev_warn(ddev, "Duplicate descriptor for config %d "
235 "interface %d altsetting %d, skipping\n",
236 cfgno, inum, asnum);
237 goto skip_to_next_interface_descriptor;
238 }
239 }
240
241 ++intfc->num_altsetting;
242 memcpy(&alt->desc, d, USB_DT_INTERFACE_SIZE);
243
244 /* Skip over any Class Specific or Vendor Specific descriptors;
245 * find the first endpoint or interface descriptor */
246 alt->extra = buffer;
247 i = find_next_descriptor(buffer, size, USB_DT_ENDPOINT,
248 USB_DT_INTERFACE, &n);
249 alt->extralen = i;
250 if (n > 0)
251 dev_dbg(ddev, "skipped %d descriptor%s after %s\n",
252 n, plural(n), "interface");
253 buffer += i;
254 size -= i;
255
256 /* Allocate space for the right(?) number of endpoints */
257 num_ep = num_ep_orig = alt->desc.bNumEndpoints;
Greg Kroah-Hartman2c044a42008-01-30 15:21:33 -0800258 alt->desc.bNumEndpoints = 0; /* Use as a counter */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259 if (num_ep > USB_MAXENDPOINTS) {
260 dev_warn(ddev, "too many endpoints for config %d interface %d "
261 "altsetting %d: %d, using maximum allowed: %d\n",
262 cfgno, inum, asnum, num_ep, USB_MAXENDPOINTS);
263 num_ep = USB_MAXENDPOINTS;
264 }
265
Greg Kroah-Hartman2c044a42008-01-30 15:21:33 -0800266 if (num_ep > 0) {
267 /* Can't allocate 0 bytes */
Alan Stern57a21c12007-05-15 17:40:37 -0400268 len = sizeof(struct usb_host_endpoint) * num_ep;
269 alt->endpoint = kzalloc(len, GFP_KERNEL);
270 if (!alt->endpoint)
271 return -ENOMEM;
272 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273
274 /* Parse all the endpoint descriptors */
275 n = 0;
276 while (size > 0) {
277 if (((struct usb_descriptor_header *) buffer)->bDescriptorType
278 == USB_DT_INTERFACE)
279 break;
280 retval = usb_parse_endpoint(ddev, cfgno, inum, asnum, alt,
281 num_ep, buffer, size);
282 if (retval < 0)
283 return retval;
284 ++n;
285
286 buffer += retval;
287 size -= retval;
288 }
289
290 if (n != num_ep_orig)
291 dev_warn(ddev, "config %d interface %d altsetting %d has %d "
292 "endpoint descriptor%s, different from the interface "
293 "descriptor's value: %d\n",
294 cfgno, inum, asnum, n, plural(n), num_ep_orig);
295 return buffer - buffer0;
296
297skip_to_next_interface_descriptor:
298 i = find_next_descriptor(buffer, size, USB_DT_INTERFACE,
299 USB_DT_INTERFACE, NULL);
300 return buffer - buffer0 + i;
301}
302
303static int usb_parse_configuration(struct device *ddev, int cfgidx,
304 struct usb_host_config *config, unsigned char *buffer, int size)
305{
306 unsigned char *buffer0 = buffer;
307 int cfgno;
308 int nintf, nintf_orig;
309 int i, j, n;
310 struct usb_interface_cache *intfc;
311 unsigned char *buffer2;
312 int size2;
313 struct usb_descriptor_header *header;
314 int len, retval;
315 u8 inums[USB_MAXINTERFACES], nalts[USB_MAXINTERFACES];
Craig W. Nadler165fe972007-06-15 23:14:35 -0400316 unsigned iad_num = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317
318 memcpy(&config->desc, buffer, USB_DT_CONFIG_SIZE);
319 if (config->desc.bDescriptorType != USB_DT_CONFIG ||
320 config->desc.bLength < USB_DT_CONFIG_SIZE) {
321 dev_err(ddev, "invalid descriptor for config index %d: "
322 "type = 0x%X, length = %d\n", cfgidx,
323 config->desc.bDescriptorType, config->desc.bLength);
324 return -EINVAL;
325 }
326 cfgno = config->desc.bConfigurationValue;
327
328 buffer += config->desc.bLength;
329 size -= config->desc.bLength;
330
331 nintf = nintf_orig = config->desc.bNumInterfaces;
332 if (nintf > USB_MAXINTERFACES) {
333 dev_warn(ddev, "config %d has too many interfaces: %d, "
334 "using maximum allowed: %d\n",
335 cfgno, nintf, USB_MAXINTERFACES);
336 nintf = USB_MAXINTERFACES;
337 }
338
339 /* Go through the descriptors, checking their length and counting the
340 * number of altsettings for each interface */
341 n = 0;
342 for ((buffer2 = buffer, size2 = size);
343 size2 > 0;
344 (buffer2 += header->bLength, size2 -= header->bLength)) {
345
346 if (size2 < sizeof(struct usb_descriptor_header)) {
347 dev_warn(ddev, "config %d descriptor has %d excess "
348 "byte%s, ignoring\n",
349 cfgno, size2, plural(size2));
350 break;
351 }
352
353 header = (struct usb_descriptor_header *) buffer2;
354 if ((header->bLength > size2) || (header->bLength < 2)) {
355 dev_warn(ddev, "config %d has an invalid descriptor "
356 "of length %d, skipping remainder of the config\n",
357 cfgno, header->bLength);
358 break;
359 }
360
361 if (header->bDescriptorType == USB_DT_INTERFACE) {
362 struct usb_interface_descriptor *d;
363 int inum;
364
365 d = (struct usb_interface_descriptor *) header;
366 if (d->bLength < USB_DT_INTERFACE_SIZE) {
367 dev_warn(ddev, "config %d has an invalid "
368 "interface descriptor of length %d, "
369 "skipping\n", cfgno, d->bLength);
370 continue;
371 }
372
373 inum = d->bInterfaceNumber;
374 if (inum >= nintf_orig)
375 dev_warn(ddev, "config %d has an invalid "
376 "interface number: %d but max is %d\n",
377 cfgno, inum, nintf_orig - 1);
378
379 /* Have we already encountered this interface?
380 * Count its altsettings */
381 for (i = 0; i < n; ++i) {
382 if (inums[i] == inum)
383 break;
384 }
385 if (i < n) {
386 if (nalts[i] < 255)
387 ++nalts[i];
388 } else if (n < USB_MAXINTERFACES) {
389 inums[n] = inum;
390 nalts[n] = 1;
391 ++n;
392 }
393
Craig W. Nadler165fe972007-06-15 23:14:35 -0400394 } else if (header->bDescriptorType ==
395 USB_DT_INTERFACE_ASSOCIATION) {
396 if (iad_num == USB_MAXIADS) {
397 dev_warn(ddev, "found more Interface "
398 "Association Descriptors "
399 "than allocated for in "
400 "configuration %d\n", cfgno);
401 } else {
402 config->intf_assoc[iad_num] =
403 (struct usb_interface_assoc_descriptor
404 *)header;
405 iad_num++;
406 }
407
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408 } else if (header->bDescriptorType == USB_DT_DEVICE ||
409 header->bDescriptorType == USB_DT_CONFIG)
410 dev_warn(ddev, "config %d contains an unexpected "
411 "descriptor of type 0x%X, skipping\n",
412 cfgno, header->bDescriptorType);
413
414 } /* for ((buffer2 = buffer, size2 = size); ...) */
415 size = buffer2 - buffer;
416 config->desc.wTotalLength = cpu_to_le16(buffer2 - buffer0);
417
418 if (n != nintf)
419 dev_warn(ddev, "config %d has %d interface%s, different from "
420 "the descriptor's value: %d\n",
421 cfgno, n, plural(n), nintf_orig);
422 else if (n == 0)
423 dev_warn(ddev, "config %d has no interfaces?\n", cfgno);
424 config->desc.bNumInterfaces = nintf = n;
425
426 /* Check for missing interface numbers */
427 for (i = 0; i < nintf; ++i) {
428 for (j = 0; j < nintf; ++j) {
429 if (inums[j] == i)
430 break;
431 }
432 if (j >= nintf)
433 dev_warn(ddev, "config %d has no interface number "
434 "%d\n", cfgno, i);
435 }
436
437 /* Allocate the usb_interface_caches and altsetting arrays */
438 for (i = 0; i < nintf; ++i) {
439 j = nalts[i];
440 if (j > USB_MAXALTSETTING) {
441 dev_warn(ddev, "too many alternate settings for "
442 "config %d interface %d: %d, "
443 "using maximum allowed: %d\n",
444 cfgno, inums[i], j, USB_MAXALTSETTING);
445 nalts[i] = j = USB_MAXALTSETTING;
446 }
447
448 len = sizeof(*intfc) + sizeof(struct usb_host_interface) * j;
Alan Stern0a1ef3b2005-10-24 15:38:24 -0400449 config->intf_cache[i] = intfc = kzalloc(len, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450 if (!intfc)
451 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452 kref_init(&intfc->ref);
453 }
454
455 /* Skip over any Class Specific or Vendor Specific descriptors;
456 * find the first interface descriptor */
457 config->extra = buffer;
458 i = find_next_descriptor(buffer, size, USB_DT_INTERFACE,
459 USB_DT_INTERFACE, &n);
460 config->extralen = i;
461 if (n > 0)
462 dev_dbg(ddev, "skipped %d descriptor%s after %s\n",
463 n, plural(n), "configuration");
464 buffer += i;
465 size -= i;
466
467 /* Parse all the interface/altsetting descriptors */
468 while (size > 0) {
469 retval = usb_parse_interface(ddev, cfgno, config,
470 buffer, size, inums, nalts);
471 if (retval < 0)
472 return retval;
473
474 buffer += retval;
475 size -= retval;
476 }
477
478 /* Check for missing altsettings */
479 for (i = 0; i < nintf; ++i) {
480 intfc = config->intf_cache[i];
481 for (j = 0; j < intfc->num_altsetting; ++j) {
482 for (n = 0; n < intfc->num_altsetting; ++n) {
483 if (intfc->altsetting[n].desc.
484 bAlternateSetting == j)
485 break;
486 }
487 if (n >= intfc->num_altsetting)
488 dev_warn(ddev, "config %d interface %d has no "
489 "altsetting %d\n", cfgno, inums[i], j);
490 }
491 }
492
493 return 0;
494}
495
Greg Kroah-Hartman2c044a42008-01-30 15:21:33 -0800496/* hub-only!! ... and only exported for reset/reinit path.
497 * otherwise used internally on disconnect/destroy path
498 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499void usb_destroy_configuration(struct usb_device *dev)
500{
501 int c, i;
502
503 if (!dev->config)
504 return;
505
506 if (dev->rawdescriptors) {
507 for (i = 0; i < dev->descriptor.bNumConfigurations; i++)
508 kfree(dev->rawdescriptors[i]);
509
510 kfree(dev->rawdescriptors);
511 dev->rawdescriptors = NULL;
512 }
513
514 for (c = 0; c < dev->descriptor.bNumConfigurations; c++) {
515 struct usb_host_config *cf = &dev->config[c];
516
517 kfree(cf->string);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518 for (i = 0; i < cf->desc.bNumInterfaces; i++) {
519 if (cf->intf_cache[i])
Greg Kroah-Hartman2c044a42008-01-30 15:21:33 -0800520 kref_put(&cf->intf_cache[i]->ref,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521 usb_release_interface_cache);
522 }
523 }
524 kfree(dev->config);
525 dev->config = NULL;
526}
527
528
Inaky Perez-Gonzalez11450652007-07-31 20:34:02 -0700529/*
530 * Get the USB config descriptors, cache and parse'em
531 *
532 * hub-only!! ... and only in reset path, or usb_new_device()
533 * (used by real hubs and virtual root hubs)
534 *
535 * NOTE: if this is a WUSB device and is not authorized, we skip the
536 * whole thing. A non-authorized USB device has no
537 * configurations.
538 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539int usb_get_configuration(struct usb_device *dev)
540{
541 struct device *ddev = &dev->dev;
542 int ncfg = dev->descriptor.bNumConfigurations;
Inaky Perez-Gonzalez11450652007-07-31 20:34:02 -0700543 int result = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544 unsigned int cfgno, length;
545 unsigned char *buffer;
546 unsigned char *bigbuffer;
Greg Kroah-Hartman2c044a42008-01-30 15:21:33 -0800547 struct usb_config_descriptor *desc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548
Inaky Perez-Gonzalez11450652007-07-31 20:34:02 -0700549 cfgno = 0;
550 if (dev->authorized == 0) /* Not really an error */
551 goto out_not_authorized;
552 result = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553 if (ncfg > USB_MAXCONFIG) {
554 dev_warn(ddev, "too many configurations: %d, "
555 "using maximum allowed: %d\n", ncfg, USB_MAXCONFIG);
556 dev->descriptor.bNumConfigurations = ncfg = USB_MAXCONFIG;
557 }
558
559 if (ncfg < 1) {
560 dev_err(ddev, "no configurations\n");
561 return -EINVAL;
562 }
563
564 length = ncfg * sizeof(struct usb_host_config);
Alan Stern0a1ef3b2005-10-24 15:38:24 -0400565 dev->config = kzalloc(length, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566 if (!dev->config)
567 goto err2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568
569 length = ncfg * sizeof(char *);
Alan Stern0a1ef3b2005-10-24 15:38:24 -0400570 dev->rawdescriptors = kzalloc(length, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571 if (!dev->rawdescriptors)
572 goto err2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573
574 buffer = kmalloc(USB_DT_CONFIG_SIZE, GFP_KERNEL);
575 if (!buffer)
576 goto err2;
577 desc = (struct usb_config_descriptor *)buffer;
578
Inaky Perez-Gonzalez11450652007-07-31 20:34:02 -0700579 result = 0;
580 for (; cfgno < ncfg; cfgno++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581 /* We grab just the first descriptor so we know how long
582 * the whole configuration is */
583 result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno,
584 buffer, USB_DT_CONFIG_SIZE);
585 if (result < 0) {
586 dev_err(ddev, "unable to read config index %d "
Inaky Perez-Gonzalez11450652007-07-31 20:34:02 -0700587 "descriptor/%s: %d\n", cfgno, "start", result);
Inaky Perez-Gonzalezcb4c8fe2006-08-25 19:35:28 -0700588 dev_err(ddev, "chopping to %d config(s)\n", cfgno);
589 dev->descriptor.bNumConfigurations = cfgno;
590 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591 } else if (result < 4) {
592 dev_err(ddev, "config index %d descriptor too short "
593 "(expected %i, got %i)\n", cfgno,
594 USB_DT_CONFIG_SIZE, result);
595 result = -EINVAL;
596 goto err;
597 }
598 length = max((int) le16_to_cpu(desc->wTotalLength),
599 USB_DT_CONFIG_SIZE);
600
601 /* Now that we know the length, get the whole thing */
602 bigbuffer = kmalloc(length, GFP_KERNEL);
603 if (!bigbuffer) {
604 result = -ENOMEM;
605 goto err;
606 }
607 result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno,
608 bigbuffer, length);
609 if (result < 0) {
610 dev_err(ddev, "unable to read config index %d "
611 "descriptor/%s\n", cfgno, "all");
612 kfree(bigbuffer);
613 goto err;
614 }
615 if (result < length) {
616 dev_warn(ddev, "config index %d descriptor too short "
617 "(expected %i, got %i)\n", cfgno, length, result);
618 length = result;
619 }
620
621 dev->rawdescriptors[cfgno] = bigbuffer;
622
623 result = usb_parse_configuration(&dev->dev, cfgno,
624 &dev->config[cfgno], bigbuffer, length);
625 if (result < 0) {
626 ++cfgno;
627 goto err;
628 }
629 }
630 result = 0;
631
632err:
633 kfree(buffer);
Inaky Perez-Gonzalez11450652007-07-31 20:34:02 -0700634out_not_authorized:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635 dev->descriptor.bNumConfigurations = cfgno;
636err2:
637 if (result == -ENOMEM)
638 dev_err(ddev, "out of memory\n");
639 return result;
640}