23#define HUB_DBGMSG printf
26static HUB_DEV_T g_hub_dev[MAX_HUB_DEVICE];
28static int do_port_reset(HUB_DEV_T *hub,
int port);
30static HUB_DEV_T *alloc_hub_device(
void)
33 for(i = 0; i < MAX_HUB_DEVICE; i++)
35 if(g_hub_dev[i].iface ==
NULL)
37 memset((
char *)&g_hub_dev[i], 0,
sizeof(HUB_DEV_T));
38 g_hub_dev[i].port_reset = do_port_reset;
45static void free_hub_device(HUB_DEV_T *hub_dev)
48 for(i = 0; i < MAX_HUB_DEVICE; i++)
50 if(g_hub_dev[i].iface == hub_dev->iface)
52 memset((
char *)&g_hub_dev[i], 0,
sizeof(HUB_DEV_T));
57static HUB_DEV_T * find_hub_device(IFACE_T *iface)
60 for(i = 0; i < MAX_HUB_DEVICE; i++)
62 if(g_hub_dev[i].iface == iface)
74static int set_hub_feature(HUB_DEV_T *hub,
int feature_selector,
int port)
76 UDEV_T *udev = hub->iface->udev;
79 return usbh_ctrl_xfer(udev, REQ_TYPE_OUT | REQ_TYPE_CLASS_DEV | REQ_TYPE_TO_DEV,
80 USB_REQ_SET_FEATURE, feature_selector, 0, 0,
81 NULL, &read_len, 200);
88static int clear_hub_feature(HUB_DEV_T *hub,
int feature_selector)
90 UDEV_T *udev = hub->iface->udev;
93 return usbh_ctrl_xfer(udev, REQ_TYPE_OUT | REQ_TYPE_CLASS_DEV | REQ_TYPE_TO_DEV,
94 USB_REQ_CLEAR_FEATURE, feature_selector, 0, 0,
95 NULL, &read_len, 200);
101static int get_hub_status(HUB_DEV_T *hub, uint16_t *wHubStatus, uint16_t *wHubChange)
103 UDEV_T *udev = hub->iface->udev;
108 ret = usbh_ctrl_xfer(udev, REQ_TYPE_IN | REQ_TYPE_CLASS_DEV | REQ_TYPE_TO_DEV,
109 USB_REQ_GET_STATUS, 0, 0, 4,
110 buff, &read_len, 200);
117 *wHubStatus = (buff[1] << 8) | buff[0];
118 *wHubChange = (buff[3] << 8) | buff[2];
125static int set_port_feature(HUB_DEV_T *hub,
int feature_selector,
int port)
127 UDEV_T *udev = hub->iface->udev;
130 return usbh_ctrl_xfer(udev, REQ_TYPE_OUT | REQ_TYPE_CLASS_DEV | REQ_TYPE_TO_OTHER,
131 USB_REQ_SET_FEATURE, feature_selector, port, 0,
132 NULL, &read_len, 200);
138static int clear_port_feature(HUB_DEV_T *hub,
int feature_selector,
int port)
140 UDEV_T *udev = hub->iface->udev;
143 return usbh_ctrl_xfer(udev, REQ_TYPE_OUT | REQ_TYPE_CLASS_DEV | REQ_TYPE_TO_OTHER,
144 USB_REQ_CLEAR_FEATURE, feature_selector, port, 0,
145 NULL, &read_len, 200);
151static int get_port_status(HUB_DEV_T *hub,
int port, uint16_t *wPortStatus, uint16_t *wPortChange)
153 UDEV_T *udev = hub->iface->udev;
158 ret = usbh_ctrl_xfer(udev, REQ_TYPE_IN | REQ_TYPE_CLASS_DEV | REQ_TYPE_TO_OTHER,
159 USB_REQ_GET_STATUS, 0, port, 4,
160 buff, &read_len, 200);
166 USB_error(
"HUB [%s] get_port_status read_len!=4. (%d).\n", hub->pos_id, read_len);
170 *wPortStatus = (buff[1] << 8) | buff[0];
171 *wPortChange = (buff[3] << 8) | buff[2];
175static void hub_status_irq(UTR_T *utr)
182 hub = (HUB_DEV_T *)utr->context;
186 USB_error(
"hub_status_irq - has error: 0x%x\n", utr->status);
192 for(i = 0; i < utr->xfer_len; i++)
194 hub->sc_bitmap |= (utr->buff[i] << (i * 8));
200int hub_probe(IFACE_T *iface)
202 UDEV_T *udev = iface->udev;
203 ALT_IFACE_T *aif = iface->aif;
213 if(aif->ifd->bInterfaceClass != USB_CLASS_HUB)
219 for(i = 0; i < aif->ifd->bNumEndpoints; i++)
221 if(((aif->ep[i].bmAttributes & EP_ATTR_TT_MASK) == EP_ATTR_TT_INT) &&
222 ((aif->ep[i].bEndpointAddress & EP_ADDR_DIR_MASK) == EP_ADDR_DIR_IN))
232 hub = alloc_hub_device();
237 iface->context = (
void *)hub;
239 str[0] += udev->port_num;
240 if(udev->parent ==
NULL)
241 strcpy(hub->pos_id, str);
244 strcpy(hub->pos_id, udev->parent->pos_id);
245 strcat(hub->pos_id, str);
248 HUB_DBGMSG(
"hub found is:[%s] - device (vid=0x%x, pid=0x%x), interface %d.\n", hub->pos_id,
249 udev->descriptor.idVendor, udev->descriptor.idProduct, iface->if_num);
254 ret = usbh_ctrl_xfer(udev, REQ_TYPE_IN | REQ_TYPE_CLASS_DEV | REQ_TYPE_TO_DEV,
255 USB_REQ_GET_DESCRIPTOR,
256 ((USB_DT_CLASS | 0x9) << 8),
258 (uint8_t *)&desc_hub, &read_len, 200);
261 USB_error(
"Failed to get hub descriptor!\n");
265 hub->bNbrPorts = desc_hub.bNbrPorts;
266 hub->bPwrOn2PwrGood = desc_hub.bPwrOn2PwrGood * 2;
267 HUB_DBGMSG(
"Hub has %d ports, power-to-power-good time is %d ms.\n", hub->bNbrPorts, hub->bPwrOn2PwrGood);
273 for(i = 1; i <= hub->bNbrPorts; i++)
275 ret = set_port_feature(hub, FS_PORT_POWER, i);
277 HUB_DBGMSG(
"Hub [%s] port %d power enabled.\n", hub->pos_id, i);
279 HUB_DBGMSG(
"Hub [%s] port %d power enabling failed!\n", hub->pos_id, i);
282 delay_us(hub->bPwrOn2PwrGood * 1000 + 100000);
284 utr = alloc_utr(udev);
287 free_hub_device(hub);
293 utr->buff = hub->buff;
294 utr->data_len = HUB_STATUS_MAX_BYTE;
296 utr->func = hub_status_irq;
298 ret = usbh_int_xfer(utr);
301 HUB_DBGMSG(
"Error - failed to submit interrupt read request (%d)", ret);
303 free_hub_device(hub);
306 HUB_DBGMSG(
"hub_probe OK.\n");
310void hub_disconnect(IFACE_T *iface)
316 hub = find_hub_device(iface);
319 HUB_DBGMSG(
"hub_disconnect - hub not found!\n");
326 for(port = 1; port <= hub->bNbrPorts; port++)
331 HUB_DBGMSG(
"Disconnect HUB [%s] port %d device 0x%x:0x%x\n", hub->pos_id, port, udev->descriptor.idVendor, udev->descriptor.idProduct);
332 disconnect_device(udev);
338 usbh_quit_utr(hub->utr);
342 HUB_DBGMSG(
"Disconnect HUB [%s].\n", hub->pos_id);
343 free_hub_device(hub);
347UDEV_DRV_T hub_driver =
356static int hub_status_change(HUB_DEV_T *hub)
358 uint16_t wHubStatus, wHubChange;
361 HUB_DBGMSG(
"Hub [%s] hub status change 0x%x.\n", hub->pos_id, hub->sc_bitmap);
363 ret = get_hub_status(hub, &wHubStatus, &wHubChange);
366 USB_error(
"Failed to get Hub [%s] status! (%d)\n", hub->pos_id, ret);
370 printf(
"Hub [%s] status: 0x%x, change: 0x%x\n", hub->pos_id, wHubStatus, wHubChange);
372 if(wHubChange & HUB_C_LOCAL_POWER)
374 ret = clear_hub_feature(hub, FS_C_HUB_LOCAL_POWER);
379 if(wHubChange & HUB_C_OVERCURRENT)
381 ret = clear_hub_feature(hub, FS_C_HUB_OVER_CURRENT);
389static int do_port_reset(HUB_DEV_T *hub,
int port)
394 uint16_t wPortStatus, wPortChange;
397 reset_time = PORT_RESET_TIME_MS;
399 for(retry = 0; retry < PORT_RESET_RETRY; retry++)
401 ret = set_port_feature(hub, FS_PORT_RESET, port);
406 while(
get_ticks() - t0 < (reset_time / 10) + 1)
410 ret = get_port_status(hub, port, &wPortStatus, &wPortChange);
413 USB_error(
"Failed to get Hub [%s] port %d status! (%d)\n", hub->pos_id, port, ret);
420 if(((wPortStatus & PORT_S_CONNECTION) == 0) ||
421 ((wPortStatus & (PORT_S_CONNECTION | PORT_S_ENABLE)) == (PORT_S_CONNECTION | PORT_S_ENABLE)))
423 clear_port_feature(hub, PORT_C_ENABLE, port);
427 reset_time += PORT_RESET_RETRY_INC_MS;
429 USB_debug(
"HUB [%s] port %d - port reset failed!\n", hub->pos_id, port);
433static int port_connect_change(HUB_DEV_T *hub,
int port, uint16_t wPortStatus)
436 uint16_t wPortChange;
439 if(wPortStatus & PORT_S_CONNECTION)
447 disconnect_device(udev);
453 ret = do_port_reset(hub, port);
457 ret = get_port_status(hub, port, &wPortStatus, &wPortChange);
460 USB_error(
"Failed to get Hub [%s] port %d status! (%d)\n", hub->pos_id, port, ret);
463 printf(
"Hub [%s] port %d, status: 0x%x, change: 0x%x\n", hub->pos_id, port, wPortStatus, wPortChange);
468 udev = alloc_device();
473 udev->port_num = port;
475 if(wPortStatus & PORT_S_HIGH_SPEED)
476 udev->speed = SPEED_HIGH;
477 else if(wPortStatus & PORT_S_LOW_SPEED)
478 udev->speed = SPEED_LOW;
480 udev->speed = SPEED_FULL;
482 udev->hc_driver = hub->iface->udev->hc_driver;
484 ret = connect_device(udev);
487 USB_error(
"connect_device error! [%d]\n", ret);
499 disconnect_device(udev);
505static int port_status_change(HUB_DEV_T *hub,
int port)
507 uint16_t wPortStatus, wPortChange;
510 ret = get_port_status(hub, port, &wPortStatus, &wPortChange);
513 USB_error(
"Failed to get Hub [%s] port %d status! (%d)\n", hub->pos_id, port, ret);
516 printf(
"Hub [%s] port %d, status: 0x%x, change: 0x%x\n", hub->pos_id, port, wPortStatus, wPortChange);
518 if(wPortChange & PORT_C_CONNECTION)
520 ret = clear_port_feature(hub, FS_C_PORT_CONNECTION, port);
524 port_connect_change(hub, port, wPortStatus);
527 if(wPortChange & PORT_C_ENABLE)
529 ret = clear_port_feature(hub, FS_C_PORT_ENABLE, port);
534 if(wPortChange & PORT_C_SUSPEND)
536 ret = clear_port_feature(hub, FS_C_PORT_SUSPEND, port);
541 if(wPortChange & PORT_C_OVERCURRENT)
543 ret = clear_port_feature(hub, FS_C_PORT_OVER_CURRENT, port);
548 if(wPortChange & FS_C_PORT_RESET)
550 ret = clear_port_feature(hub, FS_C_PORT_RESET, port);
557static volatile uint8_t _hub_polling_mutex = 0;
559static int hub_polling(
void)
563 int i, ret, port, change = 0;
565 if(_hub_polling_mutex)
568 _hub_polling_mutex = 1;
570 for(i = 0; i < MAX_HUB_DEVICE; i++)
572 if((g_hub_dev[i].iface !=
NULL) && (g_hub_dev[i].sc_bitmap))
582 if(hub->sc_bitmap & 0x1)
583 hub_status_change(hub);
585 for(port = 1; port <= hub->bNbrPorts; port++)
587 if(hub->sc_bitmap & (1 << port))
589 ret = port_status_change(hub, port);
600 ret = usbh_int_xfer(utr);
603 USB_error(
"Failed to re-submit HUB [%s] interrupt-in request (%d)", hub->pos_id, ret);
608 _hub_polling_mutex = 0;
617void usbh_hub_init(
void)
619 memset((
char *)&g_hub_dev[0], 0,
sizeof(g_hub_dev));
620 usbh_register_driver(&hub_driver);
643 ret = ohci_driver.rthub_polling();
673 HUB_DEV_T *hub =
NULL;
676 for(i = 0; i < MAX_HUB_DEVICE; i++)
678 if((g_hub_dev[i].iface !=
NULL) && (strcmp(g_hub_dev[i].pos_id, hub_id) == 0))
690 if((udev->parent == hub) && (udev->port_num == port))
NuMicro peripheral access layer header file.
#define USBH_ERR_DATA_UNDERRUN
#define USBH_ERR_TRANSFER
#define USBH_ERR_NOT_MATCHED
#define USBH_ERR_PORT_RESET
#define USBH_ERR_MEMORY_OUT
UDEV_T * usbh_find_device(char *hub_id, int port)
Find the device under the specified hub port.
HIDDEN_SYMBOLS int usbh_pooling_hubs(void)
Let USB stack polls all root hubs and downstream hubs. If there's any hub port change found,...
uint32_t get_ticks(void)
A function return current tick count.
USB Host hub class driver header file.
USB Host library header file.
USB Host library exported header file.