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