48static LIST_HEAD(_HubEventList);
50static int usb_hub_events(
void);
54static int usb_get_hub_descriptor(
USB_DEV_T *dev,
void *data,
int size)
57 USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB,
58 USB_DT_HUB << 8, 0, data, size, HZ);
62static int usb_clear_hub_feature(
USB_DEV_T *dev,
int feature)
65 USB_REQ_CLEAR_FEATURE, USB_RT_HUB, feature, 0,
NULL, 0, HZ);
69static int usb_clear_port_feature(
USB_DEV_T *dev,
int port,
int feature)
72 USB_REQ_CLEAR_FEATURE, USB_RT_PORT, feature, port,
NULL, 0, HZ);
76static int usb_set_port_feature(
USB_DEV_T *dev,
int port,
int feature)
78 USB_info(
"usb_set_port_feature, port:%d of hub:%d\n", port, dev->devnum);
80 USB_REQ_SET_FEATURE, USB_RT_PORT, feature, port,
NULL, 0, HZ);
84static int usb_get_hub_status(
USB_DEV_T *dev,
void *data)
87 uint32_t stack_buff[8];
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));
97static int usb_get_port_status(
USB_DEV_T *dev,
int port,
void *data)
100 uint32_t stack_buff[8];
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));
119 ohci_int_timer_do(0);
120 return usb_hub_events();
127static void hub_irq(
URB_T *urb)
129 USB_HUB_T *hub = (USB_HUB_T *)urb->
context;
138 USB_warning(
"nonzero status in irq %d\n", urb->
status);
139 if((++hub->nerrors < 10) || hub->error)
148 if(list_empty(&hub->event_list))
150 list_add(&hub->event_list, &_HubEventList);
155static void usb_hub_power_on(USB_HUB_T *hub)
160 for(i = 0; i < hub->descriptor.bNbrPorts; i++)
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);
171static int usb_hub_configure(USB_HUB_T *hub, EP_INFO_T *ep_info)
174 USB_HUB_STATUS_T hubstatus;
178 USB_info(
"[HUB] Enter usb_hub_configure()... hub:%d\n", hub->dev->devnum);
181 ret = usb_get_hub_descriptor(dev, &hub->descriptor,
sizeof(USB_HUB_DESC_T));
187 USB_error(
"Erro - Unable to get hub descriptor (err = %d)\n", ret);
191 dev->maxchild = hub->descriptor.bNbrPorts;
193#ifdef USB_VERBOSE_DEBUG
194 USB_info(
"%d port%s detected\n", hub->descriptor.bNbrPorts, (hub->descriptor.bNbrPorts == 1) ?
"" :
"s");
197 if(hub->descriptor.wHubCharacteristics & HUB_CHAR_COMPOUND)
199 USB_info(
"part of a compound device\n");
203 USB_info(
"standalone hub\n");
207 switch(hub->descriptor.wHubCharacteristics & HUB_CHAR_LPSM)
210 USB_info(
"ganged power switching\n");
213 USB_info(
"individual port power switching\n");
217 USB_info(
"unknown reserved power switching mode\n");
222 switch(hub->descriptor.wHubCharacteristics & HUB_CHAR_OCPM)
225 USB_info(
"global over-current protection\n");
228 USB_info(
"individual port over-current protection\n");
232 USB_info(
"no over-current protection\n");
236 switch(dev->descriptor.bDeviceProtocol)
241 USB_debug(
"Single TT, ");
244 USB_debug(
"TT per port, ");
247 USB_debug(
"Unrecognized hub protocol %d", dev->descriptor.bDeviceProtocol);
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);
255 ret = usb_get_hub_status(dev, &hubstatus);
258 USB_error(
"Unable to get hub %d status (err = %d)\n", hub->dev->devnum, ret);
262 hubstatus.wHubStatus = USB_SWAP16(hubstatus.wHubStatus);
264#ifdef USB_VERBOSE_DEBUG
266 if(hubstatus.wHubStatus & HUB_STATUS_LOCAL_POWER)
268 USB_info(
"local power source is lost (inactive)\n");
272 USB_info(
"local power source is good\n");
276 if(hubstatus.wHubStatus & HUB_STATUS_OVERCURRENT)
278 USB_info(
"!! over-current\n");
282 USB_info(
"No over-current.\n");
287 pipe = usb_rcvintpipe(dev, ep_info->bEndpointAddress);
288 maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
290 if(maxp >
sizeof(hub->buffer))
291 maxp =
sizeof(hub->buffer);
296 USB_error(
"Error - couldn't allocate interrupt urb");
301 if(ep_info->bInterval < 16)
302 ep_info->bInterval = 16;
304 FILL_INT_URB(hub->urb, dev, pipe, hub->buffer, maxp, hub_irq,
305 hub, ep_info->bInterval);
309 USB_error(
"Error - USBH_SubmitUrb failed (%d)", ret);
314 if(g_ohci_bus.root_hub != hub->dev)
315 usb_hub_power_on(hub);
327 USB_debug(
"hub_probe - dev=0x%x\n", (
int)dev);
329 ifnum = ifd->bInterfaceNumber;
331 if(dev->descriptor.bDeviceClass != 0x09)
335 for(i = 0; i < dev->ep_list_cnt; i++)
337 if((dev->ep_list[i].ifnum == ifnum) &&
338 ((dev->ep_list[i].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT))
340 ep_info = &dev->ep_list[i];
346 USB_error(
"hub int ep not found!\n");
351 if(!(ep_info->bEndpointAddress & USB_DIR_IN))
353 USB_error(
"Error - Device #%d is hub class, but has output endpoint?\n", dev->devnum);
358 if((ep_info->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
360 USB_error(
"Error - Device #%d is hub class, but has endpoint other than interrupt?\n", dev->devnum);
365 USB_debug(
"USB hub found\n");
371 INIT_LIST_HEAD(&hub->event_list);
374 if(usb_hub_configure(hub, ep_info) == 0)
377 USB_error(
"Error - hub configuration failed for device #%d\n", dev->devnum);
380 list_del(&hub->event_list);
381 INIT_LIST_HEAD(&hub->event_list);
388static void hub_disconnect(
USB_DEV_T *dev)
396 USB_warning(
"hub_disconnect - hub device not found!\n");
401 list_del(&hub->event_list);
402 INIT_LIST_HEAD(&hub->event_list);
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,
424 uint16_t portchange, portstatus;
425 USB_PORT_STATUS_T portsts;
427 for(delay_time = 0; delay_time < HUB_RESET_TIMEOUT; delay_time += delay)
433 ret = usb_get_port_status(hub, port + 1, &portsts);
436 USB_error(
"Error - get_port_status(%d) failed (err = %d)\n", port + 1, ret);
440 portstatus = portsts.wPortStatus;
441 portchange = portsts.wPortChange;
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");
447 if((portchange & USB_PORT_STAT_C_CONNECTION) ||
448 !(portstatus & USB_PORT_STAT_CONNECTION))
452 if(!(portstatus & USB_PORT_STAT_RESET) &&
453 (portstatus & USB_PORT_STAT_ENABLE))
455 if(portstatus & USB_PORT_STAT_HIGH_SPEED)
457 USB_debug(
"Device is high speed!\n");
458 dev->speed = USB_SPEED_HIGH;
460 else if(portstatus & USB_PORT_STAT_LOW_SPEED)
462 USB_debug(
"Device is low speed!\n");
463 dev->speed = USB_SPEED_LOW;
467 USB_debug(
"Device is full speed!\n");
468 dev->speed = USB_SPEED_FULL;
471 dev->slow = (portstatus & USB_PORT_STAT_LOW_SPEED) ? 1 : 0;
476 if(delay_time >= 2 * HUB_SHORT_RESET_TIME)
477 delay = HUB_LONG_RESET_TIME;
479 USB_info(
"port %d of hub %d not reset yet, waiting %dms\n", port + 1, hub->devnum, delay);
485static int usb_hub_port_reset(
USB_DEV_T *hub,
int port,
490 USB_info(
"usb_hub_port_reset: hub:%d, port:%d dev:%x\n", hub->devnum, port + 1, (
int)dev);
493 for(i = 0; i < HUB_RESET_TRIES; i++)
495 usb_set_port_feature(hub, port + 1, USB_PORT_FEAT_RESET);
497 if(!usb_hub_port_wait_reset(hub, port, dev, delay))
499 usb_clear_port_feature(hub, port + 1, USB_PORT_FEAT_C_RESET);
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;
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");
513void usb_hub_port_disable(
USB_DEV_T *hub,
int port)
517 ret = usb_clear_port_feature(hub, port + 1, USB_PORT_FEAT_ENABLE);
519 USB_error(
"cannot disable port %d of hub %d (err = %d)\n",
520 port + 1, hub->devnum, ret);
524static void usb_hub_port_connect_change(USB_HUB_T *hubstate,
USB_DEV_T *hub,
int port,
525 USB_PORT_STATUS_T *portsts)
529 uint32_t delay = HUB_SHORT_RESET_TIME;
532 portstatus = portsts->wPortStatus;
539 usb_clear_port_feature(hub, port + 1, USB_PORT_FEAT_C_CONNECTION);
542 if(hub->children[port])
543 usbh_disconnect_device(&hub->children[port]);
546 if(!(portstatus & USB_PORT_STAT_CONNECTION))
548 if(portstatus & USB_PORT_STAT_ENABLE)
549 usb_hub_port_disable(hub, port);
553 if(portstatus & USB_PORT_STAT_LOW_SPEED)
556 delay = HUB_LONG_RESET_TIME;
559 for(i = 0; i < HUB_PROBE_TRIES; i++)
565 USB_error(
"Error - couldn't allocate usb_device\n");
568 dev->hub_port = port;
569 hub->children[port] = dev;
571 if(usb_hub_port_reset(hub, port, dev, delay))
578 usbh_connect_device(dev);
580 USB_debug(
"USB new device connect, assigned device number %d\n", dev->devnum);
583 if(usbh_settle_new_device(dev) == 0)
590 delay = HUB_LONG_RESET_TIME;
593 hub->children[port] =
NULL;
594 usb_hub_port_disable(hub, port);
598int usb_hub_events(
void)
603 USB_HUB_STATUS_T hubsts;
608 if(list_empty(&_HubEventList))
619 if(list_empty(&_HubEventList))
623 tmp = _HubEventList.next;
625 hub = list_entry(tmp, USB_HUB_T, event_list);
633 USB_error(
"hub error %d!!\n", hub->error);
637 if(hub->urb->transfer_buffer_length == 1)
638 irq_data = *(uint8_t *)hub->urb->transfer_buffer;
643 irq_data = (*((uint8_t *)hub->urb->transfer_buffer + 1) << 8) |
644 *(uint8_t *)hub->urb->transfer_buffer;
647 for(i = 0; i < hub->descriptor.bNbrPorts; i++)
649 USB_PORT_STATUS_T portsts;
650 uint16_t portstatus, portchange;
652 if(!((irq_data >> (i + 1)) & 0x01))
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);
659 USB_error(
"Error - get_hub %d port %d status failed (err = %d)\n", hub->dev->devnum, i + 1, ret);
663 portstatus = portsts.wPortStatus;
664 portchange = portsts.wPortChange;
665 USB_debug(
"portstatus = %x, portchange = %x\n", portstatus, portchange);
667 if(portchange & USB_PORT_STAT_C_CONNECTION)
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);
672 else if(portchange & USB_PORT_STAT_C_ENABLE)
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);
682 if(!(portstatus & USB_PORT_STAT_ENABLE) &&
683 (portstatus & USB_PORT_STAT_CONNECTION) &&
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);
691 if(portchange & USB_PORT_STAT_C_SUSPEND)
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);
697 if(portchange & USB_PORT_STAT_C_OVERCURRENT)
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);
704 if(portchange & USB_PORT_STAT_C_RESET)
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);
712 if(usb_get_hub_status(dev, &hubsts) < 0)
713 USB_error(
"Error - get_hub_status failed\n");
717 hubchange = USB_SWAP16(hubsts.wHubChange);
718 if(hubchange & HUB_CHANGE_LOCAL_POWER)
720 USB_debug(
"hub power change\n");
721 usb_clear_hub_feature(dev, C_HUB_LOCAL_POWER);
723 if(hubchange & HUB_CHANGE_OVERCURRENT)
725 USB_error(
"!!hub overcurrent change\n");
727 usb_clear_hub_feature(dev, C_HUB_OVER_CURRENT);
728 usb_hub_power_on(hub);
738static USB_DEV_ID_T hub_id_table[] =
740 USB_DEVICE_ID_MATCH_INT_CLASS,
747static USB_DRIVER_T hub_driver =
759int usbh_init_hub_driver(
void)
URB_T * USBH_AllocUrb(void)
Allocate an URB from USB Core driver internal URB pool.
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.
void USBH_FreeUrb(URB_T *)
Free the URB allocated from USBH_AllocUrb()
int USBH_ProcessHubEvents(void)
Processed USB hub device events. User application must invoke this routine in the main while loop....
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.
USB Host core driver header file.
HIDDEN_SYMBOLS struct usb_device USB_DEV_T
USB_HUB_T * usbh_alloc_hubdev()
void usbh_free_device(USB_DEV_T *dev)
USB_HUB_T * usbh_get_hub_by_dev(USB_DEV_T *dev)
void usbh_free_hubdev(USB_HUB_T *hub)
USB_DEV_T * usbh_alloc_device(USB_DEV_T *parent, USB_BUS_T *bus)
void usbh_mdelay(uint32_t msec)