| NUC472_NUC442_BSP V3.03.003 The Board Support Package for NUC472/NUC442

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