M4521_BSP V3.02.000
The Board Support Package for M4521
usbh_hub.c
Go to the documentation of this file.
1/*
2 * USB hub driver.
3 *
4 * (C) Copyright 1999 Linus Torvalds
5 * (C) Copyright 1999 Johannes Erdfelt
6 * (C) Copyright 1999 Gregory P. Smith
7 * (C) Copyright 2001 Brad Hards (bhards@bigpond.net.au)
8 *
9 */
10
11/**************************************************************************/
22#include <stdio.h>
23#include <string.h>
24
25#include "M4521.h"
26#include "usbh_core.h"
27#include "usbh_hub.h"
28
29
47
48static LIST_HEAD(_HubEventList); /* List of hubs needing servicing */
49
50static int usb_hub_events(void);
51
52extern USB_HUB_T * usbh_get_hub_by_dev(USB_DEV_T *dev);
53
54static int usb_get_hub_descriptor(USB_DEV_T *dev, void *data, int size)
55{
56 return USBH_SendCtrlMsg(dev, usb_rcvctrlpipe(dev, 0),
57 USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB,
58 USB_DT_HUB << 8, 0, data, size, HZ);
59}
60
61
62static int usb_clear_hub_feature(USB_DEV_T *dev, int feature)
63{
64 return USBH_SendCtrlMsg(dev, usb_sndctrlpipe(dev, 0),
65 USB_REQ_CLEAR_FEATURE, USB_RT_HUB, feature, 0, NULL, 0, HZ);
66}
67
68
69static int usb_clear_port_feature(USB_DEV_T *dev, int port, int feature)
70{
71 return USBH_SendCtrlMsg(dev, usb_sndctrlpipe(dev, 0),
72 USB_REQ_CLEAR_FEATURE, USB_RT_PORT, feature, port, NULL, 0, HZ);
73}
74
75
76static int usb_set_port_feature(USB_DEV_T *dev, int port, int feature)
77{
78 USB_info("usb_set_port_feature, port:%d of hub:%d\n", port, dev->devnum);
79 return USBH_SendCtrlMsg(dev, usb_sndctrlpipe(dev, 0),
80 USB_REQ_SET_FEATURE, USB_RT_PORT, feature, port, NULL, 0, HZ);
81}
82
83
84static int usb_get_hub_status(USB_DEV_T *dev, void *data)
85{
86 int status;
87 uint32_t stack_buff[8];
88
89 status = USBH_SendCtrlMsg(dev, usb_rcvctrlpipe(dev, 0),
90 USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_HUB, 0, 0,
91 (void *)&stack_buff[0], sizeof(USB_HUB_STATUS_T), HZ * 3);
92 memcpy((uint8_t *)data, (uint8_t *)&stack_buff[0], sizeof(USB_HUB_STATUS_T));
93 return status;
94}
95
96
97static int usb_get_port_status(USB_DEV_T *dev, int port, void *data)
98{
99 int status;
100 uint32_t stack_buff[8];
101
102 status = USBH_SendCtrlMsg(dev, usb_rcvctrlpipe(dev, 0),
103 USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, 0, port,
104 (void *)&stack_buff[0], sizeof(USB_PORT_STATUS_T), HZ * 5);
105 memcpy((uint8_t *)data, (uint8_t *)&stack_buff[0], sizeof(USB_PORT_STATUS_T));
106 return status;
107}
108
110
118{
119 ohci_int_timer_do(0);
120 return usb_hub_events();
121}
122
124/*
125 * hub int-in complete function
126 */
127static void hub_irq(URB_T *urb)
128{
129 USB_HUB_T *hub = (USB_HUB_T *)urb->context;
130
131 //USB_debug("hub_irq!!\n");
132
133 /* Cause a hub reset after 10 consecutive errors */
134 if(urb->status)
135 {
136 if(urb->status == USB_ERR_NOENT)
137 return;
138 USB_warning("nonzero status in irq %d\n", urb->status);
139 if((++hub->nerrors < 10) || hub->error)
140 return;
141 hub->error = urb->status;
142 }
143 hub->nerrors = 0;
144
145 /* Something happened, let khubd figure it out */
146
147 /* Add the hub to the event queue */
148 if(list_empty(&hub->event_list))
149 {
150 list_add(&hub->event_list, &_HubEventList);
151 }
152}
153
154
155static void usb_hub_power_on(USB_HUB_T *hub)
156{
157 int i;
158
159 /* Enable power to the ports */
160 for(i = 0; i < hub->descriptor.bNbrPorts; i++)
161 {
162 USB_info("enable port:%d of hub:%d\n", i + 1, hub->dev->devnum);
163 usb_set_port_feature(hub->dev, i + 1, USB_PORT_FEAT_POWER);
164 }
165
166 /* Wait for power to be enabled */
167 usbh_mdelay(hub->descriptor.bPwrOn2PwrGood * 2);
168}
169
170
171static int usb_hub_configure(USB_HUB_T *hub, EP_INFO_T *ep_info)
172{
173 USB_DEV_T *dev = hub->dev;
174 USB_HUB_STATUS_T hubstatus;
175 uint32_t pipe;
176 int maxp, ret;
177
178 USB_info("[HUB] Enter usb_hub_configure()... hub:%d\n", hub->dev->devnum);
179
180 /* Request the entire hub descriptor. */
181 ret = usb_get_hub_descriptor(dev, &hub->descriptor, sizeof(USB_HUB_DESC_T));
182
183 /* <hub->descriptor> is large enough for a hub with 127 ports;
184 * the hub can/will return fewer bytes here. */
185 if(ret < 0)
186 {
187 USB_error("Erro - Unable to get hub descriptor (err = %d)\n", ret);
188 return ret;
189 }
190
191 dev->maxchild = hub->descriptor.bNbrPorts;
192
193#ifdef USB_VERBOSE_DEBUG
194 USB_info("%d port%s detected\n", hub->descriptor.bNbrPorts, (hub->descriptor.bNbrPorts == 1) ? "" : "s");
195
196 /* D2: Identifying a Compound Device */
197 if(hub->descriptor.wHubCharacteristics & HUB_CHAR_COMPOUND)
198 {
199 USB_info("part of a compound device\n");
200 }
201 else
202 {
203 USB_info("standalone hub\n");
204 }
205
206 /* D1..D0: Logical Power Switching Mode */
207 switch(hub->descriptor.wHubCharacteristics & HUB_CHAR_LPSM)
208 {
209 case 0x00:
210 USB_info("ganged power switching\n");
211 break;
212 case 0x01:
213 USB_info("individual port power switching\n");
214 break;
215 case 0x02:
216 case 0x03:
217 USB_info("unknown reserved power switching mode\n");
218 break;
219 }
220
221 /* D4..D3: Over-current Protection Mode */
222 switch(hub->descriptor.wHubCharacteristics & HUB_CHAR_OCPM)
223 {
224 case 0x00:
225 USB_info("global over-current protection\n");
226 break;
227 case 0x08:
228 USB_info("individual port over-current protection\n");
229 break;
230 case 0x10:
231 case 0x18:
232 USB_info("no over-current protection\n");
233 break;
234 }
235
236 switch(dev->descriptor.bDeviceProtocol)
237 {
238 case 0:
239 break;
240 case 1:
241 USB_debug("Single TT, ");
242 break;
243 case 2:
244 USB_debug("TT per port, ");
245 break;
246 default:
247 USB_debug("Unrecognized hub protocol %d", dev->descriptor.bDeviceProtocol);
248 break;
249 }
250
251 USB_info("power on to power good time: %dms\n", hub->descriptor.bPwrOn2PwrGood * 2);
252 USB_info("hub controller current requirement: %dmA\n", hub->descriptor.bHubContrCurrent);
253#endif
254
255 ret = usb_get_hub_status(dev, &hubstatus);
256 if(ret < 0)
257 {
258 USB_error("Unable to get hub %d status (err = %d)\n", hub->dev->devnum, ret);
259 return ret;
260 }
261
262 hubstatus.wHubStatus = USB_SWAP16(hubstatus.wHubStatus);
263
264#ifdef USB_VERBOSE_DEBUG
265 /* Hub status bit 0, Local Power Source */
266 if(hubstatus.wHubStatus & HUB_STATUS_LOCAL_POWER)
267 {
268 USB_info("local power source is lost (inactive)\n");
269 }
270 else
271 {
272 USB_info("local power source is good\n");
273 }
274
275 /* Hub status bit 1, Over-current Indicator */
276 if(hubstatus.wHubStatus & HUB_STATUS_OVERCURRENT)
277 {
278 USB_info("!! over-current\n");
279 }
280 else
281 {
282 USB_info("No over-current.\n");
283 }
284#endif
285
286 /* Start the interrupt endpoint */
287 pipe = usb_rcvintpipe(dev, ep_info->bEndpointAddress);
288 maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
289
290 if(maxp > sizeof(hub->buffer))
291 maxp = sizeof(hub->buffer);
292
293 hub->urb = USBH_AllocUrb();
294 if(!hub->urb)
295 {
296 USB_error("Error - couldn't allocate interrupt urb");
297 return USB_ERR_NOMEM;
298 }
299
300#if 1 /* YCHuang 2012.06.01 */
301 if(ep_info->bInterval < 16)
302 ep_info->bInterval = 16;
303#endif
304 FILL_INT_URB(hub->urb, dev, pipe, hub->buffer, maxp, hub_irq,
305 hub, ep_info->bInterval);
306 ret = USBH_SubmitUrb(hub->urb);
307 if(ret)
308 {
309 USB_error("Error - USBH_SubmitUrb failed (%d)", ret);
310 USBH_FreeUrb(hub->urb);
311 return ret;
312 }
313
314 if(g_ohci_bus.root_hub != hub->dev)
315 usb_hub_power_on(hub);
316 return 0;
317}
318
319
320static int hub_probe(USB_DEV_T *dev, USB_IF_DESC_T *ifd, const USB_DEV_ID_T *id)
321{
322 EP_INFO_T *ep_info;
323 USB_HUB_T *hub;
324 int ifnum;
325 int i;
326
327 USB_debug("hub_probe - dev=0x%x\n", (int)dev);
328
329 ifnum = ifd->bInterfaceNumber;
330
331 if(dev->descriptor.bDeviceClass != 0x09)
332 return USB_ERR_NODEV;
333
334 ep_info = NULL;
335 for(i = 0; i < dev->ep_list_cnt; i++)
336 {
337 if((dev->ep_list[i].ifnum == ifnum) &&
338 ((dev->ep_list[i].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT))
339 {
340 ep_info = &dev->ep_list[i];
341 break;
342 }
343 }
344 if(ep_info == NULL)
345 {
346 USB_error("hub int ep not found!\n");
347 return USB_ERR_NODEV;
348 }
349
350 /* Output endpoint? Curiousier and curiousier.. */
351 if(!(ep_info->bEndpointAddress & USB_DIR_IN))
352 {
353 USB_error("Error - Device #%d is hub class, but has output endpoint?\n", dev->devnum);
354 return USB_ERR_NODEV;
355 }
356
357 /* If it's not an interrupt endpoint, we'd better punt! */
358 if((ep_info->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
359 {
360 USB_error("Error - Device #%d is hub class, but has endpoint other than interrupt?\n", dev->devnum);
361 return USB_ERR_NODEV;
362 }
363
364 /* We found a hub */
365 USB_debug("USB hub found\n");
366
367 hub = usbh_alloc_hubdev();
368 if(!hub)
369 return USB_ERR_NOMEM;
370
371 INIT_LIST_HEAD(&hub->event_list);
372 hub->dev = dev;
373
374 if(usb_hub_configure(hub, ep_info) == 0)
375 return 0;
376
377 USB_error("Error - hub configuration failed for device #%d\n", dev->devnum);
378
379 /* Delete it and then reset it */
380 list_del(&hub->event_list);
381 INIT_LIST_HEAD(&hub->event_list);
382
383 usbh_free_hubdev(hub);
384 return USB_ERR_NODEV;
385}
386
387
388static void hub_disconnect(USB_DEV_T *dev)
389{
390 USB_HUB_T *hub;
391
392 hub = usbh_get_hub_by_dev(dev);
393
394 if(hub == NULL)
395 {
396 USB_warning("hub_disconnect - hub device not found!\n");
397 return;
398 }
399
400 /* Delete it and then reset it */
401 list_del(&hub->event_list);
402 INIT_LIST_HEAD(&hub->event_list);
403
404 if(hub->urb)
405 {
406 USBH_UnlinkUrb(hub->urb);
407 USBH_FreeUrb(hub->urb);
408 hub->urb = NULL;
409 }
410 usbh_free_hubdev(hub);
411}
412
413
414#define HUB_RESET_TRIES 2
415#define HUB_PROBE_TRIES 3
416#define HUB_SHORT_RESET_TIME 150
417#define HUB_LONG_RESET_TIME 500
418#define HUB_RESET_TIMEOUT 3000
420static int usb_hub_port_wait_reset(USB_DEV_T *hub, int port,
421 USB_DEV_T *dev, uint32_t delay)
422{
423 int delay_time, ret;
424 uint16_t portchange, portstatus;
425 USB_PORT_STATUS_T portsts;
426
427 for(delay_time = 0; delay_time < HUB_RESET_TIMEOUT; delay_time += delay)
428 {
429 /* wait to give the device a chance to reset */
430 usbh_mdelay(delay);
431
432 /* read and decode port status */
433 ret = usb_get_port_status(hub, port + 1, &portsts);
434 if(ret < 0)
435 {
436 USB_error("Error - get_port_status(%d) failed (err = %d)\n", port + 1, ret);
437 return -1;
438 }
439
440 portstatus = portsts.wPortStatus;
441 portchange = portsts.wPortChange;
442
443 USB_info("port %d of hub %d, portstatus %x, change %x, %s\n", port + 1, hub->devnum,
444 portstatus, portchange,
445 portstatus & (1 << USB_PORT_FEAT_LOWSPEED) ? "1.5 Mb/s" : "12 Mb/s");
446
447 if((portchange & USB_PORT_STAT_C_CONNECTION) ||
448 !(portstatus & USB_PORT_STAT_CONNECTION))
449 return -1;
450
451 /* if we have finished resetting, then break out of the loop */
452 if(!(portstatus & USB_PORT_STAT_RESET) &&
453 (portstatus & USB_PORT_STAT_ENABLE))
454 {
455 if(portstatus & USB_PORT_STAT_HIGH_SPEED)
456 {
457 USB_debug("Device is high speed!\n");
458 dev->speed = USB_SPEED_HIGH;
459 }
460 else if(portstatus & USB_PORT_STAT_LOW_SPEED)
461 {
462 USB_debug("Device is low speed!\n");
463 dev->speed = USB_SPEED_LOW;
464 }
465 else
466 {
467 USB_debug("Device is full speed!\n");
468 dev->speed = USB_SPEED_FULL;
469 }
470
471 dev->slow = (portstatus & USB_PORT_STAT_LOW_SPEED) ? 1 : 0;
472 return 0;
473 }
474
475 /* switch to the long delay after two short delay failures */
476 if(delay_time >= 2 * HUB_SHORT_RESET_TIME)
477 delay = HUB_LONG_RESET_TIME;
478
479 USB_info("port %d of hub %d not reset yet, waiting %dms\n", port + 1, hub->devnum, delay);
480 }
481 return -1;
482}
483
484
485static int usb_hub_port_reset(USB_DEV_T *hub, int port,
486 USB_DEV_T *dev, uint32_t delay)
487{
488 int i;
489
490 USB_info("usb_hub_port_reset: hub:%d, port:%d dev:%x\n", hub->devnum, port + 1, (int)dev);
491
492 /* Reset the port */
493 for(i = 0; i < HUB_RESET_TRIES; i++) /* retry loop */
494 {
495 usb_set_port_feature(hub, port + 1, USB_PORT_FEAT_RESET);
496 /* return success if the port reset OK */
497 if(!usb_hub_port_wait_reset(hub, port, dev, delay))
498 {
499 usb_clear_port_feature(hub, port + 1, USB_PORT_FEAT_C_RESET);
500 return 0;
501 }
502
503 USB_error("port %d of hub %d not enabled, %dth trying reset again...\n", port + 1, hub->devnum, i);
504 delay = HUB_LONG_RESET_TIME;
505 }
506
507 USB_error("Cannot enable port %i of hub %d, disabling port.\n", port + 1, hub->devnum);
508 USB_error("Error - Maybe the USB cable is bad?\n");
509 return -1;
510}
511
512
513void usb_hub_port_disable(USB_DEV_T *hub, int port)
514{
515 int ret;
516
517 ret = usb_clear_port_feature(hub, port + 1, USB_PORT_FEAT_ENABLE);
518 if(ret)
519 USB_error("cannot disable port %d of hub %d (err = %d)\n",
520 port + 1, hub->devnum, ret);
521}
522
523
524static void usb_hub_port_connect_change(USB_HUB_T *hubstate, USB_DEV_T *hub, int port,
525 USB_PORT_STATUS_T *portsts)
526{
527 USB_DEV_T *dev;
528 uint16_t portstatus; // portchange;
529 uint32_t delay = HUB_SHORT_RESET_TIME;
530 int i;
531
532 portstatus = portsts->wPortStatus;
533 //portchange = portsts->wPortChange;
534
535 //USB_info("usb_hub_port_connect_change - port %d, portstatus %x, change %x, %s\n", port + 1, portstatus,
536 // portchange, portstatus & (1 << USB_PORT_FEAT_LOWSPEED) ? "1.5 Mb/s" : "12 Mb/s");
537
538 /* Clear the connection change status */
539 usb_clear_port_feature(hub, port + 1, USB_PORT_FEAT_C_CONNECTION);
540
541 /* Disconnect any existing devices under this port */
542 if(hub->children[port])
543 usbh_disconnect_device(&hub->children[port]);
544
545 /* Return now if nothing is connected */
546 if(!(portstatus & USB_PORT_STAT_CONNECTION))
547 {
548 if(portstatus & USB_PORT_STAT_ENABLE)
549 usb_hub_port_disable(hub, port);
550 return;
551 }
552
553 if(portstatus & USB_PORT_STAT_LOW_SPEED)
554 {
555 usbh_mdelay(400);
556 delay = HUB_LONG_RESET_TIME;
557 }
558
559 for(i = 0; i < HUB_PROBE_TRIES; i++)
560 {
561 /* Allocate a new device struct */
562 dev = usbh_alloc_device(hub, hub->bus);
563 if(!dev)
564 {
565 USB_error("Error - couldn't allocate usb_device\n");
566 break;
567 }
568 dev->hub_port = port;
569 hub->children[port] = dev;
570
571 if(usb_hub_port_reset(hub, port, dev, delay))
572 {
573 usbh_free_device(dev);
574 break;
575 }
576
577 /* Find a new device ID for it */
578 usbh_connect_device(dev);
579
580 USB_debug("USB new device connect, assigned device number %d\n", dev->devnum);
581
582 /* Run it through the hoops (find a driver, etc) */
583 if(usbh_settle_new_device(dev) == 0)
584 return; // OK.
585
586 /* Free the configuration if there was an error */
587 usbh_free_device(dev);
588
589 /* Switch to a long reset time */
590 delay = HUB_LONG_RESET_TIME;
591 }
592
593 hub->children[port] = NULL;
594 usb_hub_port_disable(hub, port);
595}
596
597
598int usb_hub_events(void)
599{
600 USB_LIST_T *tmp;
601 USB_DEV_T *dev;
602 USB_HUB_T *hub;
603 USB_HUB_STATUS_T hubsts;
604 uint16_t hubchange;
605 uint16_t irq_data;
606 int i, ret;
607
608 if(list_empty(&_HubEventList))
609 return 0;
610
611 /*
612 * We restart the list everytime to avoid a deadlock with
613 * deleting hubs downstream from this one. This should be
614 * safe since we delete the hub from the event list.
615 * Not the most efficient, but avoids deadlocks.
616 */
617 while(1)
618 {
619 if(list_empty(&_HubEventList))
620 break;
621
622 /* Grab the next entry from the beginning of the list */
623 tmp = _HubEventList.next;
624
625 hub = list_entry(tmp, USB_HUB_T, event_list);
626 dev = hub->dev;
627
628 list_del(tmp);
629 INIT_LIST_HEAD(tmp);
630
631 if(hub->error)
632 {
633 USB_error("hub error %d!!\n", hub->error);
634 }
635
636 /* added by YCHuang */
637 if(hub->urb->transfer_buffer_length == 1)
638 irq_data = *(uint8_t *)hub->urb->transfer_buffer;
639 else
640 {
641 /* BIGBIG */
642 //irq_data = *(uint16_t *)hub->urb->transfer_buffer; /* FIX DEBUG, not verified */
643 irq_data = (*((uint8_t *)hub->urb->transfer_buffer + 1) << 8) |
644 *(uint8_t *)hub->urb->transfer_buffer;
645 }
646
647 for(i = 0; i < hub->descriptor.bNbrPorts; i++)
648 {
649 USB_PORT_STATUS_T portsts;
650 uint16_t portstatus, portchange;
651
652 if(!((irq_data >> (i + 1)) & 0x01))
653 continue;
654
655 USB_info("usb_hub_events - hub:%d, get port status...\n", hub->dev->devnum);
656 ret = usb_get_port_status(dev, i + 1, &portsts);
657 if(ret < 0)
658 {
659 USB_error("Error - get_hub %d port %d status failed (err = %d)\n", hub->dev->devnum, i + 1, ret);
660 continue;
661 }
662
663 portstatus = portsts.wPortStatus;
664 portchange = portsts.wPortChange;
665 USB_debug("portstatus = %x, portchange = %x\n", portstatus, portchange);
666
667 if(portchange & USB_PORT_STAT_C_CONNECTION)
668 {
669 USB_info("port %d of hub %d connection change\n", i + 1, hub->dev->devnum);
670 usb_hub_port_connect_change(hub, dev, i, &portsts);
671 }
672 else if(portchange & USB_PORT_STAT_C_ENABLE)
673 {
674 USB_info("port %d of hub %d enable change, status %x\n", i + 1, portstatus, hub->dev->devnum);
675 usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_ENABLE);
676
677 /*
678 * EM interference sometimes causes bad shielded USB
679 * devices to be shutdown by the hub, this hack enables
680 * them again. Works at least with mouse driver.
681 */
682 if(!(portstatus & USB_PORT_STAT_ENABLE) &&
683 (portstatus & USB_PORT_STAT_CONNECTION) &&
684 (dev->children[i]))
685 {
686 USB_error("Error - already running port %i disabled by hub (EMI?), re-enabling...\n", i + 1);
687 usb_hub_port_connect_change(hub, dev, i, &portsts);
688 }
689 }
690
691 if(portchange & USB_PORT_STAT_C_SUSPEND)
692 {
693 USB_info("port %d of hub %d suspend change\n", i + 1, hub->dev->devnum);
694 usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_SUSPEND);
695 }
696
697 if(portchange & USB_PORT_STAT_C_OVERCURRENT)
698 {
699 USB_warning("!! port %d of hub %d over-current change\n", i + 1, hub->dev->devnum);
700 usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_OVER_CURRENT);
701 usb_hub_power_on(hub);
702 }
703
704 if(portchange & USB_PORT_STAT_C_RESET)
705 {
706 USB_info("port %d of hub %d reset change\n", i + 1, hub->dev->devnum);
707 usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_RESET);
708 }
709 } /* end for i */
710
711 /* deal with hub status changes */
712 if(usb_get_hub_status(dev, &hubsts) < 0)
713 USB_error("Error - get_hub_status failed\n");
714 else
715 {
716 //hubstatus = USB_SWAP16(hubsts.wHubStatus);
717 hubchange = USB_SWAP16(hubsts.wHubChange);
718 if(hubchange & HUB_CHANGE_LOCAL_POWER)
719 {
720 USB_debug("hub power change\n");
721 usb_clear_hub_feature(dev, C_HUB_LOCAL_POWER);
722 }
723 if(hubchange & HUB_CHANGE_OVERCURRENT)
724 {
725 USB_error("!!hub overcurrent change\n");
726 usbh_mdelay(500); /* Cool down */
727 usb_clear_hub_feature(dev, C_HUB_OVER_CURRENT);
728 usb_hub_power_on(hub);
729 }
730 }
731
732 } /* end while (1) */
733
734 return 1;
735}
736
737
738static USB_DEV_ID_T hub_id_table[] =
739{
740 USB_DEVICE_ID_MATCH_INT_CLASS, /* match_flags */
741 0, 0, 0, 0, 0, 0, 0,
742 USB_CLASS_HUB, /* bInterfaceClass */
743 0, 0, 0
744};
745
746
747static USB_DRIVER_T hub_driver =
748{
749 "hub driver",
750 hub_probe,
751 hub_disconnect,
752 hub_id_table,
753 NULL, /* suspend */
754 NULL, /* resume */
755 {NULL, NULL} /* driver_list */
756};
757
758
759int usbh_init_hub_driver(void)
760{
761 USBH_RegisterDriver(&hub_driver);
762 return 0;
763}
764
766 /* end of group USBH_EXPORTED_FUNCTIONS */
768 /* end of group USBH_Driver */
770 /* end of group USB_Host_Driver */
772 /* end of group Component_Library */
774
775
776
#define NULL
Definition: M4521.h:13912
URB_T * USBH_AllocUrb(void)
Allocate an URB from USB Core driver internal URB pool.
Definition: usbh_support.c:76
int status
Definition: usbh_core.h:521
int32_t USBH_RegisterDriver(USB_DRIVER_T *new_driver)
Register a device driver to USB Host Core driver.
Definition: usbh_core.c:78
int32_t USBH_SubmitUrb(URB_T *urb)
Submit an URB to USB core for transfer data.
Definition: usbh_core.c:219
int32_t USBH_UnlinkUrb(URB_T *urb)
Cancel an URB which has been submit to USB core.
Definition: usbh_core.c:237
void USBH_FreeUrb(URB_T *)
Free the URB allocated from USBH_AllocUrb()
Definition: usbh_support.c:99
int USBH_ProcessHubEvents(void)
Processed USB hub device events. User application must invoke this routine in the main while loop....
Definition: usbh_hub.c:117
void * context
Definition: usbh_core.h:532
int32_t USBH_SendCtrlMsg(USB_DEV_T *dev, uint32_t pipe, uint8_t request, uint8_t requesttype, uint16_t value, uint16_t index, void *data, uint16_t size, int timeout)
Execute a control transfer.
Definition: usbh_core.c:375
USB Host core driver header file.
USB_IF_DESC_T
Definition: usbh_core.h:315
HIDDEN_SYMBOLS struct usb_device USB_DEV_T
#define USB_ERR_NODEV
Definition: usbh_err_code.h:11
#define USB_ERR_NOENT
Definition: usbh_err_code.h:5
#define USB_ERR_NOMEM
Definition: usbh_err_code.h:8
USB_HUB_T * usbh_alloc_hubdev()
Definition: usbh_support.c:276
void usbh_free_device(USB_DEV_T *dev)
Definition: usbh_support.c:252
USB_HUB_T * usbh_get_hub_by_dev(USB_DEV_T *dev)
Definition: usbh_support.c:310
void usbh_free_hubdev(USB_HUB_T *hub)
Definition: usbh_support.c:294
USB_DEV_T * usbh_alloc_device(USB_DEV_T *parent, USB_BUS_T *bus)
Definition: usbh_support.c:224
void usbh_mdelay(uint32_t msec)
Definition: usbh_support.c:330