43static LIST_HEAD(_HubEventList);
45static int usb_hub_events(
void);
47extern USB_HUB_T * usbh_get_hub_by_dev(
USB_DEV_T *dev);
49static int usb_get_hub_descriptor(
USB_DEV_T *dev,
void *data,
int size)
52 USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB,
53 USB_DT_HUB << 8, 0, data, size, HZ);
57static int usb_clear_hub_feature(
USB_DEV_T *dev,
int feature)
60 USB_REQ_CLEAR_FEATURE, USB_RT_HUB, feature, 0,
NULL, 0, HZ);
64static int usb_clear_port_feature(
USB_DEV_T *dev,
int port,
int feature)
67 USB_REQ_CLEAR_FEATURE, USB_RT_PORT, feature, port,
NULL, 0, HZ);
71static int usb_set_port_feature(
USB_DEV_T *dev,
int port,
int feature)
73 USB_info(
"usb_set_port_feature, port:%d of hub:%d\n", port, dev->devnum);
75 USB_REQ_SET_FEATURE, USB_RT_PORT, feature, port,
NULL, 0, HZ);
79static int usb_get_hub_status(
USB_DEV_T *dev,
void *data)
82 uint32_t stack_buff[8];
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));
92static int usb_get_port_status(
USB_DEV_T *dev,
int port,
void *data)
95 uint32_t stack_buff[8];
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));
115 ohci_int_timer_do(0);
116 return usb_hub_events();
125static void hub_irq(
URB_T *urb)
127 USB_HUB_T *hub = (USB_HUB_T *)urb->
context;
136 USB_warning(
"nonzero status in irq %d\n", urb->
status);
137 if ((++hub->nerrors < 10) || hub->error)
146 if (list_empty(&hub->event_list))
148 list_add(&hub->event_list, &_HubEventList);
153static void usb_hub_power_on(USB_HUB_T *hub)
158 for (i = 0; i < hub->descriptor.bNbrPorts; i++)
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);
165 usbh_mdelay(hub->descriptor.bPwrOn2PwrGood * 2);
169static int usb_hub_configure(USB_HUB_T *hub, EP_INFO_T *ep_info)
172 USB_HUB_STATUS_T hubstatus;
176 USB_info(
"[HUB] Enter usb_hub_configure()... hub:%d\n", hub->dev->devnum);
179 ret = usb_get_hub_descriptor(dev, &hub->descriptor,
sizeof(USB_HUB_DESC_T));
185 USB_error(
"Erro - Unable to get hub descriptor (err = %d)\n", ret);
189 dev->maxchild = hub->descriptor.bNbrPorts;
191#ifdef USB_VERBOSE_DEBUG
192 USB_info(
"%d port%s detected\n", hub->descriptor.bNbrPorts, (hub->descriptor.bNbrPorts == 1) ?
"" :
"s");
195 if (hub->descriptor.wHubCharacteristics & HUB_CHAR_COMPOUND)
197 USB_info(
"part of a compound device\n");
201 USB_info(
"standalone hub\n");
205 switch (hub->descriptor.wHubCharacteristics & HUB_CHAR_LPSM)
208 USB_info(
"ganged power switching\n");
211 USB_info(
"individual port power switching\n");
215 USB_info(
"unknown reserved power switching mode\n");
220 switch (hub->descriptor.wHubCharacteristics & HUB_CHAR_OCPM)
223 USB_info(
"global over-current protection\n");
226 USB_info(
"individual port over-current protection\n");
230 USB_info(
"no over-current protection\n");
234 switch (dev->descriptor.bDeviceProtocol)
239 USB_debug(
"Single TT, ");
242 USB_debug(
"TT per port, ");
245 USB_debug(
"Unrecognized hub protocol %d", dev->descriptor.bDeviceProtocol);
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);
253 ret = usb_get_hub_status(dev, &hubstatus);
256 USB_error(
"Unable to get hub %d status (err = %d)\n", hub->dev->devnum, ret);
260 hubstatus.wHubStatus = USB_SWAP16(hubstatus.wHubStatus);
262#ifdef USB_VERBOSE_DEBUG
264 if (hubstatus.wHubStatus & HUB_STATUS_LOCAL_POWER)
266 USB_info(
"local power source is lost (inactive)\n");
270 USB_info(
"local power source is good\n");
274 if (hubstatus.wHubStatus & HUB_STATUS_OVERCURRENT)
276 USB_info(
"!! over-current\n");
280 USB_info(
"No over-current.\n");
285 pipe = usb_rcvintpipe(dev, ep_info->bEndpointAddress);
286 maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
288 if (maxp >
sizeof(hub->buffer))
289 maxp =
sizeof(hub->buffer);
294 USB_error(
"Error - couldn't allocate interrupt urb");
299 if (ep_info->bInterval < 16)
300 ep_info->bInterval = 16;
302 FILL_INT_URB(hub->urb, dev, pipe, hub->buffer, maxp, hub_irq,
303 hub, ep_info->bInterval);
307 USB_error(
"Error - USBH_SubmitUrb failed (%d)", ret);
312 if (g_ohci_bus.root_hub != hub->dev)
313 usb_hub_power_on(hub);
325 USB_debug(
"hub_probe - dev=0x%x\n", (
int)dev);
327 ifnum = ifd->bInterfaceNumber;
329 if (dev->descriptor.bDeviceClass != 0x09)
333 for (i = 0; i < dev->ep_list_cnt; i++)
335 if ((dev->ep_list[i].ifnum == ifnum) &&
336 ((dev->ep_list[i].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT))
338 ep_info = &dev->ep_list[i];
344 USB_error(
"hub int ep not found!\n");
349 if (!(ep_info->bEndpointAddress & USB_DIR_IN))
351 USB_error(
"Error - Device #%d is hub class, but has output endpoint?\n", dev->devnum);
356 if ((ep_info->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
358 USB_error(
"Error - Device #%d is hub class, but has endpoint other than interrupt?\n", dev->devnum);
363 USB_debug(
"USB hub found\n");
365 hub = usbh_alloc_hubdev();
369 INIT_LIST_HEAD(&hub->event_list);
372 if (usb_hub_configure(hub, ep_info) == 0)
375 USB_error(
"Error - hub configuration failed for device #%d\n", dev->devnum);
378 list_del(&hub->event_list);
379 INIT_LIST_HEAD(&hub->event_list);
381 usbh_free_hubdev(hub);
386static void hub_disconnect(
USB_DEV_T *dev)
390 hub = usbh_get_hub_by_dev(dev);
394 USB_warning(
"hub_disconnect - hub device not found!\n");
399 list_del(&hub->event_list);
400 INIT_LIST_HEAD(&hub->event_list);
408 usbh_free_hubdev(hub);
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
418static int usb_hub_port_wait_reset(
USB_DEV_T *hub,
int port,
422 uint16_t portchange, portstatus;
423 USB_PORT_STATUS_T portsts;
425 for (delay_time = 0; delay_time < HUB_RESET_TIMEOUT; delay_time += delay)
431 ret = usb_get_port_status(hub, port + 1, &portsts);
434 USB_error(
"Error - get_port_status(%d) failed (err = %d)\n", port + 1, ret);
438 portstatus = portsts.wPortStatus;
439 portchange = portsts.wPortChange;
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");
445 if ((portchange & USB_PORT_STAT_C_CONNECTION) ||
446 !(portstatus & USB_PORT_STAT_CONNECTION))
450 if (!(portstatus & USB_PORT_STAT_RESET) &&
451 (portstatus & USB_PORT_STAT_ENABLE))
453 if (portstatus & USB_PORT_STAT_HIGH_SPEED)
455 USB_debug(
"Device is high speed!\n");
456 dev->speed = USB_SPEED_HIGH;
458 else if (portstatus & USB_PORT_STAT_LOW_SPEED)
460 USB_debug(
"Device is low speed!\n");
461 dev->speed = USB_SPEED_LOW;
465 USB_debug(
"Device is full speed!\n");
466 dev->speed = USB_SPEED_FULL;
469 dev->slow = (portstatus & USB_PORT_STAT_LOW_SPEED) ? 1 : 0;
474 if (delay_time >= 2 * HUB_SHORT_RESET_TIME)
475 delay = HUB_LONG_RESET_TIME;
477 USB_info(
"port %d of hub %d not reset yet, waiting %dms\n", port + 1, hub->devnum, delay);
483static int usb_hub_port_reset(
USB_DEV_T *hub,
int port,
488 USB_info(
"usb_hub_port_reset: hub:%d, port:%d dev:%x\n", hub->devnum, port+1, (
int)dev);
491 for (i = 0; i < HUB_RESET_TRIES; i++)
493 usb_set_port_feature(hub, port + 1, USB_PORT_FEAT_RESET);
495 if (!usb_hub_port_wait_reset(hub, port, dev, delay))
497 usb_clear_port_feature(hub, port + 1, USB_PORT_FEAT_C_RESET);
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;
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");
511void usb_hub_port_disable(
USB_DEV_T *hub,
int port)
515 ret = usb_clear_port_feature(hub, port + 1, USB_PORT_FEAT_ENABLE);
517 USB_error(
"cannot disable port %d of hub %d (err = %d)\n",
518 port + 1, hub->devnum, ret);
522static void usb_hub_port_connect_change(USB_HUB_T *hubstate,
USB_DEV_T *hub,
int port,
523 USB_PORT_STATUS_T *portsts)
527 uint32_t delay = HUB_SHORT_RESET_TIME;
530 portstatus = portsts->wPortStatus;
537 usb_clear_port_feature(hub, port + 1, USB_PORT_FEAT_C_CONNECTION);
540 if (hub->children[port])
541 usbh_disconnect_device(&hub->children[port]);
544 if (!(portstatus & USB_PORT_STAT_CONNECTION))
546 if (portstatus & USB_PORT_STAT_ENABLE)
547 usb_hub_port_disable(hub, port);
551 if (portstatus & USB_PORT_STAT_LOW_SPEED)
554 delay = HUB_LONG_RESET_TIME;
557 for (i = 0; i < HUB_PROBE_TRIES; i++)
560 dev = usbh_alloc_device(hub, hub->bus);
563 USB_error(
"Error - couldn't allocate usb_device\n");
566 dev->hub_port = port;
567 hub->children[port] = dev;
569 if (usb_hub_port_reset(hub, port, dev, delay))
571 usbh_free_device(dev);
576 usbh_connect_device(dev);
578 USB_debug(
"USB new device connect, assigned device number %d\n", dev->devnum);
581 if (usbh_settle_new_device(dev) == 0)
585 usbh_free_device(dev);
588 delay = HUB_LONG_RESET_TIME;
591 hub->children[port] =
NULL;
592 usb_hub_port_disable(hub, port);
596int usb_hub_events(
void)
601 USB_HUB_STATUS_T hubsts;
606 if (list_empty(&_HubEventList))
617 if (list_empty(&_HubEventList))
621 tmp = _HubEventList.next;
623 hub = list_entry(tmp, USB_HUB_T, event_list);
631 USB_error(
"hub error %d!!\n", hub->error);
635 if (hub->urb->transfer_buffer_length == 1)
636 irq_data = *(uint8_t *)hub->urb->transfer_buffer;
641 irq_data = (*((uint8_t *)hub->urb->transfer_buffer+1) << 8) |
642 *(uint8_t *)hub->urb->transfer_buffer;
645 for (i = 0; i < hub->descriptor.bNbrPorts; i++)
647 USB_PORT_STATUS_T portsts;
648 uint16_t portstatus, portchange;
650 if (!((irq_data >> (i+1)) & 0x01))
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);
657 USB_error(
"Error - get_hub %d port %d status failed (err = %d)\n", hub->dev->devnum, i+1, ret);
661 portstatus = portsts.wPortStatus;
662 portchange = portsts.wPortChange;
663 USB_debug(
"portstatus = %x, portchange = %x\n", portstatus, portchange);
665 if (portchange & USB_PORT_STAT_C_CONNECTION)
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);
670 else if (portchange & USB_PORT_STAT_C_ENABLE)
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);
680 if (!(portstatus & USB_PORT_STAT_ENABLE) &&
681 (portstatus & USB_PORT_STAT_CONNECTION) &&
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);
689 if (portchange & USB_PORT_STAT_C_SUSPEND)
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);
695 if (portchange & USB_PORT_STAT_C_OVERCURRENT)
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);
702 if (portchange & USB_PORT_STAT_C_RESET)
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);
710 if (usb_get_hub_status(dev, &hubsts) < 0)
711 USB_error(
"Error - get_hub_status failed\n");
715 hubchange = USB_SWAP16(hubsts.wHubChange);
716 if (hubchange & HUB_CHANGE_LOCAL_POWER)
718 USB_debug(
"hub power change\n");
719 usb_clear_hub_feature(dev, C_HUB_LOCAL_POWER);
721 if (hubchange & HUB_CHANGE_OVERCURRENT)
723 USB_error(
"!!hub overcurrent change\n");
725 usb_clear_hub_feature(dev, C_HUB_OVER_CURRENT);
726 usb_hub_power_on(hub);
736static USB_DEV_ID_T hub_id_table[] =
738 USB_DEVICE_ID_MATCH_INT_CLASS,
745static USB_DRIVER_T hub_driver =
757int usbh_init_hub_driver(
void)
NUC472/NUC442 peripheral access layer header file. This file contains all the peripheral register's d...
int32_t USBH_RegisterDriver(USB_DRIVER_T *new_driver)
Register a device driver to USB Host Core driver.
int32_t USBH_SubmitUrb(URB_T *urb)
Submit an URB to USB core for transfer data.
int32_t USBH_UnlinkUrb(URB_T *urb)
Cancel an URB which has been submit to USB core.
URB_T * USBH_AllocUrb(void)
Allocate an URB from USB Core driver internal URB pool.
void USBH_FreeUrb(URB_T *)
Free the URB allocated from USBH_AllocUrb()
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.
int USBH_ProcessHubEvents(void)
Processed USB hub device events. User application must invoke this routine in the main while loop....
HIDDEN_SYMBOLS struct usb_device USB_DEV_T
#define NULL
NULL pointer.
USB Host core driver header file.