xref: /utopia/UTPA2-700.0.x/modules/usb/drv/usb_ecos/newhost/drvHub.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 //#include <MsCommon.h> // NUSED
79 
80 #include  "include/drvConfig.h"
81 //#include  "include/drvCompiler.h" // NUSED
82 //#include  "include/drvTypes.h" // NUSED
83 #include  "include/drvErrno.h"
84 //#include  "include/drvPorts.h" // NUSED
85 //#include  "include/drvPCIMEM.h" // NUSED
86 //#include  "include/drvTimer.h" // NUSED
87 //#include  "include/drvList.h" // NUSED
88 #include  "include/drvKernel.h"
89 //#include  "include/drvBitops.h" // NUSED
90 //#include "include/drvCPE_AMBA.h" // NUSED
91 
92 // USB related header files
93 //#include "include/drvUSBHost.h" // NUSED
94 #include "drvUSBCore.h"
95 //#include "drvUsbd.h" // NUSED
96 //#include "drvHub.h" // NUSED
97 #include "drvEHCI.h"
98 #include "drvUSBHwCtl.h"
99 /* applying drvUsbHostConfig.h (inside drvUSBHwCtl.h) */
100 
101 //#define DBG_DBG
102 #ifdef DBG_DBG
103 #undef ms_usbhost_debug
104 #define ms_usbhost_debug(fmt, arg...)    \
105         do {diag_printf(fmt, ##arg);} while(0)
106 #endif
107 
108 //struct list_head hub_list =            { &(hub_list), &(hub_list) };
109 
110 /**
111      * @brief               Interpreting post speed by text
112      *
113      * @param           int portstatus
114      *
115      * @return          Speed description
116      */
ms_portspeed(int portstatus)117 static __inline__ char *ms_portspeed (int portstatus)
118 {
119     if (portstatus & USB_PORT_STAT_HIGH_SPEED)
120         return "480 Mb/s";
121     else if (portstatus & USB_PORT_STAT_LOW_SPEED)
122         return "1.5 Mb/s";
123     else
124         return "12 Mb/s";
125 }
126 
127 /**
128      * @brief               retrieving  generic device pointer from usb device
129      *
130      * @param           struct usb_device *ms_dev
131      *
132      * @return          generic device pointer
133      */
ms_hubdev(struct usb_device * ms_dev)134 static __inline__ struct device_s *ms_hubdev (struct usb_device *ms_dev)
135 {
136     return &ms_dev->actconfig->interface[0]->dev;
137 }
138 
139 /**
140      * @brief               hub driver complete function
141      *
142      * @param           struct urb *urb
143      * @param           struct stPtRegs *regs
144      *
145      * @return          none
146      */
ms_hub_irq(struct urb * urb,struct stPtRegs * regs)147 static void ms_hub_irq(struct urb *urb, struct stPtRegs *regs)
148 {
149     struct usb_hub *pHub = (struct usb_hub *)urb->pContext;
150     U32 flags;
151     int status;
152     int ms_rtval = ENOENT;
153     struct usb_hcd    *hcd = (struct usb_hcd*) urb->dev->bus->hcpriv;
154 
155     switch (urb->s32Status)
156     {
157         case -ENOENT:
158         case -ECONNRESET:
159         case -ESHUTDOWN:
160             ms_usbhost_debug("<%s> urb->status : %d \n", __FUNCTION__, (int)urb->s32Status);
161             return;
162 
163         default:
164             ms_usbhost_debug ("transfer --> %d\n", urb->s32Status);
165             ms_rtval = urb->s32Status;
166             if ((++pHub->nerrors < 10) || pHub->error)
167                 goto resubmit;
168             pHub->error = urb->s32Status;
169 
170         case 0:
171             break;
172     }
173 
174     pHub->nerrors = 0;
175 
176     osapi_spin_lock_irqsave(&hub_event_lock, flags);
177     if (!pHub->disconnected && ms_is_empty_list(&pHub->event_list))
178     {
179         //list_add(&pHub->event_list, &hub_event_list);
180         ms_insert_list_after(&pHub->event_list, hcd->phub_event); // new, link to the right hcd
181 
182         ms_usbhost_debug("%s:%s >>> Add HUB EVENT!\n", hcd->product_desc, interface_to_usbdev(pHub->intf)->devpath);
183     }
184     osapi_spin_unlock_irqrestore(&hub_event_lock, flags);
185 
186 resubmit:
187     if ((status = ms_usb_submit_urb (pHub->urb, GFP_ATOMIC)) != 0
188         /* ENODEV means we raced disconnect() */
189         && status != -ENODEV)
190     {
191         diag_printf ("previous urb status is %d, resubmit --> %d\n", ms_rtval, status);
192         diag_printf ("hcd->state=%d\n",hcd->state);
193     }
194 }
195 
196 /**
197      * @brief               hub power on function
198      *
199      * @param           struct usb_hub *hub
200      *
201      * @return          none
202      */
ms_hub_power_on(struct usb_hub * hub)203 void ms_hub_power_on(struct usb_hub *hub)
204 {
205     struct usb_device *ms_dev;
206     int i;
207 
208     ms_usbhost_debug("enabling power on all ports, delay %d\n", hub->descriptor.bPwrOn2PwrGood * 2);
209     ms_dev = interface_to_usbdev(hub->intf);
210     for (i = 0; i < hub->descriptor.bNbrPorts; i++)
211         // (USB_PORT_FEAT_POWER)
212         ms_usb_control_cmd(ms_dev, usb_sndctrlpipe(ms_dev, 0),
213             USB_REQ_SET_FEATURE, USB_RT_PORT, USB_PORT_FEAT_POWER, i + 1, NULL, 0, HZ);
214 
215     wait_ms(hub->descriptor.bPwrOn2PwrGood * 2);
216 }
217 
218 /**
219      * @brief               retrieving hub current condition
220      *
221      * @param           struct usb_hub *hub
222      * @param           U16 *status_r
223      * @param           U16 *change_r
224      *
225      * @return          error code
226      */
ms_hub_hub_status(struct usb_hub * hub,U16 * status_r,U16 * change_r)227 int ms_hub_hub_status(struct usb_hub *hub, U16 *status_r, U16 *change_r)
228 {
229     struct usb_device *ms_dev = interface_to_usbdev (hub->intf);
230     S32 s32Ret;
231 
232     // ms_get_hub_status
233     s32Ret = ms_usb_control_cmd(ms_dev, usb_rcvctrlpipe(ms_dev, 0),
234         USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_HUB, 0, 0,
235         &hub->status.hub, sizeof(hub->status.hub), HZ * USB_CTRL_GET_TIMEOUT);
236     if (s32Ret < 0)
237     {
238         ms_usbhost_err ("<%s> failed (err = %d)\n", __FUNCTION__, (int)s32Ret);
239     }
240     else
241     {
242         *status_r = hub->status.hub.wHubStatus;
243         *change_r = hub->status.hub.wHubChange;
244         s32Ret = 0;
245     }
246     return s32Ret;
247 }
248 
249 /**
250      * @brief               hub configure by hub descriptor
251      *
252      * @param           struct usb_hub *hub
253      * @param           struct usb_endpoint_descriptor *endpoint
254      *
255      * @return          error code
256      */
ms_hub_configure(struct usb_hub * hub,struct usb_endpoint_descriptor * endpoint)257 static int ms_hub_configure(struct usb_hub *hub,
258   struct usb_endpoint_descriptor *endpoint)
259 {
260     struct usb_device *ms_dev = interface_to_usbdev (hub->intf);
261     //struct device_s *hub_dev;
262     U16 hubstatus, hubchange;
263     U32 pipe;
264     S32 maxp, s32Ret;
265     char *message;
266 
267     hub->buffer = (char (*)[3]) ms_usb_buffer_alloc(ms_dev, sizeof(*hub->buffer), GFP_KERNEL,
268         &hub->buffer_dma);
269     if (!hub->buffer)
270     {
271         message = "can't allocate hub irq buffer";
272         s32Ret = -ENOMEM;
273         goto fail;
274     }
275 
276     // ms_get_hub_descriptor
277     s32Ret = ms_usb_control_cmd(ms_dev, usb_rcvctrlpipe(ms_dev, 0),
278         USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB,
279         USB_DT_HUB << 8, 0, &hub->descriptor, sizeof(hub->descriptor), HZ * USB_CTRL_GET_TIMEOUT);
280     if (s32Ret < 0)
281     {
282         message = "can't read hub descriptor";
283         goto fail;
284     }
285     else if (hub->descriptor.bNbrPorts > USB_MAXCHILDREN)
286     {
287         message = "hub has too many ports!";
288         s32Ret = -ENODEV;
289         goto fail;
290     }
291 
292     //hub_dev = ms_hubdev(ms_dev);
293     ms_dev->u32MaxChild = hub->descriptor.bNbrPorts;
294     ms_usbhost_msg ("%d port%s detected\n", ms_dev->u32MaxChild, (ms_dev->u32MaxChild == 1) ? "" : "s");
295 
296     hub->descriptor.wHubCharacteristics = hub->descriptor.wHubCharacteristics;
297 
298     if (hub->descriptor.wHubCharacteristics & HUB_CHAR_COMPOUND)
299     {
300         int  i;
301         char  portstr [USB_MAXCHILDREN + 1];
302 
303         for (i = 0; i < ms_dev->u32MaxChild; i++)
304           portstr[i] = hub->descriptor.DeviceRemovable[((i + 1) / 8)] & (1 << ((i + 1) % 8))
305             ? 'F' : 'R';
306         portstr[ms_dev->u32MaxChild] = 0;
307         ms_usbhost_msg("compound device; port removable status: %s\n", portstr);
308     }
309     else
310         ms_usbhost_debug("Standalone hub\n");
311 
312     switch (hub->descriptor.wHubCharacteristics & HUB_CHAR_LPSM)
313     {
314         case 0x00:
315             ms_usbhost_debug("Ganged power switching\n");
316             break;
317         case 0x01:
318             ms_usbhost_debug("Individual port power switching\n");
319             break;
320         case 0x02:
321         case 0x03:
322             ms_usbhost_debug("Unknown reserved power switching mode\n");
323             break;
324     }
325 
326     switch (hub->descriptor.wHubCharacteristics & HUB_CHAR_OCPM)
327     {
328         case 0x00:
329           ms_usbhost_debug("Global over-current protection\n");
330           break;
331         case 0x08:
332           ms_usbhost_debug("Individual port over-current protection\n");
333           break;
334         case 0x10:
335         case 0x18:
336           ms_usbhost_debug("No over-current protection\n");
337           break;
338     }
339 
340     osapi_spin_lock_init (&hub->tt.lock);
341     ms_list_init (&hub->tt.clear_list);
342     //INIT_WORK (&hub->tt.kevent, hub_tt_kevent, hub);
343     switch (ms_dev->descriptor.bDeviceProtocol)
344     {
345         case 0:
346           break;
347         case 1:
348           ms_usbhost_debug("Single TT\n");
349           hub->tt.hub = ms_dev;
350           break;
351         case 2:
352           ms_usbhost_debug("TT per port\n");
353           hub->tt.hub = ms_dev;
354           hub->tt.multi = 1;
355           break;
356         default:
357           ms_usbhost_err("Unrecognized hub protocol %d\n", ms_dev->descriptor.bDeviceProtocol);
358           break;
359     }
360 
361     switch (hub->descriptor.wHubCharacteristics & HUB_CHAR_TTTT)
362     {
363         case 0x00:
364             if (ms_dev->descriptor.bDeviceProtocol != 0)
365             {
366                 hub->tt.think_time = 666;
367                 ms_usbhost_debug("TT requires at most 8 FS bit times\n");
368             }
369             break;
370         case 0x20:
371             hub->tt.think_time = 666 * 2;
372             ms_usbhost_debug("TT requires at most 16 FS bit times\n");
373             break;
374         case 0x40:
375             hub->tt.think_time = 666 * 3;
376             ms_usbhost_debug("TT requires at most 24 FS bit times\n");
377             break;
378         case 0x60:
379             hub->tt.think_time = 666 * 4;
380             ms_usbhost_debug("TT requires at most 32 FS bit times\n");
381             break;
382     }
383 
384     ms_usbhost_debug("Port LEDs are %s supported\n",(hub->descriptor.wHubCharacteristics & HUB_CHAR_PORTIND)? "" : "not");
385     ms_usbhost_debug("Power on to power good last time: %dms\n", hub->descriptor.bPwrOn2PwrGood * 2);
386     ms_usbhost_debug("Hub current requirement: %dmA\n", hub->descriptor.bHubContrCurrent);
387 
388     s32Ret = ms_hub_hub_status(hub, &hubstatus, &hubchange);
389     if (s32Ret < 0)
390     {
391         message = "can't get hub status";
392         goto fail;
393     }
394 
395     ms_usbhost_debug("Local power source is %s\n",(hubstatus & HUB_STATUS_LOCAL_POWER)? "lost (inactive)" : "good");
396 
397     ms_usbhost_debug("%s over-current exists\n",(hubstatus & HUB_STATUS_OVERCURRENT) ? "" : "No");
398 
399     pipe = usb_rcvintpipe(ms_dev, endpoint->bEndpointAddress);
400     maxp = usb_maxpacket(ms_dev, pipe, usb_pipeout(pipe));
401 
402     if ((U32) maxp > sizeof(*hub->buffer))
403         maxp = sizeof(*hub->buffer);
404 
405     hub->urb = ms_usb_alloc_urb(GFP_KERNEL);
406     if (!hub->urb)
407     {
408         message = "couldn't allocate interrupt urb";
409         s32Ret = -ENOMEM;
410         goto fail;
411     }
412 
413     ms_usb_stuff_intr_urb(hub->urb, ms_dev, pipe, *hub->buffer, maxp, ms_hub_irq,
414         hub, endpoint->bInterval);
415     hub->urb->tTransferDma = hub->buffer_dma;
416     hub->urb->u32TransferFlags |= MS_FLAG_URB_NO_TRANSFER_DMA_MAP;
417 
418     /* power on hub before submit urb */
419     ms_hub_power_on(hub);
420 
421     s32Ret = ms_usb_submit_urb(hub->urb, GFP_KERNEL);
422     if (s32Ret)
423     {
424         message = "couldn't submit status urb";
425         goto fail;
426     }
427 
428     return 0;
429 
430 fail:
431     ms_usbhost_err("Hub config failed, %s (err %d)\n", message, s32Ret);
432     return s32Ret;
433 }
434 
435 /**
436      * @brief           hub disconnect service
437      *
438      * @param           struct usb_interface *intf
439      *
440      * @return          none
441      */
ms_hub_disconnect(struct usb_interface * intf)442 static void ms_hub_disconnect(struct usb_interface *intf)
443 {
444     struct usb_hub *pHub = (struct usb_hub*) ms_usb_get_intfdata (intf);
445     U32 flags;
446 
447     if (!pHub)
448         return;
449 
450     osapi_spin_lock_irqsave(&hub_event_lock, flags);
451     /* Delete it and then reset it */
452     if (!ms_is_empty_list(&pHub->event_list))
453     {
454         ms_list_remove(&pHub->event_list);
455         ms_list_init(&pHub->event_list);
456     }
457     //ms_list_remove(&pHub->hub_list);
458     //ms_list_init(&pHub->hub_list);
459     pHub->disconnected = 1;
460     osapi_spin_unlock_irqrestore(&hub_event_lock, flags);
461 
462     /* All children disconnect  and cease the hub */
463     pHub->error = 0;
464     //ms_hub_quiesce(pHub, HUB_DISCONNECT);
465 
466     ms_usb_set_intfdata (intf, NULL);
467 
468     if (pHub->urb)
469     {
470         ms_usbhost_debug("hub_disconnect: unlink urb %p\n", pHub->urb);
471         //ms_usb_unlink_urb(pHub->urb); // patch from Linux 2.6.28
472         ms_usb_free_urb(pHub->urb);
473         pHub->urb = NULL;
474     }
475 
476     if (pHub->buffer)
477     {
478         ms_usb_buffer_free(interface_to_usbdev(intf),
479             sizeof(*pHub->buffer), pHub->buffer, pHub->buffer_dma);
480         pHub->buffer = NULL;
481     }
482 
483     kfree(pHub);
484 }
485 
486 /**
487      * @brief               hub driver probe function
488      *
489      * @param           struct usb_interface *intf
490      * @param           const struct usb_device_id *id
491      *
492      * @return          error code
493      */
ms_hub_probe(struct usb_interface * pIntf,const struct usb_device_id * id)494 static int ms_hub_probe(struct usb_interface *pIntf, const struct usb_device_id *id)
495 {
496     struct usb_host_interface *pHIdesc;
497     struct usb_endpoint_descriptor *pEndpoint;
498     struct usb_device *pUdev;
499     struct usb_hub *pHub;
500     //U32 flags;
501 
502     pHIdesc = pIntf->altsetting + pIntf->act_altsetting;
503     pUdev = interface_to_usbdev(pIntf);
504 
505     if (pUdev->level == MAX_HUB_TOPO_LEVEL)
506     {
507         ms_usbhost_msg("hub nested too deep, level = %d\n", MAX_HUB_TOPO_LEVEL);
508         return -MS_ERR_2BIG;
509     }
510 
511     if ((pHIdesc->desc.bInterfaceSubClass != 0) && (pHIdesc->desc.bInterfaceSubClass != 1))
512     {
513 descriptor_error:
514         ms_usbhost_err("bad descriptor, ignoring hub\n");
515         return -EIO;
516     }
517 
518     if (pHIdesc->desc.bNumEndpoints != 1)
519     {
520         goto descriptor_error;
521     }
522 
523     pEndpoint = &pHIdesc->endpoint[0].desc;
524 
525     // Determine hub endpoint attribute as interrupt IN
526     if (!(pEndpoint->bEndpointAddress & USB_DIR_IN))
527     {
528         goto descriptor_error;
529     }
530     if ((pEndpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
531         != USB_ENDPOINT_XFER_INT)
532     {
533         goto descriptor_error;
534     }
535 
536     ms_usbhost_msg ("USB hub found\n");
537 
538     pHub = (struct usb_hub*) kmalloc(sizeof(*pHub), GFP_KERNEL);
539     if (!pHub)
540     {
541         ms_usbhost_err("couldn't kmalloc hub struct\n");
542         return -ENOMEM;
543     }
544 
545     memset(pHub, 0, sizeof(*pHub));
546 
547     ms_list_init(&pHub->event_list);
548     pHub->intf = pIntf;
549 
550     //osapi_spin_lock_irqsave(&hub_event_lock, flags);
551     //ms_list_init(&pHub->hub_list);
552     //ms_insert_list_after(&pHub->hub_list, &hub_list);
553     //osapi_spin_unlock_irqrestore(&hub_event_lock, flags);
554 
555     ms_usb_set_intfdata (pIntf, pHub);
556 
557     if (ms_hub_configure(pHub, pEndpoint) >= 0)
558         return 0;
559 
560     ms_hub_disconnect (pIntf);
561     return -ENODEV;
562 }
563 
564 /**
565      * @brief               hub reset according to hub tree
566      *
567      * @param           struct usb_hub *hub
568      *
569      * @return          error code
570      */
ms_hub_reset(struct usb_hub * hub)571 int ms_hub_reset(struct usb_hub *hub)
572 {
573     struct usb_device *ms_dev = interface_to_usbdev(hub->intf);
574     int i;
575 
576     ms_usbhost_msg("\nhub reset\n");
577     for (i = 0; i < hub->descriptor.bNbrPorts; i++)
578     {
579         if (ms_dev->children[i])
580             ms_usb_disconnect(&ms_dev->children[i]);
581     }
582 
583     if (hub->urb)
584     {
585         ms_usb_unlink_urb(hub->urb);
586         ms_usbhost_msg("hub_reset: unlink urb\n");
587     }
588     else
589         return -1;
590 
591     if (ms_usb_reset_device(ms_dev))
592         return -1;
593 
594     hub->urb->dev = ms_dev;
595     if (ms_usb_submit_urb(hub->urb, GFP_KERNEL))
596         return -1;
597 
598     ms_hub_power_on(hub);
599 
600     return 0;
601 }
602 
603 /**
604      * @brief               hub disconnect by hub tree
605      *
606      * @param           struct usb_device *ms_dev
607      *
608      * @return          none
609      */
ms_hub_start_disconnect(struct usb_device * ms_dev)610 void ms_hub_start_disconnect(struct usb_device *ms_dev)
611 {
612     struct usb_device *ms_parent = ms_dev->parent;
613     int i;
614 
615     if (ms_parent)
616     {
617         for (i = 0; i < ms_parent->u32MaxChild; i++)
618         {
619             if (ms_parent->children[i] == ms_dev)
620             {
621                 ms_usb_disconnect(&ms_parent->children[i]);
622                 return;
623             }
624         }
625     }
626 
627     ms_usbhost_err("cannot disconnect hub %s\n", ms_dev->devpath);
628 }
629 
630 /**
631      * @brief               retrieving hub port current condition
632      *
633      * @param           struct usb_device *dev
634      * @param           int port
635      * @param           U16 *status_r
636      * @param           U16 *change_r
637      *
638      * @return          error code
639      */
ms_hub_port_status(struct usb_device * ms_dev,int port,U16 * status_r,U16 * change_r)640 int ms_hub_port_status(struct usb_device *ms_dev, int port,
641              U16 *status_r, U16 *change_r)
642 {
643     struct usb_hub *hub = (struct usb_hub*) ms_usb_get_intfdata(ms_dev->actconfig->interface[0]);
644     S32 s32Err;
645 
646     // ms_get_port_status
647     s32Err = ms_usb_control_cmd(ms_dev, usb_rcvctrlpipe(ms_dev, 0),
648         USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, 0, port+1,
649         &hub->status.port, sizeof(hub->status.port), HZ * USB_CTRL_GET_TIMEOUT);
650     if (s32Err < 0)
651     {
652         ms_usbhost_err("%s failed (err = %d)\n", __FUNCTION__, (int)s32Err);
653     }
654     else
655     {
656         *status_r = hub->status.port.wPortStatus;
657         *change_r = hub->status.port.wPortChange;
658         s32Err = 0;
659     }
660     return s32Err;
661 }
662 
663 /**
664      * @brief               hub port reset waiting function
665      *
666      * @param           struct usb_device *hub
667      * @param           int port
668      * @param           struct usb_device *ms_dev
669      * @param           U32 delay
670      *
671      * @return          error code, -1 on error, 0 on success, 1 on disconnect.
672      */
ms_hub_port_wait_reset(struct usb_device * hub,int port,struct usb_device * ms_dev,U32 delay)673 static int ms_hub_port_wait_reset(struct usb_device *hub, int port,
674         struct usb_device *ms_dev, U32 delay)
675 {
676     S32 s32Dtime, s32Ret;
677     U16 u16Portstatus;
678     U16 u16Portchange;
679 
680     for (s32Dtime = 0; s32Dtime < HUB_RESET_TIMEOUT; s32Dtime += delay)
681     {
682         wait_ms(delay);
683 
684         s32Ret = ms_hub_port_status(hub, port, &u16Portstatus, &u16Portchange);
685         if (s32Ret < 0) {
686             if (s32Ret == -ENODEV)
687                 return 1;
688             else
689                 return -1;
690         }
691 
692         if (!(u16Portstatus & USB_PORT_STAT_CONNECTION))
693             return 1;
694 
695         if ((u16Portchange & USB_PORT_STAT_C_CONNECTION))
696             //return -1;
697             return 1; // disconnect
698 
699         if (!(u16Portstatus & USB_PORT_STAT_RESET) &&
700             (u16Portstatus & USB_PORT_STAT_ENABLE))
701         {
702             if (u16Portstatus & USB_PORT_STAT_HIGH_SPEED)
703                 ms_dev->eSpeed = USB_HIGH_SPEED;
704             else if (u16Portstatus & USB_PORT_STAT_LOW_SPEED)
705                 ms_dev->eSpeed = USB_LOW_SPEED;
706             else
707                 ms_dev->eSpeed = USB_FULL_SPEED;
708             ms_usbhost_msg("::Device Speed is %s\n", ms_portspeed(u16Portstatus));
709             return 0;
710         }
711 
712         if (s32Dtime >= 2 * HUB_SHORT_RESET_TIME)
713             delay = HUB_LONG_RESET_TIME;
714 
715         ms_usbhost_debug ("port %d not reset yet, waiting %dms\n", port + 1, delay);
716     }
717 
718     return -1;
719 }
720 
721 /**
722      * @brief               hub port reset command
723      *
724      * @param           struct usb_device *hub
725      * @param           int port
726      * @param           struct usb_device *ms_dev
727      * @param           U32 delay
728      *
729      * @return          error code
730      */
ms_hub_port_reset(struct usb_device * hub,int port,struct usb_device * ms_dev,U32 delay)731 static int ms_hub_port_reset(struct usb_device *hub, int port,
732         struct usb_device *ms_dev, U32 delay)
733 {
734     int i, status;
735 
736     /* patch for DM always keep high issue */
737     #if (_USB_HS_CUR_DRIVE_DM_ALLWAYS_HIGH_PATCH)
738     /* turn off overwrite mode */
739     if (hub->parent == NULL)
740     {
741       struct usb_hcd *hcd = (struct usb_hcd*) hub->bus->hcpriv;
742       struct cpe_dev *dev;
743       const struct device_s *__mptr = hcd->controller;
744       dev = (struct cpe_dev *)( (char *)__mptr - offsetof(struct cpe_dev,dev) );
745       U32 regUTMI = dev->utmibase;
746 
747       usb_writeb(usb_readb((void*)(regUTMI+0x0*2)) & ~BIT1, (void*) (regUTMI+0x0*2)); //tern_ov = 0
748     }
749     #endif
750 
751     for (i = 0; i < HUB_RESET_TRIES; i++)
752     {
753         // (USB_PORT_FEAT_RESET)
754         ms_usb_control_cmd(hub, usb_sndctrlpipe(hub, 0),
755             USB_REQ_SET_FEATURE, USB_RT_PORT, USB_PORT_FEAT_RESET, port+1, NULL, 0, HZ);
756 
757         status = ms_hub_port_wait_reset(hub, port, ms_dev, delay);
758         ms_usbhost_debug("<hub_port_reset> loop %d, status %d\n", i, status);
759         if (status != -1)
760         {
761             // (USB_PORT_FEAT_C_RESET)
762             ms_usb_control_cmd(hub, usb_sndctrlpipe(hub, 0),
763                 USB_REQ_CLEAR_FEATURE, USB_RT_PORT, USB_PORT_FEAT_C_RESET, port+1, NULL, 0, HZ);
764             // status: 0 on success, 1 on disconnect
765             //ms_dev->eState = status ? USB_STATE_NOTATTACHED : USB_STATE_DEFAULT;
766             ms_usb_set_device_state(ms_dev, status ? USB_STATE_NOTATTACHED : USB_STATE_DEFAULT);
767             return status;
768         }
769 
770         ms_usbhost_debug("port %d not enabled, trying reset again...\n", port + 1);
771         delay = HUB_LONG_RESET_TIME; // increase reset waiting time
772     }
773 
774     ms_usbhost_err("Cannot enable port %d.  Maybe the USB cable is bad?\n", port + 1);
775 
776     return -1;
777 }
778 
779 /**
780      * @brief               hub port disable command
781      *
782      * @param           struct usb_device *hub
783      * @param           int port
784      *
785      * @return          error code
786      */
ms_hub_port_disable(struct usb_device * hub,int port)787 int ms_hub_port_disable(struct usb_device *hub, int port)
788 {
789     S32 s32Err;
790 
791     // (USB_PORT_FEAT_ENABLE)
792     s32Err = ms_usb_control_cmd(hub, usb_sndctrlpipe(hub, 0),
793         USB_REQ_CLEAR_FEATURE, USB_RT_PORT, USB_PORT_FEAT_ENABLE, port+1, NULL, 0, HZ);
794     if (s32Err)
795     {
796         ms_usbhost_err("cannot disable port %d (err = %d)\n", port + 1, (int)s32Err);
797     }
798 
799     return s32Err;
800 }
801 
ms_recursively_NOTATTACHED(struct usb_device * udev)802 static void ms_recursively_NOTATTACHED(struct usb_device *udev)
803 {
804 	int i;
805 
806 	for (i = 0; i < udev->u32MaxChild; ++i) {
807 		if (udev->children[i])
808 			ms_recursively_NOTATTACHED(udev->children[i]);
809 	}
810 	udev->eState = USB_STATE_NOTATTACHED;
811 }
812 
ms_usb_set_device_state(struct usb_device * udev,enum usb_device_state new_state)813 void ms_usb_set_device_state(struct usb_device *udev,
814     enum usb_device_state new_state)
815 {
816 	unsigned long flags;
817 
818 	osapi_spin_lock_irqsave(&device_state_lock, flags);
819 	if (udev->eState == USB_STATE_NOTATTACHED)
820 		;	/* no action */
821 	else if (new_state != USB_STATE_NOTATTACHED) {
822 		udev->eState = new_state;
823 	} else
824 		ms_recursively_NOTATTACHED(udev);
825 	osapi_spin_unlock_irqrestore(&device_state_lock, flags);
826 }
827 
828 #define HUB_DEBOUNCE_TIMEOUT  1500 //400
829 //#define HUB_DEBOUNCE_STEP      25
830 //#define HUB_DEBOUNCE_STABLE   4 // # of counts
831 /**
832      * @brief               hub port deboucing
833      *
834      * @param           struct usb_device *hub
835      * @param           int port
836      *
837      * @return          error code
838      */
ms_hub_port_debounce(struct usb_device * hub,int port)839 static int ms_hub_port_debounce(struct usb_device *hub, int port)
840 {
841     S32 s32Err;
842     S32 s32Dtime, s32Stable_count;
843     U16 u16Portchange, u16Portstatus;
844     U32 u32Connection;
845 
846     u32Connection = 0;
847     s32Stable_count = 0;
848     for (s32Dtime = 0; s32Dtime < HUB_DEBOUNCE_TIMEOUT; s32Dtime += HUB_DEBOUNCE_STEP)
849     {
850         wait_ms(HUB_DEBOUNCE_STEP);
851 
852         s32Err = ms_hub_port_status(hub, port, &u16Portstatus, &u16Portchange);
853         if (s32Err < 0)
854             return -1;
855 
856         if ((U16) (u16Portstatus & USB_PORT_STAT_CONNECTION) == u32Connection)
857         {
858             if (u32Connection)
859             {
860                 if (++s32Stable_count == HUB_DEBOUNCE_STABLE)
861                     break;
862             }
863         }
864         else
865         {
866             s32Stable_count = 0;
867         }
868         u32Connection = u16Portstatus & USB_PORT_STAT_CONNECTION;
869 
870         if ((u16Portchange & USB_PORT_STAT_C_CONNECTION))
871         {
872             // (USB_PORT_FEAT_C_CONNECTION)
873             ms_usb_control_cmd(hub, usb_sndctrlpipe(hub, 0),
874                 USB_REQ_CLEAR_FEATURE, USB_RT_PORT, USB_PORT_FEAT_C_CONNECTION, port+1, NULL, 0, HZ);
875         }
876     }
877 
878     ms_usbhost_debug("debounce: port %d: delay %dms stable %d status 0x%x\n",
879         port + 1, s32Dtime, s32Stable_count, u16Portstatus);
880 
881     return ((u16Portstatus & USB_PORT_STAT_CONNECTION)) ? 0 : 1;
882 }
883 
884 /**
885      * @brief           hub port connect change process
886      *
887      * @param           struct usb_hub *hubstate
888      * @param           int port
889      * @param           U16 portstatus
890      * @param           U16 portchange
891      *
892      * @return          none
893      */
ms_hub_port_connect_change(struct usb_hub * hubstate,int port,U16 portstatus,U16 portchange)894 static struct usb_device* ms_hub_port_connect_change(
895 	struct usb_hub *hubstate, int port, U16 portstatus, U16 portchange)
896 {
897     struct usb_device *pHub = interface_to_usbdev(hubstate->intf);
898     struct usb_device *pUdev;
899     //struct s_hcd_dev    *phcd_dev;
900     struct usb_hcd    *pHcd = (struct usb_hcd*) pHub->bus->hcpriv;
901     U32 u32Delay = HUB_SHORT_RESET_TIME;
902     int i, sErr = 0;
903 
904     ms_usbhost_msg("hub_port_connect_change ===%s===>\t",
905         ECOS_USB_HOST_LOCAL_VER);
906     ms_usbhost_msg("port %d, status %x, change %x\n",
907         port+1, portstatus, portchange);
908 
909     /* patch for DM always keep high issue */
910     #if (_USB_HS_CUR_DRIVE_DM_ALLWAYS_HIGH_PATCH)
911     /* turn on overwrite mode */
912     if (pHub->parent == NULL)
913     {
914         struct cpe_dev *dev;
915         const struct device_s *__mptr = pHcd->controller;
916         dev = (struct cpe_dev *)( (char *)__mptr - offsetof(struct cpe_dev,dev) );
917         U32 regUTMI = dev->utmibase;
918 
919         usb_writeb(usb_readb((void*)(regUTMI+0x0*2)) | BIT1, (void*) (regUTMI+0x0*2)); //tern_ov = 1
920     }
921     #endif
922 
923     /* move back to hub_events() */
924     // (USB_PORT_FEAT_C_CONNECTION)
925     //ms_usb_control_cmd(pHub, usb_sndctrlpipe(pHub, 0),
926     //    USB_REQ_CLEAR_FEATURE, USB_RT_PORT, USB_PORT_FEAT_C_CONNECTION, port+1, NULL, 0, HZ);
927 
928     if (pHub->children[port])
929         ms_usb_disconnect(&pHub->children[port]);
930 
931     if (!(portstatus & USB_PORT_STAT_CONNECTION))
932     {
933         if (portstatus & USB_PORT_STAT_ENABLE)
934             ms_hub_port_disable(pHub, port);
935         /* deal with HC abnormal state in fast plug in/out */
936         else if (pHub->parent == NULL) // limited at roothub
937             ms_roothub_disconn_reinit(pHcd);
938         return NULL;
939     }
940 
941     if (ms_hub_port_debounce(pHub, port))
942     {
943         ms_usbhost_err("connect-debounce failed, port %d disabled\n",
944             port+1);
945         ms_hub_port_disable(pHub, port);
946         return NULL;
947     }
948 
949     if (!pHub->parent)
950         u32Delay = HUB_ROOT_RESET_TIME;
951 
952     if (portstatus & USB_PORT_STAT_LOW_SPEED)
953         u32Delay = HUB_LONG_RESET_TIME;
954 
955   for (i = 0; i < HUB_PROBE_TRIES; i++) {
956     struct usb_device *pdev;
957     int  len;
958 
959     pUdev = ms_usb_alloc_dev(pHub, pHub->bus);
960     if (!pUdev) {
961       ms_usbhost_err("couldn't allocate usb_device\n");
962       break;
963     }
964 
965     pHub->children[port] = pUdev;
966     //pUdev->eState = USB_STATE_POWERED;
967     ms_usb_set_device_state(pUdev, USB_STATE_POWERED); // patch from Linux 2.6.28
968 
969     ms_usbhost_debug("pHcd->product_desc: (%s)\n", pHcd->product_desc);
970     if ( (pHub->parent == NULL) && (pHcd->isBadDevice) )
971     {
972         if (pHcd->badDeviceCnt == 3)
973             ms_RH_force_FSmode(pHcd, 1); //force enter FSmode
974     }
975     pHcd->isBadDevice = FALSE;
976 
977     if (pHub->parent == NULL && (pHcd->isBadDeviceRH == TRUE))
978     {
979         diag_printf("[USB] clear Bad Device on RH\n");
980         pHcd->isBadDeviceRH = FALSE;
981     }
982 
983     if (ms_hub_port_reset(pHub, port, pUdev, u32Delay)) {
984         ms_usb_put_dev(pUdev);
985         continue;
986     }
987 
988     // device unexpected disconnected checking
989     if (pHub->parent == NULL)
990     {
991         //struct ehci_hcd *ehci = hcd_to_ehci (pHcd);
992         //U32 temp = hcd_reg_readl((U32)&ehci->op_regs->portsc[0]);
993 
994         //if (!(temp & PORTSC_CONNECT))
995         if (!ms_RoothubPortConnected(pHcd))
996         {
997             diag_printf("[USB] no connect after bus reset\n");
998             ms_usb_put_dev(pUdev);
999             break;
1000         }
1001     }
1002 
1003     pUdev->level = pHub->level + 1;
1004 
1005     ms_usb_choose_address(pUdev);
1006 
1007     if (pHub->tt) {
1008       pUdev->tt = pHub->tt;
1009       pUdev->u32TTPort = pHub->u32TTPort;
1010     }
1011     else if (pUdev->eSpeed != USB_HIGH_SPEED
1012         /* MStar patch to setup roothub tt record */
1013         && (pHub->parent == NULL || pHub->eSpeed == USB_HIGH_SPEED)) {
1014         //&& pHub->eSpeed == USB_HIGH_SPEED) {
1015       pUdev->tt = &hubstate->tt;
1016       pUdev->u32TTPort = port + 1;
1017     }
1018 
1019     pdev = pUdev->parent;
1020     if (pdev->devpath [0] != '0')
1021       len = USB_sprintf (pUdev->devpath,"%s.%d", pdev->devpath, port + 1);
1022     else
1023       len = USB_sprintf (pUdev->devpath,"%d", port + 1);
1024     if (len == sizeof pUdev->devpath) {
1025       ms_usbhost_err("devpath size! usb/%03d/%03d path %s\n",
1026         (int)pUdev->bus->busnum, (int)pUdev->u32DevNum, pUdev->devpath);
1027     }
1028 
1029     ms_usbhost_msg("new USB device on path usb:%s, assigned address %d\n",
1030       pUdev->devpath, (int)pUdev->u32DevNum);
1031 
1032     pUdev->dev.parent = pUdev->parent->dev.parent->parent;
1033 
1034     if (!(sErr = ms_usb_new_device(pUdev, &pHub->dev)))
1035       goto done;
1036 
1037     ms_usbhost_msg("[HPCC] usb new device failed tier(%d)\n", i);
1038     ms_hub_port_disable(pHub, port); // patch from Linux code
1039 
1040     /* Clean qh buffer through urb list of udev */
1041     //ms_usb_disable_endpoint(pUdev, 0);
1042     ms_usb_disable_endpoint(pUdev, 0+USB_DIR_OUT);
1043     ms_usb_disable_endpoint(pUdev, 0+USB_DIR_IN);
1044     //phcd_dev = (struct s_hcd_dev *)pUdev->hcpriv;
1045     //ms_ehci_disable_ep(pHcd, phcd_dev, 0);
1046 
1047     ms_usb_put_dev(pUdev);
1048 
1049     if (sErr == -ESHUTDOWN || sErr == -ENODEV)
1050     {
1051         ms_usbhost_err("[HPCC] sErr %s!\n",
1052 		(sErr == -ENODEV) ? "ENODEV" : "ESHUTDOWN");
1053         break;
1054     }
1055     u32Delay = HUB_LONG_RESET_TIME; // increase hub reset period
1056   }
1057 
1058 
1059   diag_printf("HUB_PROBE_TRIES fail, #%d\n", i);
1060   if (i >= HUB_PROBE_TRIES && pHub->parent == NULL) // 3 reset retries
1061   {
1062     ms_usbhost_err("HUB PROBE fail, set bad device on root hub!\n");
1063     pHcd->isBadDeviceRH = TRUE;
1064   }
1065   pHub->children[port] = NULL;
1066   ms_hub_port_disable(pHub, port);
1067   pUdev = NULL;
1068 done:
1069   osapi_up(&usb_address0_sem);
1070   return pUdev;
1071 }
1072 
1073 static struct usb_device_id hub_id_table [] = {
1074     { USBDEV_MATCH_ID_DEV_CLASS,0,0,0,0,USB_CLASS_HUB,0,0,0,0,0,0},
1075     { USBDEV_MATCH_ID_INT_CLASS,0,0,0,0,0,0,0,USB_CLASS_HUB,0,0,0},
1076     { 0,0,0,0,0,0,0,0,0,0,0,0}
1077 
1078 };
1079 
1080 static struct usb_driver hub_driver = {
1081     "hub",
1082     ms_hub_probe,
1083     ms_hub_disconnect,
1084     hub_id_table
1085 };
1086 
1087 /**
1088      * @brief               hub driver installation
1089      *
1090      * @param           none
1091      *
1092      * @return          error code
1093      */
ms_usb_hub_init(void)1094 int ms_usb_hub_init(void)
1095 {
1096     if (ms_usb_register(&hub_driver) < 0)
1097     {
1098         ms_usbhost_err("Unable to register USB hub driver\n");
1099         return -1;
1100     }
1101     // Start up hub thread here (if platform has OS support)
1102 
1103     return 0;
1104 }
1105 
ms_usb_hub_uninit(void)1106 int ms_usb_hub_uninit(void)
1107 {
1108     ms_usb_deregister(&hub_driver);
1109     return 0;
1110 }
1111 /**
1112      * @brief               usb reset function
1113      *
1114      * @param           struct usb_device *ms_dev
1115      *
1116      * @return          error code
1117      */
ms_usb_physical_reset_device(struct usb_device * ms_dev)1118 int ms_usb_physical_reset_device(struct usb_device *ms_dev)
1119 {
1120     struct usb_device *parent = ms_dev->parent;
1121     struct usb_device_descriptor *d_desc;
1122     S32 i, s32Err, port = -1;
1123 
1124     if (!parent)
1125     {
1126         ms_usbhost_err("attempting to reset root hub!\n");
1127         return -EINVAL;
1128     }
1129 
1130     for (i = 0; i < parent->u32MaxChild; i++)
1131         if (parent->children[i] == ms_dev)
1132         {
1133             port = i;
1134             break;
1135         }
1136 
1137     if (port < 0)
1138         return -ENOENT;
1139 
1140     d_desc = (struct usb_device_descriptor*) kmalloc(sizeof *d_desc, GFP_NOIO);
1141     if (!d_desc)
1142     {
1143         ms_usbhost_err("[physical reset device] No available memory!\n");
1144         return -ENOMEM;
1145     }
1146 
1147     s32Err = ms_hub_port_reset(parent, port, ms_dev, HUB_SHORT_RESET_TIME);
1148     if (s32Err)
1149     {
1150         ms_usbhost_err("hub port[%d] reset fail, to disable the port (error=%d)\n", (int)port, (int)s32Err);
1151         ms_hub_port_disable(parent, port);
1152         kfree(d_desc);
1153         return -ENODEV;
1154     }
1155 
1156     diag_printf("Re-enumerating...\n");
1157     s32Err = ms_usb_set_address(ms_dev);
1158     if (s32Err < 0)
1159     {
1160         ms_usbhost_err("USB device not accepting new address (error=%d)\n", (int)s32Err);
1161         ms_hub_port_disable(parent, port);
1162         kfree(d_desc);
1163         /* prevent usb_port_reset to be submitted */
1164         if (s32Err == -ETIMEDOUT)
1165             s32Err = -ENODEV;
1166         return s32Err;
1167     }
1168 
1169     wait_ms(10);
1170 
1171     s32Err = ms_usb_get_descriptor(ms_dev, USB_DT_DEVICE, 0, d_desc, sizeof(*d_desc));
1172     if (s32Err < 0)
1173     {
1174         ms_usbhost_err("USB device not getting device descriptor (error=%d)\n", (int)s32Err);
1175         kfree(d_desc);
1176         return s32Err;
1177     }
1178 
1179     /* no need to do endien transform */
1180     //d_desc->bcdUSB = d_desc->bcdUSB;
1181     //d_desc->idVendor = d_desc->idVendor;
1182     //d_desc->idProduct = d_desc->idProduct;
1183     //d_desc->bcdDevice = d_desc->bcdDevice;
1184 
1185     /* this part is for re-enumeration, descriptor changed */
1186     if (memcmp(&ms_dev->descriptor, d_desc, sizeof(*d_desc)))
1187     {
1188         kfree(d_desc);
1189         ms_usb_destroy_config(ms_dev);
1190 
1191         s32Err = ms_usb_get_dev_descriptor(ms_dev);
1192         if ((U32) s32Err < sizeof(ms_dev->descriptor))
1193         {
1194             if (s32Err < 0)
1195             {
1196                 ms_usbhost_err("unable to get device %s descriptor (error=%d)\n",
1197                     ms_dev->devpath, (int)s32Err);
1198             }
1199             else
1200                 ms_usbhost_msg("USB device %s descriptor short read "
1201                     "(expected %i, got %i)\n",
1202                     ms_dev->devpath, sizeof(ms_dev->descriptor), (int)s32Err);
1203 
1204             //ms_clear_bit(ms_dev->u32DevNum, ms_dev->bus->devmap.usb_devicemap,U32);
1205             ms_devmap_clear_bit(ms_dev->u32DevNum, ms_dev->bus->devmap.usb_devicemap);
1206             ms_dev->u32DevNum = -1;
1207             return -EIO;
1208         }
1209 
1210         s32Err = ms_usb_get_config(ms_dev);
1211         if (s32Err < 0)
1212         {
1213             ms_usbhost_err("unable to get configuration (error=%d)\n", (int)s32Err);
1214             ms_usb_destroy_config(ms_dev);
1215             //ms_clear_bit(ms_dev->u32DevNum, ms_dev->bus->devmap.usb_devicemap,U32);
1216             ms_devmap_clear_bit(ms_dev->u32DevNum, ms_dev->bus->devmap.usb_devicemap);
1217             ms_dev->u32DevNum = -1;
1218             return 1;
1219         }
1220 
1221         //if(ms_dev->descriptor.bDeviceClass == USB_CLASS_COMM)
1222         //    ms_usb_set_config(ms_dev, ms_dev->config[1].desc.bConfigurationValue);
1223         //else
1224             ms_usb_set_config(ms_dev, ms_dev->config[0].desc.bConfigurationValue);
1225         return 1;
1226     }
1227 
1228     kfree(d_desc);
1229 
1230     s32Err = ms_usb_set_config(ms_dev, ms_dev->actconfig->desc.bConfigurationValue);
1231     diag_printf("usb_physical_reset_device done\n");
1232     return 0;
1233 }
1234 
1235 /**
1236      * @brief               usb reset function
1237      *
1238      * @param           struct usb_device *ms_dev
1239      *
1240      * @return          error code
1241      */
ms_usb_reset_device(struct usb_device * ms_dev)1242 int ms_usb_reset_device(struct usb_device *ms_dev)
1243 {
1244     int retval;
1245 
1246     ms_usbhost_debug("ms_usb_reset_device\n");
1247 
1248 	if (ms_dev->eState == USB_STATE_NOTATTACHED ||
1249 			ms_dev->eState == USB_STATE_SUSPENDED) {
1250 		ms_usbhost_err("device reset not allowed in state %d\n",
1251 				ms_dev->eState);
1252 		return -EINVAL;
1253 	}
1254 
1255     /* unbind interface */
1256 
1257     retval = ms_usb_physical_reset_device(ms_dev);
1258 
1259     /* rebind interface */
1260 
1261     return retval;
1262 }
1263 
1264 /**
1265      * @brief               hub events process
1266      *
1267      * @param           struct s_gVar4UsbPort *pRootHub
1268      *
1269      * @return          none
1270      */
ms_hub_events(struct s_gVar4UsbPort * pRootHub)1271 static int ms_hub_events(struct s_gVar4UsbPort *pRootHub)
1272 {
1273     U32 flags;
1274     struct list_head *tmp_list = &pRootHub->hub_event;
1275     struct list_head *list_t;
1276     struct usb_device *ms_dev;
1277     struct usb_hub *hub;
1278     U16 hubstatus;
1279     U16 hubchange;
1280     U16 u16Portstatus;
1281     U16 u16Portchange;
1282     S32 i, s32Err;
1283     S32 isHubConnEvent = 0;
1284 
1285     while (1)
1286     {
1287         osapi_spin_lock_irqsave(&hub_event_lock, flags);
1288         if (ms_is_empty_list(tmp_list))
1289         {
1290             osapi_spin_unlock_irqrestore(&hub_event_lock, flags);
1291             break;
1292         }
1293 
1294         list_t = tmp_list->next;
1295         hub = entry_to_container(list_t, struct usb_hub, event_list);
1296         ms_dev = interface_to_usbdev(hub->intf);
1297         ms_list_remove_and_init(list_t);
1298         osapi_spin_unlock_irqrestore(&hub_event_lock, flags);
1299 
1300         if (hub->error)
1301         {
1302             ms_usbhost_debug ("resetting for error %d\n", hub->error);
1303 
1304             if (ms_hub_reset(hub))
1305             {
1306                 ms_usbhost_err("can't reset; disconnecting\n");
1307                 ms_hub_start_disconnect(ms_dev);
1308                 continue;
1309             }
1310 
1311             hub->nerrors = 0;
1312             hub->error = 0;
1313         }
1314 
1315         ms_usbhost_debug("**EX** get hub event:%s at port %d\n",
1316                 ms_dev->devpath, pRootHub->hostid);
1317 
1318         if (ms_dev->parent == NULL)
1319             ms_usbhost_debug("<saved irq> portsc[0x%4x], usbcmd[%x]\n",
1320                 pRootHub->p_UsbHcd->saved_ehci_state.iPsc,
1321                 pRootHub->p_UsbHcd->saved_ehci_state.usbcmd);
1322 
1323         for (i = 0; i < hub->descriptor.bNbrPorts; i++)
1324         {
1325             int connect_change = 0;
1326 
1327             s32Err = ms_hub_port_status(ms_dev, i, &u16Portstatus, &u16Portchange);
1328             if ((ms_dev->parent == NULL) &&
1329                 (pRootHub->p_UsbHcd->saved_ehci_state.iPsc & 0x2) &&
1330                 ((u16Portchange & USB_PORT_STAT_C_CONNECTION)==0) &&
1331                 ((u16Portstatus & USB_PORT_STAT_CONNECTION)==0))
1332             {
1333                 diag_printf("current u16Portchange [0x%4x], u16Portstatus [0x%4x] s32Err %d\n", u16Portchange, u16Portstatus, s32Err);
1334                 u16Portchange |= USB_PORT_STAT_C_CONNECTION;
1335             }
1336             if (s32Err < 0)
1337             {
1338                 continue;
1339             }
1340             if (u16Portchange & USB_PORT_STAT_C_CONNECTION)
1341             {
1342                 // (USB_PORT_FEAT_C_CONNECTION)
1343                 ms_usb_control_cmd(ms_dev, usb_sndctrlpipe(ms_dev, 0),
1344                     USB_REQ_CLEAR_FEATURE, USB_RT_PORT, USB_PORT_FEAT_C_CONNECTION, i + 1, NULL, 0, HZ);
1345                 connect_change = 1;
1346             }
1347             if (u16Portchange & USB_PORT_STAT_C_ENABLE)
1348             {
1349                 ms_usbhost_debug ("port %d enable change, status %x\n", i + 1, u16Portstatus);
1350                 // (USB_PORT_FEAT_C_ENABLE)
1351                 ms_usb_control_cmd(ms_dev, usb_sndctrlpipe(ms_dev, 0),
1352                     USB_REQ_CLEAR_FEATURE, USB_RT_PORT, USB_PORT_FEAT_C_ENABLE, i + 1, NULL, 0, HZ);
1353 
1354                 if (!(u16Portstatus & USB_PORT_STAT_ENABLE)
1355                     && (u16Portstatus & USB_PORT_STAT_CONNECTION)
1356                     && (ms_dev->children[i]))
1357                 {
1358                     ms_usbhost_err("port %d disabled by hub (EMI?), re-enabling...\n", (int)i + 1);
1359                     connect_change = 1;
1360                 }
1361             }
1362 
1363             if (u16Portchange & USB_PORT_STAT_C_SUSPEND)
1364             {
1365                 ms_usbhost_debug ("suspend change on port %d\n", i + 1);
1366                 // (USB_PORT_FEAT_C_SUSPEND)
1367                 ms_usb_control_cmd(ms_dev, usb_sndctrlpipe(ms_dev, 0),
1368                     USB_REQ_CLEAR_FEATURE, USB_RT_PORT, USB_PORT_FEAT_C_SUSPEND, i + 1, NULL, 0, HZ);
1369             }
1370 
1371             if (u16Portchange & USB_PORT_STAT_C_OVERCURRENT)
1372             {
1373                 ms_usbhost_err("over-current change on port %d\n", (int)i + 1);
1374                 // (USB_PORT_FEAT_C_OVER_CURRENT)
1375                 ms_usb_control_cmd(ms_dev, usb_sndctrlpipe(ms_dev, 0),
1376                     USB_REQ_CLEAR_FEATURE, USB_RT_PORT, USB_PORT_FEAT_C_OVER_CURRENT, i + 1, NULL, 0, HZ);
1377                 ms_hub_power_on(hub);
1378             }
1379 
1380             if (u16Portchange & USB_PORT_STAT_C_RESET)
1381             {
1382                 ms_usbhost_debug ("reset change on port %d\n", i + 1);
1383                 // (USB_PORT_FEAT_C_RESET)
1384                 ms_usb_control_cmd(ms_dev, usb_sndctrlpipe(ms_dev, 0),
1385                     USB_REQ_CLEAR_FEATURE, USB_RT_PORT, USB_PORT_FEAT_C_RESET, i + 1, NULL, 0, HZ);
1386             }
1387             if (connect_change) {
1388                 struct usb_device *pUdev;
1389 
1390                 pUdev = ms_hub_port_connect_change(hub, i, u16Portstatus, u16Portchange);
1391                 if ((pUdev != NULL) && (u16Portstatus & USB_PORT_STAT_CONNECTION))
1392                 {
1393                     pRootHub->arConnDev[isHubConnEvent].connDev = pUdev;
1394                     isHubConnEvent++;
1395                     USB_ASSERT(isHubConnEvent<USB_MAXCHILDREN, "exceed the size of arConnDev!!!!\n");
1396                 }
1397             }
1398         } /* end for i */
1399 
1400         if (ms_hub_hub_status(hub, &hubstatus, &hubchange) < 0)
1401         {
1402             ms_usbhost_err("get_hub_status failed\n");
1403         }
1404         else
1405         {
1406             if (hubchange & HUB_CHANGE_LOCAL_POWER)
1407             {
1408                 ms_usbhost_debug ("power change\n");
1409                 // (C_HUB_LOCAL_POWER)
1410                 ms_usb_control_cmd(ms_dev, usb_sndctrlpipe(ms_dev, 0),
1411                     USB_REQ_CLEAR_FEATURE, USB_RT_HUB, C_HUB_LOCAL_POWER, 0, NULL, 0, HZ);
1412             }
1413 
1414             if (hubchange & HUB_CHANGE_OVERCURRENT)
1415             {
1416                 ms_usbhost_debug ("overcurrent change\n");
1417                 // (C_HUB_OVER_CURRENT)
1418                 ms_usb_control_cmd(ms_dev, usb_sndctrlpipe(ms_dev, 0),
1419                     USB_REQ_CLEAR_FEATURE, USB_RT_HUB, C_HUB_OVER_CURRENT, 0, NULL, 0, HZ);
1420                 wait_ms(500); // to be cool down
1421                 ms_hub_power_on(hub);
1422             }
1423         }
1424     } /* end while (1) */
1425 
1426     return (isHubConnEvent);
1427 }
1428 
1429 #ifdef USB_EHCI_TT
1430 static void ms_hub_tt_kevent(struct s_gVar4UsbPort *);
1431 #endif
1432 /**
1433      * @brief               hub event polling from UsbTask
1434      *
1435      * @param           struct s_gVar4UsbPort *pRootHub
1436      *
1437      * @return          # of device connected
1438      */
ms_hub_poll(struct s_gVar4UsbPort * pRootHub)1439 int ms_hub_poll(struct s_gVar4UsbPort *pRootHub)
1440 {
1441     S32 isHubConnected = 0;
1442     struct list_head *tmp_list = &pRootHub->hub_event;
1443 
1444     if (ms_is_empty_list(tmp_list))
1445         return 0;
1446 
1447     ms_USBCriticalSectionIn(pRootHub->hostid);
1448     isHubConnected = ms_hub_events(pRootHub);
1449 #ifdef USB_EHCI_TT
1450     ms_hub_tt_kevent(pRootHub);
1451 #endif
1452     ms_USBCriticalSectionOut(pRootHub->hostid);
1453     return (isHubConnected);
1454 }
1455 
1456 #ifdef USB_EHCI_TT
1457 /**
1458      * @brief           high speed hub tt buffer clear
1459      *
1460      * @param           struct usb_device *ms_dev
1461      * @param           int ms_pipe
1462      *
1463      * @return          none
1464      */
ms_usb_hub_tt_clear_buffer(struct usb_device * ms_dev,int ms_pipe)1465 void ms_usb_hub_tt_clear_buffer (struct usb_device *ms_dev, int ms_pipe)
1466 {
1467     struct usb_tt    *utt = ms_dev->tt;
1468     U32    flags;
1469     struct usb_tt_clear  *ms_clear;
1470     struct usb_hcd *hcd = (struct usb_hcd*) ms_dev->bus->hcpriv;
1471 
1472     diag_printf("%s++\n",__FUNCTION__);
1473     if ((ms_clear = kmalloc (sizeof *ms_clear, GFP_ATOMIC)) == 0)
1474     {
1475         ms_usbhost_err("can't allocate CLEAR_TT_BUFFER state for hub at usb-%s-%s\n",
1476             ms_dev->bus->bus_name, utt->hub->devpath);
1477         return;
1478     }
1479 
1480     ms_clear->tt = utt->multi ? ms_dev->u32TTPort : 1;
1481     ms_clear->devinfo = usb_pipeendpoint (ms_pipe);
1482     ms_clear->devinfo |= ms_dev->u32DevNum << 4;
1483     ms_clear->devinfo |= usb_pipecontrol (ms_pipe)
1484         ? (USB_ENDPOINT_XFER_CONTROL << 11)
1485         : (USB_ENDPOINT_XFER_BULK << 11);
1486     if (usb_pipein (ms_pipe))
1487         ms_clear->devinfo |= 1 << 15;
1488 
1489     osapi_spin_lock_irqsave (&utt->lock, flags);
1490     ms_insert_list_before (&ms_clear->clear_list, &utt->clear_list);
1491     //schedule_work (&utt->kevent);
1492     ms_insert_list_after(&utt->clear_list, &hcd->tt_clear_list); // new, link to the right hcd
1493     osapi_spin_unlock_irqrestore (&utt->lock, flags);
1494 }
1495 
ms_hub_tt_kevent(struct s_gVar4UsbPort * pRootHub)1496 static void ms_hub_tt_kevent(struct s_gVar4UsbPort *pRootHub)
1497 {
1498 	struct list_head	*tmp_list = &pRootHub->p_UsbHcd->tt_clear_list;
1499 	struct list_head	*list_t;
1500 	struct usb_hub		*hub;
1501 	unsigned long		flags;
1502 	int			limit = 100;
1503 
1504 	osapi_spin_lock_irqsave (&hub->tt.lock, flags);
1505 	if (ms_is_empty_list(tmp_list)) {
1506 		osapi_spin_unlock_irqrestore (&hub->tt.lock, flags);
1507 		return;
1508 	}
1509 	list_t = tmp_list->next;
1510 	hub = entry_to_container(list_t, struct usb_hub, event_list);
1511 	while (--limit && !list_empty (&hub->tt.clear_list)) {
1512 		struct list_head	*temp;
1513 		struct usb_tt_clear	*clear;
1514 		struct usb_device	*hdev = interface_to_usbdev(hub->intf);
1515 		int			status;
1516 
1517 		temp = hub->tt.clear_list.next;
1518 		clear = list_entry (temp, struct usb_tt_clear, clear_list);
1519 		list_del (&clear->clear_list);
1520 
1521 		/* drop lock so HCD can concurrently report other TT errors */
1522 		osapi_spin_unlock_irqrestore (&hub->tt.lock, flags);
1523 		/* hub_clear_tt_buffer */
1524 		status = ms_usb_control_cmd(hdev, usb_rcvctrlpipe(hdev, 0),
1525 			       HUB_CLEAR_TT_BUFFER, USB_RT_PORT, clear->devinfo,
1526 			       clear->tt, NULL, 0, 1000);
1527 		osapi_spin_lock_irqsave (&hub->tt.lock, flags);
1528 
1529 		if (status)
1530 			ms_usbhost_err ("clear tt %d (%04x) error %d\n",
1531 				clear->tt, clear->devinfo, status);
1532 		kfree(clear);
1533 	}
1534 	osapi_spin_unlock_irqrestore (&hub->tt.lock, flags);
1535 }
1536 
1537 #endif
1538 
1539