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