1 //<MStar Software>
2 //******************************************************************************
3 // MStar Software
4 // Copyright (c) 2010 - 2012 MStar Semiconductor, Inc. All rights reserved.
5 // All software, firmware and related documentation herein ("MStar Software") are
6 // intellectual property of MStar Semiconductor, Inc. ("MStar") and protected by
7 // law, including, but not limited to, copyright law and international treaties.
8 // Any use, modification, reproduction, retransmission, or republication of all
9 // or part of MStar Software is expressly prohibited, unless prior written
10 // permission has been granted by MStar.
11 //
12 // By accessing, browsing and/or using MStar Software, you acknowledge that you
13 // have read, understood, and agree, to be bound by below terms ("Terms") and to
14 // comply with all applicable laws and regulations:
15 //
16 // 1. MStar shall retain any and all right, ownership and interest to MStar
17 // Software and any modification/derivatives thereof.
18 // No right, ownership, or interest to MStar Software and any
19 // modification/derivatives thereof is transferred to you under Terms.
20 //
21 // 2. You understand that MStar Software might include, incorporate or be
22 // supplied together with third party`s software and the use of MStar
23 // Software may require additional licenses from third parties.
24 // Therefore, you hereby agree it is your sole responsibility to separately
25 // obtain any and all third party right and license necessary for your use of
26 // such third party`s software.
27 //
28 // 3. MStar Software and any modification/derivatives thereof shall be deemed as
29 // MStar`s confidential information and you agree to keep MStar`s
30 // confidential information in strictest confidence and not disclose to any
31 // third party.
32 //
33 // 4. MStar Software is provided on an "AS IS" basis without warranties of any
34 // kind. Any warranties are hereby expressly disclaimed by MStar, including
35 // without limitation, any warranties of merchantability, non-infringement of
36 // intellectual property rights, fitness for a particular purpose, error free
37 // and in conformity with any international standard. You agree to waive any
38 // claim against MStar for any loss, damage, cost or expense that you may
39 // incur related to your use of MStar Software.
40 // In no event shall MStar be liable for any direct, indirect, incidental or
41 // consequential damages, including without limitation, lost of profit or
42 // revenues, lost or damage of data, and unauthorized system use.
43 // You agree that this Section 4 shall still apply without being affected
44 // even if MStar Software has been modified by MStar in accordance with your
45 // request or instruction for your use, except otherwise agreed by both
46 // parties in writing.
47 //
48 // 5. If requested, MStar may from time to time provide technical supports or
49 // services in relation with MStar Software to you for your use of
50 // MStar Software in conjunction with your or your customer`s product
51 // ("Services").
52 // You understand and agree that, except otherwise agreed by both parties in
53 // writing, Services are provided on an "AS IS" basis and the warranty
54 // disclaimer set forth in Section 4 above shall apply.
55 //
56 // 6. Nothing contained herein shall be construed as by implication, estoppels
57 // or otherwise:
58 // (a) conferring any license or right to use MStar name, trademark, service
59 // mark, symbol or any other identification;
60 // (b) obligating MStar or any of its affiliates to furnish any person,
61 // including without limitation, you and your customers, any assistance
62 // of any kind whatsoever, or any information; or
63 // (c) conferring any license or right under any intellectual property right.
64 //
65 // 7. These terms shall be governed by and construed in accordance with the laws
66 // of Taiwan, R.O.C., excluding its conflict of law rules.
67 // Any and all dispute arising out hereof or related hereto shall be finally
68 // settled by arbitration referred to the Chinese Arbitration Association,
69 // Taipei in accordance with the ROC Arbitration Law and the Arbitration
70 // Rules of the Association by three (3) arbitrators appointed in accordance
71 // with the said Rules.
72 // The place of arbitration shall be in Taipei, Taiwan and the language shall
73 // be English.
74 // The arbitration award shall be final and binding to both parties.
75 //
76 //******************************************************************************
77 //<MStar Software>
78
79 #include <MsCommon.h>
80
81 #include "include/drvConfig.h"
82 #include "include/drvCompiler.h"
83 #include "include/drvList.h"
84 #include "include/drvPorts.h"
85 #include "include/drvPCIMEM.h"
86 #include "include/drvTimer.h"
87 #include "include/drvUSB.h"
88 #include "drvHCD.h"
89 #define USB_MAXALTSETTING 128
90 #define USB_MAXENDPOINTS 30
91
92 #define USB_MAXCONFIG 8
93 #define USB_ALTSETTINGALLOC 4
94 #define USB_MAXINTERFACES 32
95 #define max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff)
96
usb_parse_endpoint(struct usb_device * dev,struct usb_host_endpoint * endpoint,unsigned char * buffer,int size)97 static int usb_parse_endpoint(struct usb_device *dev, struct usb_host_endpoint *endpoint, unsigned char *buffer, int size)
98 {
99 struct usb_descriptor_header *header;
100 unsigned char *begin;
101 int parsed = 0, len, numskipped;
102
103 header = (struct usb_descriptor_header *)buffer;
104
105 if (header->bLength > size) {
106 usb_err("ran out of descriptors parsing%s","");
107 return -1;
108 }
109
110 if (header->bDescriptorType != USB_DT_ENDPOINT) {
111 usb_warn("unexpected descriptor 0x%X, expecting endpoint, 0x%X",
112 header->bDescriptorType, USB_DT_ENDPOINT);
113 return parsed;
114 }
115
116 if (header->bLength == USB_DT_ENDPOINT_AUDIO_SIZE)
117 memcpy(&endpoint->desc, buffer, USB_DT_ENDPOINT_AUDIO_SIZE);
118 else
119 memcpy(&endpoint->desc, buffer, USB_DT_ENDPOINT_SIZE);
120
121 endpoint->desc.wMaxPacketSize = LE16ToCPU(endpoint->desc.wMaxPacketSize);
122
123 #if 0
124 if (to_usb_device(ddev)->speed == USB_SPEED_HIGH
125 && usb_endpoint_xfer_bulk(d)) {
126 unsigned maxp;
127
128 maxp = le16_to_cpu(endpoint->desc.wMaxPacketSize) & 0x07ff;
129 if (maxp != 512)
130 dev_warn(ddev, "config %d interface %d altsetting %d "
131 "bulk endpoint 0x%X has invalid maxpacket %d\n",
132 cfgno, inum, asnum, d->bEndpointAddress,
133 maxp);
134 }
135 #else
136 if (dev->speed == USB_SPEED_HIGH
137 && (endpoint->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
138 unsigned maxp;
139
140 maxp = max_packet(endpoint->desc.wMaxPacketSize);
141 if (maxp != 512)
142 diag_printf("bulk endpoint 0x%X has invalid maxpacket %d\n",
143 endpoint->desc.bEndpointAddress, maxp);
144 }
145 #endif
146
147 buffer += header->bLength;
148 size -= header->bLength;
149 parsed += header->bLength;
150
151 begin = buffer;
152 numskipped = 0;
153 while ((U32)size >= sizeof(struct usb_descriptor_header)) {
154 header = (struct usb_descriptor_header *)buffer;
155
156 if (header->bLength < 2) {
157 usb_err("invalid descriptor length of %d", header->bLength);
158 return -1;
159 }
160
161 if ((header->bDescriptorType == USB_DT_ENDPOINT) ||
162 (header->bDescriptorType == USB_DT_INTERFACE) ||
163 (header->bDescriptorType == USB_DT_CONFIG) ||
164 (header->bDescriptorType == USB_DT_DEVICE))
165 break;
166 #if 0
167 if ( header->bDescriptorType == USB_DT_OTG )
168 {
169 vdbg("OTG descriptor found, bmAttributes=0x%08X\n",buffer[2]);
170 OTG.otgd->desc.bLength = buffer[0];
171 OTG.otgd->desc.bDescriptorType = buffer[1];
172 OTG.otgd->desc.bmAttributes = buffer[2];
173 }
174 else
175 #else
176 dbg("skipping descriptor 0x%X,len=%d",
177 header->bDescriptorType,header->bLength);
178 #endif
179 numskipped++;
180 buffer += header->bLength;
181 size -= header->bLength;
182 parsed += header->bLength;
183 }
184 if (numskipped)
185 dbg("skipped %d class/vendor specific endpoint descriptors", numskipped);
186
187 len = (int)(buffer - begin);
188 if (!len) {
189 endpoint->extra = NULL;
190 endpoint->extralen = 0;
191 return parsed;
192 }
193
194 endpoint->extra = (unsigned char *) kmalloc(len, GFP_KERNEL);
195
196 if (!endpoint->extra) {
197 usb_err("couldn't allocate memory for endpoint extra descriptors%s","");
198 endpoint->extralen = 0;
199 return parsed;
200 }
201
202 memcpy(endpoint->extra, begin, len);
203 endpoint->extralen = len;
204
205 return parsed;
206 }
207
usb_release_intf(struct device_s * dev)208 static void usb_release_intf(struct device_s *dev)
209 {
210 struct usb_interface *intf;
211 int j;
212 int k;
213
214 intf = to_usb_interface(dev);
215
216 if (intf->altsetting) {
217 for (j = 0; j < intf->num_altsetting; j++) {
218 struct usb_host_interface *as = &intf->altsetting[j];
219 if (as->extra)
220 kfree(as->extra);
221
222 if (as->endpoint) {
223 for (k = 0; k < as->desc.bNumEndpoints; k++)
224 if (as->endpoint[k].extra)
225 kfree(as->endpoint[k].extra);
226 kfree(as->endpoint);
227 }
228 }
229 kfree(intf->altsetting);
230 }
231 kfree(intf);
232 }
233
234 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
usb_parse_interface(struct usb_device * dev,struct usb_interface * interface,unsigned char * buffer,int size)235 static int usb_parse_interface(struct usb_device *dev, struct usb_interface *interface, unsigned char *buffer, int size)
236 {
237 int i, len, numskipped, retval, parsed = 0;
238 struct usb_descriptor_header *header;
239 struct usb_host_interface *ifp;
240 unsigned char *begin;
241
242 interface->act_altsetting = 0;
243 interface->num_altsetting = 0;
244 interface->max_altsetting = USB_ALTSETTINGALLOC;
245 device_initialize(&interface->dev);
246 interface->dev.release = usb_release_intf;
247
248 //get_device(&interface->dev);
249
250 interface->altsetting = (struct usb_host_interface *) kmalloc(sizeof(*interface->altsetting) * interface->max_altsetting,
251 GFP_KERNEL);
252
253 if (!interface->altsetting) {
254 usb_err("failed to alloc altsetting%s","");
255 return -1;
256 }
257
258 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
259 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
260 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
261 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
262 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
263 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
264 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
265 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
266 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
267 while (size > 0) {
268 struct usb_interface_descriptor *d;
269
270 if (interface->num_altsetting >= interface->max_altsetting) {
271 struct usb_host_interface *ptr;
272 int oldmas;
273
274 oldmas = interface->max_altsetting;
275 interface->max_altsetting += USB_ALTSETTINGALLOC;
276 if (interface->max_altsetting > USB_MAXALTSETTING) {
277 usb_warn("too many alt settings (incr %d max %d)\n",
278 USB_ALTSETTINGALLOC, USB_MAXALTSETTING);
279 return -1;
280 }
281
282 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
283 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
284 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
285 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
286 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
287 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
288 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
289 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
290 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
291 ptr = (struct usb_host_interface *) kmalloc(sizeof(*ptr) * interface->max_altsetting, GFP_KERNEL);
292 if (ptr == NULL) {
293 usb_err("failed to kmalloc interface->altsetting%s","");
294 return -1;
295 }
296 memcpy(ptr, interface->altsetting, sizeof(*interface->altsetting) * oldmas);
297 kfree(interface->altsetting);
298 interface->altsetting = ptr;
299 }
300
301 ifp = interface->altsetting + interface->num_altsetting;
302 ifp->endpoint = NULL;
303 ifp->extra = NULL;
304 ifp->extralen = 0;
305 interface->num_altsetting++;
306
307 memcpy(ifp, buffer, USB_DT_INTERFACE_SIZE);
308
309 buffer += ifp->desc.bLength;
310 parsed += ifp->desc.bLength;
311 size -= ifp->desc.bLength;
312
313 begin = buffer;
314 numskipped = 0;
315
316 while ((U32)size >= sizeof(struct usb_descriptor_header)) {
317 header = (struct usb_descriptor_header *)buffer;
318
319 if (header->bLength < 2) {
320 usb_err("invalid descriptor len of %d", header->bLength);
321 return -1;
322 }
323
324 if ((header->bDescriptorType == USB_DT_INTERFACE) ||
325 (header->bDescriptorType == USB_DT_ENDPOINT) ||
326 (header->bDescriptorType == USB_DT_CONFIG) ||
327 (header->bDescriptorType == USB_DT_DEVICE))
328 break;
329
330 numskipped++;
331
332 buffer += header->bLength;
333 parsed += header->bLength;
334 size -= header->bLength;
335 }
336
337 if (numskipped)
338 dbg("skipped %d class/vendor specific interface descriptors", numskipped);
339
340 len = (int)(buffer - begin);
341 if (len) {
342 ifp->extra = (unsigned char*) kmalloc(len, GFP_KERNEL);
343
344 if (!ifp->extra) {
345 usb_err("couldn't allocate memory for interface extra descriptors%s","");
346 ifp->extralen = 0;
347 return -1;
348 }
349 memcpy(ifp->extra, begin, len);
350 ifp->extralen = len;
351 }
352
353 header = (struct usb_descriptor_header *)buffer;
354 if (((U32)size >= sizeof(struct usb_descriptor_header)) &&
355 ((header->bDescriptorType == USB_DT_CONFIG) ||
356 (header->bDescriptorType == USB_DT_DEVICE)))
357 return parsed;
358
359 if (ifp->desc.bNumEndpoints > USB_MAXENDPOINTS) {
360 usb_warn("too many endpoints%s","");
361 return -1;
362 }
363 else if ( ifp->desc.bNumEndpoints == 0 )
364 {
365 goto skip_ep_pase;
366 }
367
368 ifp->endpoint = (struct usb_host_endpoint *)
369 kmalloc(ifp->desc.bNumEndpoints *
370 sizeof(struct usb_host_endpoint), GFP_KERNEL);
371 if (!ifp->endpoint) {
372 usb_err("out of memory%s","");
373 return -1;
374 }
375
376 memset(ifp->endpoint, 0, ifp->desc.bNumEndpoints *
377 sizeof(struct usb_host_endpoint));
378
379 for (i = 0; i < ifp->desc.bNumEndpoints; i++) {
380 header = (struct usb_descriptor_header *)buffer;
381
382 if (header->bLength > size) {
383 usb_err("ran out of descriptors parsing%s","");
384 return -1;
385 }
386
387 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
388 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
389 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
390 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
391 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
392 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
393 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
394 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
395 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
396 retval = usb_parse_endpoint(dev, ifp->endpoint + i, buffer, size);
397 if (retval < 0)
398 return retval;
399
400 buffer += retval;
401 parsed += retval;
402 size -= retval;
403 }
404 skip_ep_pase:
405 d = (struct usb_interface_descriptor *)buffer;
406 if (size < USB_DT_INTERFACE_SIZE
407 || d->bDescriptorType != USB_DT_INTERFACE
408 || !d->bAlternateSetting)
409 return parsed;
410 }
411
412 return parsed;
413 }
414
usb_parse_configuration(struct usb_device * dev,struct usb_host_config * config,char * buffer)415 int usb_parse_configuration(struct usb_device *dev, struct usb_host_config *config, char *buffer)
416 {
417 int i, size;
418 int retval = -EINVAL;
419 struct usb_descriptor_header *header;
420
421 memcpy(&config->desc, buffer, USB_DT_CONFIG_SIZE);
422 config->desc.wTotalLength = LE16ToCPU(config->desc.wTotalLength);
423 size = config->desc.wTotalLength;
424
425 //for (i = 0; i < USB_MAXINTERFACES; ++i)
426 // config->interface[i] = (struct usb_interface)NULL;
427
428 if (config->desc.bNumInterfaces > USB_MAXINTERFACES) {
429 usb_warn("too many interfaces%s","");
430 goto error;
431 }
432
433 for (i = 0; i < config->desc.bNumInterfaces; ++i) {
434 config->interface[i] = (struct usb_interface *) kmalloc(sizeof(struct usb_interface), GFP_KERNEL);
435 dbg("kmalloc IF %p, numif %i", config->interface[i], i);
436 if (!config->interface[i]) {
437 usb_err("out of memory%s","");
438 retval = -ENOMEM;
439 goto error;
440 }
441 memset(config->interface[i], 0x00, sizeof(struct usb_interface));
442 }
443
444 buffer += config->desc.bLength;
445 size -= config->desc.bLength;
446
447 config->extra = NULL;
448 config->extralen = 0;
449
450 for (i = 0; i < config->desc.bNumInterfaces; i++) {
451 int numskipped, len;
452 char *begin;
453
454 begin = buffer;
455 numskipped = 0;
456 while ((U32)size >= sizeof(struct usb_descriptor_header)) {
457 header = (struct usb_descriptor_header *)buffer;
458
459 if ((header->bLength > size) || (header->bLength < 2)) {
460 usb_err("invalid descriptor length of %d", header->bLength);
461 return -1;
462 }
463
464 if ((header->bDescriptorType == USB_DT_ENDPOINT) ||
465 (header->bDescriptorType == USB_DT_INTERFACE) ||
466 (header->bDescriptorType == USB_DT_CONFIG) ||
467 (header->bDescriptorType == USB_DT_DEVICE))
468 break;
469
470 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
471 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
472 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
473 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
474 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
475 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
476 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
477 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
478 /*USB HOST USB HOST USB HOST USB HOST USB HOST USB HOST*/
479 dbg("skipping descriptor 0x%X", header->bDescriptorType);
480 numskipped++;
481 buffer += header->bLength;
482 size -= header->bLength;
483 }
484 if (numskipped)
485 dbg("skipped %d class/vendor specific endpoint descriptors", numskipped);
486
487 len = (int)(buffer - begin);
488 if (len) {
489 if (config->extralen) {
490 usb_warn("extra config descriptor%s","");
491 } else {
492 config->extra = (unsigned char*) kmalloc(len, GFP_KERNEL);
493 if (!config->extra) {
494 usb_err("couldn't allocate memory for config extra descriptors%s","");
495 config->extralen = 0;
496 return -1;
497 }
498
499 memcpy(config->extra, begin, len);
500 config->extralen = len;
501 }
502 }
503
504 retval = usb_parse_interface(dev, config->interface[i], (unsigned char*) buffer, size);
505 if (retval < 0)
506 return retval;
507
508 buffer += retval;
509 size -= retval;
510 }
511
512 return size;
513 error:
514 for (i = 0; i < USB_MAXINTERFACES; ++i)
515 kfree(config->interface[i]);
516 return retval;
517 }
518
usb_destroy_configuration(struct usb_device * dev)519 void usb_destroy_configuration(struct usb_device *dev)
520 {
521 int c, i;
522
523 if (!dev->config)
524 return;
525
526 if (dev->rawdescriptors) {
527 for (i = 0; i < dev->descriptor.bNumConfigurations; i++)
528 kfree(dev->rawdescriptors[i]);
529
530 kfree(dev->rawdescriptors);
531 }
532
533 for (c = 0; c < dev->descriptor.bNumConfigurations; c++) {
534 struct usb_host_config *cf = &dev->config[c];
535
536 if (!cf->interface)
537 break;
538
539 for (i = 0; i < cf->desc.bNumInterfaces; i++) {
540 //struct usb_interface *ifp = cf->interface[i];
541 put_device(&ifp->dev);
542 }
543 }
544 kfree(dev->config);
545 }
546
547
usb_get_configuration(struct usb_device * dev)548 int usb_get_configuration(struct usb_device *dev)
549 {
550 int result;
551 U32 cfgno, length;
552 unsigned char *buffer;
553 unsigned char *bigbuffer;
554 struct usb_config_descriptor *desc;
555 int i=0;
556
557 if (dev->descriptor.bNumConfigurations > USB_MAXCONFIG) {
558 usb_warn("too many configurations%s","");
559 return -EINVAL;
560 }
561
562 if (dev->descriptor.bNumConfigurations < 1) {
563 usb_warn("not enough configurations%s","");
564 return -EINVAL;
565 }
566
567 dev->config = (struct usb_host_config *)
568 kmalloc(dev->descriptor.bNumConfigurations *
569 sizeof(struct usb_host_config), GFP_KERNEL);
570 if (!dev->config) {
571 usb_err("out of memory%s","");
572 return -ENOMEM;
573 }
574 memset(dev->config, 0, dev->descriptor.bNumConfigurations *
575 sizeof(struct usb_host_config));
576
577 dev->rawdescriptors = (char **)kmalloc(sizeof(char *) *
578 dev->descriptor.bNumConfigurations, GFP_KERNEL);
579 if (!dev->rawdescriptors) {
580 usb_err("out of memory%s","");
581 return -ENOMEM;
582 }
583
584 buffer = (unsigned char*) kmalloc(8, GFP_KERNEL);
585 if (!buffer) {
586 usb_err("unable to allocate memory for configuration descriptors%s","");
587 return -ENOMEM;
588 }
589 desc = (struct usb_config_descriptor *)buffer;
590
591 for (cfgno = 0; cfgno < dev->descriptor.bNumConfigurations; cfgno++) {
592 result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, 8);
593 if (result < 8) {
594 if (result < 0)
595 {
596 usb_err("unable to get descriptor%s","");
597 }
598 else {
599 usb_err("config descriptor too short (expected %i, got %i)", 8, result);
600 result = -EINVAL;
601 }
602 goto err;
603 }
604
605 length = LE16ToCPU(desc->wTotalLength);
606 bigbuffer = (unsigned char*) kmalloc(length, GFP_KERNEL);
607 if (!bigbuffer) {
608 do
609 {
610 length = LE16ToCPU(desc->wTotalLength);
611 i++;
612 }while(length == 0 );
613 usb_err("unable to allocate (len=%d) memory for configuration descriptors, i=%d",length,i);
614 result = -ENOMEM;
615 goto err;
616 }
617
618 result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, bigbuffer, length);
619 if (result < 0) {
620 usb_err("couldn't get all of config descriptors%s","");
621 kfree(bigbuffer);
622 goto err;
623 }
624
625 if ((U32)result < length) {
626 usb_err("config descriptor too short (expected %i, got %i)", length, result);
627 result = -EINVAL;
628 kfree(bigbuffer);
629 goto err;
630 }
631
632 dev->rawdescriptors[cfgno] = (char*) bigbuffer;
633
634 result = usb_parse_configuration(dev, &dev->config[cfgno], (char*) bigbuffer);
635 if (result > 0) {
636 dbg("descriptor data left%s","");
637 }
638 else if (result < 0) {
639 result = -EINVAL;
640 goto err;
641 }
642 }
643
644 kfree(buffer);
645 return 0;
646 err:
647 kfree(buffer);
648 dev->descriptor.bNumConfigurations = cfgno;
649 return result;
650 }
651
652
653
654
655
656