xref: /utopia/UTPA2-700.0.x/modules/usb/drv/usb_ecos/newhost/drvMsg.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> // NUSED
80 //#include <cyg/hal/hal_if.h> // NUSED
81 
82 #include  "include/drvConfig.h"
83 
84 #ifdef CONFIG_DEBUG
85 #define DEBUG
86 #else
87 #undef DEBUG
88 #endif
89 
90 //#include  "include/drvCompiler.h" // NUSED
91 //#include  "include/drvErrno.h" // NUSED
92 //#include  "include/drvPorts.h" // NUSED
93 //#include  "include/drvPCIMEM.h" // NUSED
94 //#include  "include/drvTimer.h" // NUSED
95 //#include  "include/drvList.h" // NUSED
96 
97 //#include "include/drvUSBHost.h" // NUSED
98 //#include "drvUsbd.h" // NUSED
99 //#include "include/drvCPE_AMBA.h" // NUSED
100 #include "drvEHCI.h"
101 
102 /**
103      * @brief               complete function of URB
104      *
105      * @param urb
106      * @param regs
107      *
108      * @return          none
109      */
ms_usb_api_completion(struct urb * urb,struct stPtRegs * regs)110 static void ms_usb_api_completion(struct urb *urb, struct stPtRegs *regs)
111 {
112     struct usb_api_data *pAwd = (struct usb_api_data *)urb->pContext;
113 
114     /* move to ms_usb_hcd_giveback_urb() to support 3rd driver */
115     //if (urb->SetDMABuf != NULL)
116     //{
117     //    //MsOS_FreeMemory(urb->SetDMABuf, gs32NonCachedPoolID_MIU0 );
118     //    Usb_FreeNonCachedMemory(urb->SetDMABuf);
119     //
120     //    urb->SetDMABuf = NULL;
121     //}
122     //
123     //if (urb->TxDMABuf != NULL)
124     //{
125     //    if (usb_pipein(urb->u32Pipe))
126     //    {
127     //    #ifdef DEBUG_PERFORMANCE
128     //        if (urb->u32TransferBufferLength >= 512)
129     //        diag_printf("ms_usb_api_completion: copy length: 0x%lx \n", urb->u32TransferBufferLength);
130     //    #endif
131     //        memcpy(urb->pTransferBuffer, urb->TxDMABuf, urb->u32TransferBufferLength);
132     //    }
133     //    //MsOS_FreeMemory(urb->TxDMABuf,gs32NonCachedPoolID_MIU0 );
134     //    Usb_FreeNonCachedMemory(urb->TxDMABuf);
135     //
136     //    urb->TxDMABuf = NULL;
137     //}
138 
139     pAwd->done = 1;
140     wmb();
141 
142     wake_up(&pAwd->wqh);
143 }
144 #ifdef DEBUG
145 extern BOOL ms_isHcdRunning(struct usb_hcd *hcd); // debug
146 extern void ms_dumpHcdRegister(struct usb_hcd *hcd); // debug
147 #endif
148 /**
149      * @brief               Start the URB and wait until it complete
150      *
151      * @param urb
152      * @param timeout
153      * @param act_len
154      *
155      * @return          function status
156      */
ms_usb_start_wait_urb(struct urb * urb,int timeout,int * act_len)157 static int ms_usb_start_wait_urb(struct urb *urb, int timeout, int* act_len)
158 {
159     struct usb_api_data stAwd;
160     struct usb_hcd *hcd = urb->dev->bus->hcpriv;
161     struct ehci_hcd *ehci = hcd_to_ehci (hcd);
162     int status;
163     int rh_csc_shutdown = 0;
164     U32 uDelay=0;
165 
166     stAwd.done = 0;
167 
168     urb->pContext = &stAwd;
169     status = ms_usb_submit_urb(urb, GFP_ATOMIC);
170     if (status)
171     {
172         ms_usb_free_urb(urb);
173         return status;
174     }
175 
176     while ( timeout && (stAwd.done == 0) )
177     {
178         /* to speed up one WIFI dongle with internal HUB */
179         //if((urb->dev->parent != NULL) && (urb->dev->parent->parent == NULL) // device on roothub
180         if ((hcd_reg_readb((U32)&ehci->op_regs->portsc[0]) & PORTSC_CSC)  // CSC happen on ehci port
181             || !(hcd_reg_readb((U32)&ehci->op_regs->portsc[0]) & PORTSC_PE)) // PE cleared on ehci port
182         {
183             timeout = 0;
184             rh_csc_shutdown = 1;
185             diag_printf("[USB] CSC happend/PE clr while wait CMP PSC [0x%x]\n", hcd_reg_readb((U32)&ehci->op_regs->portsc[0]));
186             break;
187         }
188 
189         if ( uDelay > (U32) timeout)
190         {
191             timeout =0;
192             break;
193         }
194         else
195         {
196             mdelay(1);//tick base is 1 ms
197             //HAL_DELAY_US(1000); // NUSED
198             uDelay+=1;
199         }
200         rmb();
201     }
202 
203     if (!timeout && !stAwd.done)
204     {
205         diag_printf("usb_control/bulk_msg: timeout... (status=%d)\n", (int)urb->s32Status);
206         if (urb->s32Status != -EINPROGRESS)
207         {
208             status = urb->s32Status;
209         }
210         else
211         {
212             //int retv;
213 
214             //diag_printf("<%s> set Bad Device............\n", __FUNCTION__);
215 #ifdef DEBUG
216             ms_dumpHcdRegister(hcd);
217             if (ms_isHcdRunning(hcd)) // just for debugging
218                 diag_printf("HCD RUN!!!\n");
219 #endif
220             hcd->isBadDevice = TRUE;
221             hcd->badDeviceCnt++;
222 
223             /* Linux kernel put 5 seconds wait time for control commands,  we put 3 seconds here */
224             diag_printf("timeout unlink(kill) urb(qh:%p)\n", urb->hcpriv);
225             ms_hcd_unlink_urb(urb, -ENOENT);
226             //if ((retv = ms_usb_unlink_urb(urb)) == -ETIMEDOUT)
227             //{
228             //    diag_printf("timeout retry %d\n", retv);
229             //    retv = ms_usb_unlink_urb(urb);
230             //}
231             //diag_printf("timeout unlink urb(%p) error %d\n", urb, retv);
232 
233             status = rh_csc_shutdown ? -ESHUTDOWN : -ETIMEDOUT;
234         }
235     }
236     else
237         status = urb->s32Status;
238 
239     if (act_len)
240         *act_len = urb->u32ActualLength;
241 
242     ms_usb_free_urb(urb);
243     return status;
244 }
245 
246 /**
247      * @brief               Send a control setup command
248      *
249      * @param pDev
250      * @param pipe
251      * @param u8Reg
252      * @param urReg_type
253      * @param u16Val
254      * @param u16Index
255      * @param data
256      * @param u16Size
257      * @param timeout
258      *
259      * @return          function status or actual length
260      */
ms_usb_control_cmd(struct usb_device * pDev,unsigned int pipe,unsigned char u8Req,unsigned char u8Req_type,unsigned short u16Val,unsigned short u16Index,void * data,unsigned short u16Size,int timeout)261 int ms_usb_control_cmd(
262         struct usb_device *pDev,
263         unsigned int pipe,
264         unsigned char u8Req,
265         unsigned char u8Req_type,
266         unsigned short u16Val,
267         unsigned short u16Index,
268         void *data,
269         unsigned short u16Size,
270         int timeout)
271 {
272     struct usb_ctrlrequest *dr = (struct usb_ctrlrequest*) kmalloc(sizeof(struct usb_ctrlrequest), GFP_NOIO);
273     struct urb *pUrb;
274     int ret;
275     int length = 0;
276     void *addr_t;
277 
278     if (!dr)
279         return -ENOMEM;
280 
281     addr_t = (void *)dr;
282     dr->bRequestType= u8Req_type;
283     dr->bRequest = u8Req;
284     dr->wValue = u16Val;
285     dr->wIndex = u16Index;
286     dr->wLength = u16Size;
287 
288     pUrb = ms_usb_alloc_urb(GFP_NOIO);
289     if (!pUrb)
290     {
291         ret = -ENOMEM;
292         goto Func_done;
293     }
294 
295     ms_usb_stuff_control_urb(pUrb, pDev, pipe, (unsigned char*)dr, data, u16Size,
296             ms_usb_api_completion, 0);
297     ret = ms_usb_start_wait_urb(pUrb, timeout, &length);
298     if (ret < 0)
299     {
300         ms_debug_err("%s retv:%d, RT:%x,R:%x,V:%x,I:%x,L:%x\n", __FUNCTION__,
301             ret, dr->bRequestType, dr->bRequest, dr->wValue, dr->wIndex, dr->wLength);
302     }
303     else
304         ret = length;
305 
306 Func_done:
307     kfree(addr_t);
308 
309     return ret;
310 }
311 
312 /**
313      * @brief               Send a bulk stansaction
314      *
315      * @param pUsb_dev
316      * @param pipe
317      * @param data
318      * @param len
319      * @param actual_length
320      * @param timeout
321      *
322      * @return          function status
323      */
324 #if 0 // NUSED
325 int ms_usb_bulk_msg(
326         struct usb_device *pUsb_dev,
327         unsigned int pipe,
328         void *data,
329         int len,
330         int *actual_length,
331         int timeout)
332 {
333     struct urb *urb;
334 
335     if (len < 0)
336         return -EINVAL;
337 
338     urb=ms_usb_alloc_urb(GFP_KERNEL);
339     if (!urb)
340         return -ENOMEM;
341 
342     ms_usb_stuff_bulk_urb(urb, pUsb_dev, pipe, data, len,
343             ms_usb_api_completion, 0);
344 
345     return ms_usb_start_wait_urb(urb,timeout,actual_length);
346 }
347 #endif
348 
349 /**
350      * @brief               get descriptor from the device
351      *
352      * @param pDev
353      * @param u8Type
354      * @param u8Index
355      * @param pBuf
356      * @param size
357      *
358      * @return          function status
359      */
ms_usb_get_descriptor(struct usb_device * pDev,unsigned char u8Type,unsigned char u8Index,void * pBuf,int size)360 int ms_usb_get_descriptor(
361         struct usb_device *pDev,
362         unsigned char u8Type,
363         unsigned char u8Index,
364         void *pBuf,
365         int size)
366 {
367     int retry = 3;
368     int relt = 0;
369 
370     memset(pBuf,0,size);
371 
372     while (retry--)
373     {
374         relt = ms_usb_control_cmd(pDev, usb_rcvctrlpipe(pDev, 0),
375                 USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
376                 (u8Type << 8) + u8Index, 0, pBuf, size,
377                 HZ * USB_CTRL_GET_TIMEOUT);
378 
379         if ( (relt > 0) || (relt == -EPIPE) )
380             break;
381     }
382 
383     return relt;
384 }
385 
386 /**
387      * @brief               get the device descriptor from the device
388      *
389      * @param pDev
390      *
391      * @return          function status
392      */
ms_usb_get_dev_descriptor(struct usb_device * pDev)393 int ms_usb_get_dev_descriptor(struct usb_device *pDev)
394 {
395 
396     return ms_usb_get_descriptor(pDev, USB_DT_DEVICE,
397             0, &pDev->descriptor,
398             sizeof(pDev->descriptor));
399 }
400 
401 /**
402      * @brief               Clear halt status of the endpoint
403      *
404      * @param pDev
405      * @param pipe
406      *
407      * @return          function status
408      */
ms_usb_clear_halt(struct usb_device * pDev,int pipe)409 int ms_usb_clear_halt(struct usb_device *pDev, int pipe)
410 {
411     int retval;
412     int endp;
413 
414     if (usb_pipein (pipe))
415         endp = usb_pipeendpoint(pipe) | USB_DIR_IN;
416     else
417         endp = usb_pipeendpoint(pipe);
418 
419     retval = ms_usb_control_cmd(pDev, usb_sndctrlpipe(pDev, 0),
420             USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0, endp, NULL, 0,
421             HZ * USB_CTRL_SET_TIMEOUT);
422 
423     if (retval < 0)
424         return retval;
425     else
426     {
427         usb_settoggle(pDev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0);
428         //usb_endpoint_running(pDev, usb_pipeendpoint(pipe), usb_pipeout(pipe));
429 
430         return 0;
431     }
432 
433 }
434 
435 /**
436      * @brief               disable the endpoint
437      *
438      * @param pDev
439      * @param epaddr
440      *
441      * @return          none
442      */
ms_usb_disable_endpoint(struct usb_device * pDev,U32 epaddr)443 void ms_usb_disable_endpoint(struct usb_device *pDev, U32 epaddr)
444 {
445     U32 u32Ept = epaddr & USB_ENDPOINT_NUMBER_MASK;
446 
447     if (!pDev)
448         return;
449     //if (pDev && pDev->bus && pDev->bus->bus_ops && pDev->bus->bus_ops->ms_disable_ep)
450     {
451         if (pDev->pEpMaxPacketIn[u32Ept] || pDev->pEpMaxPacketOut[u32Ept])
452         {
453             ms_usb_hcd_flush_endpoint(pDev, epaddr);
454             /* unbind interface considered not to disable endpoint */
455             //pDev->bus->bus_ops->ms_disable_ep(pDev, epaddr);
456             ms_hcd_endpoint_disable(pDev, epaddr);
457             ms_hcd_check_dev_urb(pDev, epaddr); // check urb
458         }
459     }
460 }
461 
462 /**
463      * @brief               disable the interface
464      *
465      * @param pDev
466      * @param pIntf
467      *
468      * @return          none
469      */
ms_usb_disable_interface(struct usb_device * pDev,struct usb_interface * pIntf)470 void ms_usb_disable_interface(struct usb_device *pDev, struct usb_interface *pIntf)
471 {
472     int EptIdx;
473     struct usb_host_interface *hintf = &pIntf->altsetting[pIntf->act_altsetting];
474 
475     for (EptIdx = 0; EptIdx < hintf->desc.bNumEndpoints; ++EptIdx)
476         ms_usb_disable_endpoint(pDev, hintf->endpoint[EptIdx].desc.bEndpointAddress);
477 }
478 
479 /**
480      * @brief               disable the device
481      *
482      * @param pDev
483      * @param skip_ep0
484      *
485      * @return          none
486      */
ms_usb_disable_device(struct usb_device * pDev,int skip_ep0)487 void ms_usb_disable_device(struct usb_device *pDev, int skip_ep0)
488 {
489     int EptIdx, i;
490 
491     if (pDev->actconfig)
492     {
493         for (i = 0; i < pDev->actconfig->desc.bNumInterfaces; i++)
494         {
495             struct usb_interface  *pUiface;
496 
497             /* remove this interface */
498             pUiface = pDev->actconfig->interface[i];
499             ms_usbhost_debug("%s - unregistering interface %s\n",
500                             pUdev->dev.dev_name, pUdev->dev.bus_id);
501             ms_device_unregister(&pUiface->dev);
502         }
503         /* patched from Linux */
504         pDev->actconfig = NULL;
505         if (pDev->eState == USB_STATE_CONFIGURED)
506             ms_usb_set_device_state(pDev, USB_STATE_ADDRESS);
507     }
508 
509     /* if check_bandwidth, that needs two phases of disable endpoint */
510     for (EptIdx = skip_ep0; EptIdx < 16; ++EptIdx)
511     {
512         ms_usb_disable_endpoint(pDev, EptIdx);
513         ms_usb_disable_endpoint(pDev, EptIdx + USB_DIR_IN);
514     }
515 }
516 
517 /**
518      * @brief               enable the endpoint
519      *
520      * @param pDev
521      * @param pEpt_desc
522      *
523      * @return          none
524      */
ms_usb_enable_endpoint(struct usb_device * pDev,struct usb_endpoint_descriptor * pEpt_desc)525 void ms_usb_enable_endpoint(struct usb_device *pDev,
526     struct usb_endpoint_descriptor *pEpt_desc)
527 {
528     unsigned int eptaddr = pEpt_desc->bEndpointAddress;
529     unsigned int eptnum = eptaddr & USB_ENDPOINT_NUMBER_MASK;
530     int is_control = ((pEpt_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
531         USB_ENDPOINT_XFER_CONTROL);
532 
533     if (usb_endpoint_dir(eptaddr) || is_control)
534     {
535         //usb_endpoint_running(pDev, eptnum, 1);
536         usb_settoggle(pDev, eptnum, 1, 0);
537         pDev->pEpMaxPacketOut[eptnum] = pEpt_desc->wMaxPacketSize;
538     }
539 
540     if (!usb_endpoint_dir(eptaddr) || is_control)
541     {
542         //usb_endpoint_running(pDev, eptnum, 0);
543         usb_settoggle(pDev, eptnum, 0, 0);
544         pDev->pEpMaxPacketIn[eptnum] = pEpt_desc->wMaxPacketSize;
545     }
546 }
547 
548 /**
549      * @brief               enable the interface
550      *
551      * @param pDev
552      * @param pIntf
553      *
554      * @return          none
555      */
ms_usb_enable_interface(struct usb_device * pDev,struct usb_interface * pIntf)556 void ms_usb_enable_interface(struct usb_device *pDev,
557     struct usb_interface *pIntf)
558 {
559     struct usb_host_interface *pAlt_set =
560             &pIntf->altsetting[pIntf->act_altsetting];
561     int i;
562 
563     for (i = 0; i < pAlt_set->desc.bNumEndpoints; ++i)
564         ms_usb_enable_endpoint(pDev, &pAlt_set->endpoint[i].desc);
565 }
566 
567 /**
568      * @brief               set specific interface to the device
569      *
570      * @param pDev
571      * @param interface
572      * @param alternate
573      *
574      * @return          function status
575      */
ms_usb_set_interface(struct usb_device * pDev,int interface,int alternate)576 int ms_usb_set_interface(struct usb_device *pDev, int interface, int alternate)
577 {
578     struct usb_interface *pIntf;
579     int ret;
580     int manual = 0;
581 
582     pIntf = ms_usb_ifnum_to_if(pDev, interface);
583     if (!pIntf)
584     {
585         ms_usbhost_err("Invalid interface %d", interface);
586         return -EINVAL;
587     }
588 
589     if (alternate < 0 || alternate >= pIntf->num_altsetting)
590         return -EINVAL;
591 
592     ret = ms_usb_control_cmd(pDev, usb_sndctrlpipe(pDev, 0),
593                 USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE,
594                 pIntf->altsetting[alternate]
595                 .desc.bAlternateSetting,
596                 interface, NULL, 0, HZ * 5);
597 
598     if (ret == -EPIPE && pIntf->num_altsetting == 1)
599     {
600         ms_debug_msg("manual set interface for pIntf %d, alt %d",
601         interface, alternate);
602         manual = 1;
603     }
604     else if (ret < 0)
605         return ret;
606 
607     ms_usb_disable_interface(pDev, pIntf);
608 
609     pIntf->act_altsetting = alternate;
610 
611     if (manual)
612     {
613         struct usb_host_interface *iface_as = &pIntf->altsetting[alternate];
614         int ii;
615 
616         for (ii = 0; ii < iface_as->desc.bNumEndpoints; ii++)
617         {
618             unsigned int epaddr = iface_as->endpoint[ii].desc.bEndpointAddress;
619             unsigned int pipe =
620             __pack_pipe(pDev, USB_ENDPOINT_NUMBER_MASK & epaddr)
621             | (usb_endpoint_dir(epaddr) ? USB_DIR_OUT : USB_DIR_IN);
622 
623             ms_usb_clear_halt(pDev, pipe);
624         }
625     }
626 
627     ms_usb_enable_interface(pDev, pIntf);
628 
629     return 0;
630 }
631 
632 /**
633      * @brief               set specific configuration to the device
634      *
635      * @param pDev
636      * @param config_val
637      *
638      * @return          function status
639      */
ms_usb_set_config(struct usb_device * pDev,int config_val)640 int ms_usb_set_config(struct usb_device *pDev, int config_val)
641 {
642     int i, ret;
643     struct usb_host_config *cp = NULL;
644 
645     for (i=0; i<pDev->descriptor.bNumConfigurations; i++)
646     {
647         if (pDev->config[i].desc.bConfigurationValue == config_val)
648         {
649             cp = &pDev->config[i];
650             break;
651         }
652     }
653     if ((!cp && config_val != 0) || (cp && config_val == 0))
654     {
655         ms_usbhost_err("selecting invalid config_val %d", config_val);
656         return -EINVAL;
657     }
658 
659     if (pDev->eState != USB_STATE_ADDRESS)
660         ms_usb_disable_device (pDev, 1);  // Skip ep0
661     pDev->toggle[0] = pDev->toggle[1] = 0;
662     //pDev->halted[0] = pDev->halted[1] = 0; // Obsolete
663     //pDev->eState = USB_STATE_ADDRESS;
664     ms_usb_set_device_state(pDev, USB_STATE_ADDRESS);
665 
666     if ((ret = ms_usb_control_cmd(pDev, usb_sndctrlpipe(pDev, 0),
667         USB_REQ_SET_CONFIGURATION, 0, config_val, 0,
668         NULL, 0, HZ * USB_CTRL_SET_TIMEOUT)) < 0)
669         return ret;
670     if (config_val)
671         //pDev->eState = USB_STATE_CONFIGURED;
672         ms_usb_set_device_state(pDev, USB_STATE_CONFIGURED);
673     pDev->actconfig = cp;
674 
675     for (i = 0; i < cp->desc.bNumInterfaces; ++i)
676     {
677         struct usb_interface *intf = cp->interface[i];
678 
679         intf->act_altsetting = 0;
680         ms_usb_enable_interface(pDev, intf);
681     }
682 
683     return 0;
684 }
685 
686 
687 /**
688      * @brief               get the string from the device
689      *
690      * @param pDev
691      * @param index
692      * @param pBuf
693      * @param size
694      *
695      * @return          function status
696      */
ms_usb_string(struct usb_device * pDev,int index,char * pBuf,size_t size)697 int ms_usb_string(struct usb_device *pDev, int index, char *pBuf, size_t size)
698 {
699     unsigned char *pTmp_buf;
700     int err, len;
701     U32 u, idx;
702     void *addr_t;
703 
704     if ( (int)size <= 0 || !pBuf || !index)
705         return -EINVAL;
706 
707     pBuf[0] = 0;
708     pTmp_buf = (unsigned char*) kmalloc(256, GFP_KERNEL);
709 
710     if (!pTmp_buf)
711         return -ENOMEM;
712 
713     addr_t = (void *)pTmp_buf;
714     /* get langid for strings if it's not yet known */
715     if (!pDev->u32HaveLangId)
716     {
717         err = ms_usb_control_cmd(pDev, usb_rcvctrlpipe(pDev, 0),
718 	        USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
719 	        (USB_DT_STRING << 8), 0, pTmp_buf, 4,
720 	        HZ * USB_CTRL_GET_TIMEOUT);
721 
722         if (err < 0)
723         {
724             ms_debug_err("error getting string descriptor 0 (error=%d)\n", err);
725             goto errout;
726         }
727         else if (err < 4 || pTmp_buf[0] < 4)
728         {
729             ms_debug_msg("string descriptor 0 too short!\n");
730             err = -EINVAL;
731             goto errout;
732         }
733         else
734         {
735             pDev->u32HaveLangId = -1;
736             pDev->u32StringLangId = pTmp_buf[2] | (pTmp_buf[3]<< 8);
737             /* always use the first langid listed */
738             ms_debug_debug("USB device number %d default language ID 0x%x\n",
739             pDev->u32DevNum, pDev->u32StringLangId);
740         }
741     }
742 
743     err = ms_usb_control_cmd(pDev, usb_rcvctrlpipe(pDev, 0),
744             USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
745             (USB_DT_STRING << 8) + index, pDev->u32StringLangId, pTmp_buf, 2,
746             HZ * USB_CTRL_GET_TIMEOUT);
747 
748     if(err<2)
749         goto errout;
750     else if (pTmp_buf[1]!=3)
751     {
752         err = -EINVAL;
753         goto errout;
754     }
755     len=pTmp_buf[0];
756 
757     err = ms_usb_control_cmd(pDev, usb_rcvctrlpipe(pDev, 0),
758             USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
759             (USB_DT_STRING << 8) + index, pDev->u32StringLangId, pTmp_buf, len,
760             HZ * USB_CTRL_GET_TIMEOUT);
761 
762     if (err < 0)
763         goto errout;
764 
765     size--;
766     for (idx = 0, u = 2; u < (U32) err; u += 2)
767     {
768         if (idx >= size)
769             break;
770         if (pTmp_buf[u+1])
771             pBuf[idx++] = '?';
772         else
773             pBuf[idx++] = pTmp_buf[u];
774     }
775     pBuf[idx] = 0;
776     err = idx;
777 
778 errout:
779     kfree(addr_t);
780     return err;
781 }
782