xref: /utopia/UTPA2-700.0.x/modules/usb/drv/usb_ecos/newhost/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/drvUSBHost.h"
88 #include "drvUsbd.h"
89 #define USB_MAX_ALTSETTING    128
90 #define USB_MAX_ENDPOINTS     30
91 
92 #define USB_MAX_CONFIG        8
93 #define USB_ALTSETTING_ALLOC  4
94 #define USB_MAX_INTERFACES    32
95 #define MAX_PKT_SIZE(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff)
96 
97 /**
98      * @brief               Parse endpoint descriptor in the buffer
99      *
100      * @param dev
101      * @param ept
102      * @param buf
103      * @param bufsize
104      *
105      * @return          The number of bytes it parsed
106      */
ms_usb_parse_ept(struct usb_device * dev,struct usb_host_endpoint * pEpt,unsigned char * pBuf,int iBufSize)107 static int ms_usb_parse_ept(
108         struct usb_device *dev,
109         struct usb_host_endpoint *pEpt,
110         unsigned char *pBuf,
111         int iBufSize)
112 {
113     struct usb_descriptor_header *desc = (struct usb_descriptor_header *)pBuf;
114     int checked = 0, len;
115 
116     if (desc->bDescriptorType != USB_DT_ENDPOINT)
117     {
118         //diag_printf("pEpt descriptor type is invalid\n");
119         return 0;
120     }
121 
122     if (desc->bLength > iBufSize)
123     {
124         diag_printf("pEpt descriptor size is too large (%d)\n", desc->bLength);
125         return -1;
126     }
127 
128     len = USB_DT_ENDPOINT_SIZE;
129     if (desc->bLength == USB_DT_ENDPOINT_AUDIO_SIZE)
130         len = USB_DT_ENDPOINT_AUDIO_SIZE;
131 
132     memcpy(&pEpt->desc, pBuf, len);
133 
134     pEpt->desc.wMaxPacketSize = pEpt->desc.wMaxPacketSize;
135 
136     if (dev->eSpeed == USB_HIGH_SPEED
137         && (pEpt->desc.bmAttributes & 0x03) == USB_ENDPOINT_XFER_BULK) {
138         if (512 != pEpt->desc.wMaxPacketSize)
139         {
140             diag_printf("bulk pEpt max packet size is not 512\n");
141         }
142     }
143 
144     pBuf += desc->bLength;
145     iBufSize -= desc->bLength;
146     checked += desc->bLength;
147 
148     //Skip descriptors we don't support
149     while ((U32)iBufSize >= sizeof(struct usb_descriptor_header))
150     {
151         desc = (struct usb_descriptor_header *)pBuf;
152 
153         if ((desc->bDescriptorType == USB_DT_ENDPOINT) ||
154             (desc->bDescriptorType == USB_DT_INTERFACE) ||
155             (desc->bDescriptorType == USB_DT_CONFIG) ||
156             (desc->bDescriptorType == USB_DT_DEVICE))
157             break;
158 
159         pBuf += desc->bLength;
160         iBufSize -= desc->bLength;
161         checked += desc->bLength;
162     }
163 
164   return checked;
165 }
166 
167 /**
168      * @brief               Release memory associated with the interface
169      *
170      * @param dev
171      *
172      * @return          None
173      */
ms_usb_release_intf(struct device_s * dev)174 static void ms_usb_release_intf(struct device_s *dev)
175 {
176     struct usb_interface *pIntf = get_usb_interface(dev);
177     int ii;
178 
179     if (pIntf->altsetting)
180     {
181         for (ii = 0; ii < pIntf->num_altsetting; ii++)
182         {
183             struct usb_host_interface *pAltset = &pIntf->altsetting[ii];
184 
185             if (pAltset->endpoint)
186                 kfree(pAltset->endpoint);
187         }
188         kfree(pIntf->altsetting);
189     }
190 
191     kfree(pIntf);
192 }
193 
194 /**
195      * @brief               Parse interface descriptor in the buffer
196      *
197      * @param dev
198      * @param intf
199      * @param buf
200      * @param bufsize
201      *
202      * @return          The number of bytes it parsed
203      */
ms_usb_parse_interface(struct usb_device * dev,struct usb_interface * pIntf,unsigned char * pBuf,int bufsize)204 static int ms_usb_parse_interface(
205         struct usb_device *dev,
206         struct usb_interface *pIntf,
207         unsigned char *pBuf,
208         int bufsize)
209 {
210     int i, retval, checked = 0;
211     struct usb_descriptor_header *pDesc;
212     struct usb_host_interface *pIf;
213     struct usb_interface_descriptor  *pIntf_desc;
214 
215     pIntf->act_altsetting = 0;
216     pIntf->num_altsetting = 0;
217     pIntf->max_altsetting = USB_ALTSETTING_ALLOC; //Use 4 interface altsettings each time
218     ms_device_initialize(&pIntf->dev);
219     pIntf->dev.release_func = ms_usb_release_intf;
220 
221     pIntf->altsetting = (struct usb_host_interface *)
222         kmalloc(sizeof(*pIntf->altsetting) * pIntf->max_altsetting, GFP_KERNEL);
223 
224     if (!pIntf->altsetting)
225     {
226         diag_printf("failed to alloc altsetting\n");
227         return -1;
228     }
229 
230     while (bufsize > 0)
231     {
232         if (pIntf->num_altsetting >= pIntf->max_altsetting) //Allocate more memory for altset
233         {
234             struct usb_host_interface *pInft_tmp;
235             int cur_max_altsetting;
236 
237             cur_max_altsetting = pIntf->max_altsetting;
238             pIntf->max_altsetting += USB_ALTSETTING_ALLOC;
239             if (pIntf->max_altsetting > USB_MAX_ALTSETTING)
240             {
241                 diag_printf("altsettings are over (%d)\n", USB_MAX_ALTSETTING);
242                 return -1;
243             }
244 
245             pInft_tmp = (struct usb_host_interface *)
246                     kmalloc(sizeof(*pInft_tmp) * pIntf->max_altsetting, GFP_KERNEL);
247             if (pInft_tmp == NULL)
248             {
249                 diag_printf("failed to alloc mem for altsetting\n");
250                 return -1;
251             }
252             memcpy(pInft_tmp, pIntf->altsetting, sizeof(*pIntf->altsetting) * cur_max_altsetting);
253             kfree(pIntf->altsetting);
254             pIntf->altsetting = pInft_tmp;
255         }
256 
257         pIf = pIntf->altsetting + pIntf->num_altsetting;
258         pIf->endpoint = NULL;
259         pIntf->num_altsetting++;
260 
261         memcpy(pIf, pBuf, USB_DT_INTERFACE_SIZE);
262 
263         pBuf += pIf->desc.bLength;
264         checked += pIf->desc.bLength;
265         bufsize -= pIf->desc.bLength;
266 
267         //skip descriptors we can't handle
268         while ((U32)bufsize >= sizeof(struct usb_descriptor_header))
269         {
270             pDesc = (struct usb_descriptor_header *)pBuf;
271 
272             if ((pDesc->bDescriptorType == USB_DT_INTERFACE) ||
273                 (pDesc->bDescriptorType == USB_DT_ENDPOINT) ||
274                 (pDesc->bDescriptorType == USB_DT_CONFIG) ||
275                 (pDesc->bDescriptorType == USB_DT_DEVICE))
276                 break;
277 
278             pBuf += pDesc->bLength;
279             checked += pDesc->bLength;
280             bufsize -= pDesc->bLength;
281         }
282 
283         pDesc = (struct usb_descriptor_header *)pBuf;
284         if (((U32)bufsize >= sizeof(struct usb_descriptor_header)) &&
285             ((pDesc->bDescriptorType == USB_DT_CONFIG) ||
286             (pDesc->bDescriptorType == USB_DT_DEVICE)))
287             return checked;
288 
289         if ( (pIf->desc.bNumEndpoints > 0) && (pIf->desc.bNumEndpoints <= USB_MAX_ENDPOINTS) )
290         {
291             pIf->endpoint = (struct usb_host_endpoint *)
292                         kmalloc(sizeof(struct usb_host_endpoint) *
293                                 pIf->desc.bNumEndpoints, GFP_KERNEL);
294             if (!pIf->endpoint)
295             {
296                 diag_printf("fail to alloc mem for ept\n");
297                 return -1;
298             }
299 
300             memset(pIf->endpoint, 0, sizeof(struct usb_host_endpoint) *
301                     pIf->desc.bNumEndpoints);
302 
303             for (i = 0; i < pIf->desc.bNumEndpoints; i++)
304             {
305                 retval = ms_usb_parse_ept(dev, pIf->endpoint + i, pBuf, bufsize);
306                 if (retval < 0)
307                     return retval;
308 
309                 pBuf += retval;
310                 checked += retval;
311                 bufsize -= retval;
312             }
313         }
314 
315         //parsing endpoint done
316         pIntf_desc = (struct usb_interface_descriptor *)pBuf;
317         if (bufsize < USB_DT_INTERFACE_SIZE
318             || pIntf_desc->bDescriptorType != USB_DT_INTERFACE
319             || !pIntf_desc->bAlternateSetting)
320             return checked;
321     }
322 
323     return checked;
324 }
325 
326 /**
327      * @brief               Parse configuration descriptor in the buffer
328      *
329      * @param dev
330      * @param config
331      * @param buf
332      *
333      * @return          The number of bytes it parsed
334      */
ms_usb_parse_config(struct usb_device * dev,struct usb_host_config * pConfig,char * pBuf)335 int ms_usb_parse_config(
336         struct usb_device *dev,
337         struct usb_host_config *pConfig,
338         char *pBuf)
339 {
340     int i, Desc_size;
341     int retval = -EINVAL;
342     struct usb_descriptor_header *pDesc;
343 
344     memcpy(&pConfig->desc, pBuf, USB_DT_CONFIG_SIZE);
345     pConfig->desc.wTotalLength = pConfig->desc.wTotalLength;
346     Desc_size = pConfig->desc.wTotalLength;
347 
348     //for (i = 0; i < USB_MAX_INTERFACES; ++i)
349     //  pConfig->interface[i] = (struct usb_interface)NULL;
350 
351     if (pConfig->desc.bNumInterfaces > USB_MAX_INTERFACES)
352     {
353         diag_printf("too many interfaces %d", pConfig->desc.bNumInterfaces);
354         return -EINVAL;
355     }
356 
357     for (i = 0; i < pConfig->desc.bNumInterfaces; i++)
358     {
359         pConfig->interface[i] = (struct usb_interface *) kmalloc(sizeof(struct usb_interface), GFP_KERNEL);
360         if (!pConfig->interface[i])
361         {
362             diag_printf("fail to alloc mem for interface\n");
363             retval = -ENOMEM;
364             goto error_exit;
365         }
366         memset(pConfig->interface[i], 0x00, sizeof(struct usb_interface));
367     }
368 
369     pBuf += pConfig->desc.bLength;
370     Desc_size -= pConfig->desc.bLength;
371 
372     for (i = 0; i < pConfig->desc.bNumInterfaces; i++)
373     {
374         while ((U32)Desc_size >= sizeof(struct usb_descriptor_header))
375         {
376             pDesc = (struct usb_descriptor_header *)pBuf;
377 
378             if ((pDesc->bDescriptorType == USB_DT_ENDPOINT) ||
379                 (pDesc->bDescriptorType == USB_DT_INTERFACE) ||
380                 (pDesc->bDescriptorType == USB_DT_CONFIG) ||
381                 (pDesc->bDescriptorType == USB_DT_DEVICE))
382                 break;
383 
384             pBuf += pDesc->bLength;
385             Desc_size -= pDesc->bLength;
386         }
387 
388         retval = ms_usb_parse_interface(dev, pConfig->interface[i], (unsigned char*) pBuf, Desc_size);
389         if (retval < 0)
390             return retval;
391 
392         pBuf += retval;
393         Desc_size -= retval;
394     }
395 
396     return Desc_size;
397 
398 error_exit:
399     for (i = 0; i < USB_MAX_INTERFACES; ++i)
400         kfree(pConfig->interface[i]);
401 
402     return retval;
403 }
404 
405 /**
406      * @brief               Release memory associated with the interface
407      *
408      * @param dev
409      *
410      * @return          None
411      */
ms_usb_destroy_config(struct usb_device * dev)412 void ms_usb_destroy_config(struct usb_device *dev)
413 {
414     int config_idx, i;
415 
416     if (dev->config == NULL)
417         return;
418 
419     if (dev->pRawDescriptors)
420     {
421         for (i = 0; i < dev->descriptor.bNumConfigurations; i++)
422             kfree(dev->pRawDescriptors[i]);
423 
424         kfree(dev->pRawDescriptors);
425     }
426 
427     for (config_idx = 0; config_idx < dev->descriptor.bNumConfigurations; config_idx++)
428     {
429         struct usb_host_config *pConfig = &dev->config[config_idx];
430 
431         if (!pConfig->interface)
432             break;
433     }
434 
435     kfree(dev->config);
436 }
437 
438 
439 /**
440      * @brief               Retrieve configuration descriptor from the device
441      *
442      * @param dev
443      *
444      * @return            Function status
445      */
ms_usb_get_config(struct usb_device * dev)446 int ms_usb_get_config(struct usb_device *dev)
447 {
448     int retval;
449     U32 cfg_num, len;
450     unsigned char *pBuf = NULL;
451     unsigned char *pBuf_tmp;
452     struct usb_config_descriptor *pDesc;
453     U8  uCfg_count;
454 
455     uCfg_count = dev->descriptor.bNumConfigurations;
456     if ( (uCfg_count == 0) || (uCfg_count > USB_MAX_CONFIG) )
457     {
458         diag_printf("number of config is invalid\n");
459         return -EINVAL;
460     }
461 
462     dev->config = (struct usb_host_config *)
463             kmalloc(dev->descriptor.bNumConfigurations *
464             sizeof(struct usb_host_config), GFP_KERNEL);
465 
466     if (!dev->config)
467     {
468         diag_printf("fail to alloc mem for config");
469         return -ENOMEM;
470     }
471 
472     memset(dev->config, 0, dev->descriptor.bNumConfigurations *
473             sizeof(struct usb_host_config));
474 
475     dev->pRawDescriptors = (char **)kmalloc(sizeof(char *) *
476             dev->descriptor.bNumConfigurations, GFP_KERNEL);
477 
478     if (!dev->pRawDescriptors)
479     {
480         diag_printf("fail to alloc mem for descriptors\n");
481         return -ENOMEM;
482     }
483 
484     pBuf = (unsigned char*) kmalloc(8, GFP_KERNEL);
485     if (!pBuf)
486     {
487         diag_printf("unable to allocate memory for configuration descriptors\n");
488         return -ENOMEM;
489     }
490 
491     pDesc = (struct usb_config_descriptor *)pBuf;
492 
493     for (cfg_num = 0; cfg_num < dev->descriptor.bNumConfigurations; cfg_num++)
494     {
495         retval = ms_usb_get_descriptor(dev, USB_DT_CONFIG, cfg_num, pBuf, 8);
496         if (retval < 0)
497         {
498             diag_printf("fail to get config descriptor %d\n", retval);
499             goto error_exit;
500         }
501 
502         len = pDesc->wTotalLength;
503 
504         pBuf_tmp = (unsigned char*) kmalloc(len, GFP_KERNEL);
505         if (pBuf_tmp == NULL)
506         {
507             diag_printf("fail to alloc mem for config desc\n");
508             retval = -ENOMEM;
509             goto error_exit;
510         }
511 
512         retval = ms_usb_get_descriptor(dev, USB_DT_CONFIG, cfg_num, pBuf_tmp, len);
513         if (retval < 0)
514         {
515             diag_printf("fail to get config descriptor %d\n", retval);
516             kfree(pBuf_tmp);
517             goto error_exit;
518         }
519 
520         dev->pRawDescriptors[cfg_num] = (char*) pBuf_tmp;
521 
522         retval = ms_usb_parse_config(dev, &dev->config[cfg_num], (char*) pBuf_tmp);
523         if (retval < 0)
524         {
525             retval = -EINVAL;
526             goto error_exit;
527         }
528     }
529 
530     if (pBuf)
531         kfree(pBuf);
532     return 0;
533 
534 error_exit:
535     if (pBuf)
536         kfree(pBuf);
537 
538     dev->descriptor.bNumConfigurations = cfg_num; //modify the number of config
539     return retval;
540 }
541 
542 
543 
544 
545 
546