xref: /utopia/UTPA2-700.0.x/modules/usb/drv/usb_ecos/usbhost/drvConfig.c (revision 53ee8cc121a030b8d368113ac3e966b4705770ef)
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