24#define HUB_DBGMSG printf
27static HUB_DEV_T g_hub_dev[MAX_HUB_DEVICE];
29static int do_port_reset(HUB_DEV_T *hub,
int port);
31static HUB_DEV_T *alloc_hub_device(
void)
34 for (i = 0; i < MAX_HUB_DEVICE; i++)
36 if (g_hub_dev[i].iface ==
NULL)
38 memset((
char *)&g_hub_dev[i], 0,
sizeof(HUB_DEV_T));
39 g_hub_dev[i].port_reset = do_port_reset;
46static void free_hub_device(HUB_DEV_T *hub_dev)
49 for (i = 0; i < MAX_HUB_DEVICE; i++)
51 if (g_hub_dev[i].iface == hub_dev->iface)
53 memset((
char *)&g_hub_dev[i], 0,
sizeof(HUB_DEV_T));
58static HUB_DEV_T * find_hub_device(IFACE_T *iface)
61 for (i = 0; i < MAX_HUB_DEVICE; i++)
63 if (g_hub_dev[i].iface == iface)
75static int set_hub_feature(HUB_DEV_T *hub,
int feature_selector,
int port)
77 UDEV_T *udev = hub->iface->udev;
80 return usbh_ctrl_xfer(udev, REQ_TYPE_OUT | REQ_TYPE_CLASS_DEV | REQ_TYPE_TO_DEV,
81 USB_REQ_SET_FEATURE, feature_selector, 0, 0,
82 NULL, &read_len, 200);
89static int clear_hub_feature(HUB_DEV_T *hub,
int feature_selector)
91 UDEV_T *udev = hub->iface->udev;
94 return usbh_ctrl_xfer(udev, REQ_TYPE_OUT | REQ_TYPE_CLASS_DEV | REQ_TYPE_TO_DEV,
95 USB_REQ_CLEAR_FEATURE, feature_selector, 0, 0,
96 NULL, &read_len, 200);
102static int get_hub_status(HUB_DEV_T *hub, uint16_t *wHubStatus, uint16_t *wHubChange)
104 UDEV_T *udev = hub->iface->udev;
109 ret = usbh_ctrl_xfer(udev, REQ_TYPE_IN | REQ_TYPE_CLASS_DEV | REQ_TYPE_TO_DEV,
110 USB_REQ_GET_STATUS, 0, 0, 4,
111 buff, &read_len, 200);
118 *wHubStatus = (buff[1] << 8) | buff[0];
119 *wHubChange = (buff[3] << 8) | buff[2];
126static int set_port_feature(HUB_DEV_T *hub,
int feature_selector,
int port)
128 UDEV_T *udev = hub->iface->udev;
131 return usbh_ctrl_xfer(udev, REQ_TYPE_OUT | REQ_TYPE_CLASS_DEV | REQ_TYPE_TO_OTHER,
132 USB_REQ_SET_FEATURE, feature_selector, port, 0,
133 NULL, &read_len, 200);
139static int clear_port_feature(HUB_DEV_T *hub,
int feature_selector,
int port)
141 UDEV_T *udev = hub->iface->udev;
144 return usbh_ctrl_xfer(udev, REQ_TYPE_OUT | REQ_TYPE_CLASS_DEV | REQ_TYPE_TO_OTHER,
145 USB_REQ_CLEAR_FEATURE, feature_selector, port, 0,
146 NULL, &read_len, 200);
152static int get_port_status(HUB_DEV_T *hub,
int port, uint16_t *wPortStatus, uint16_t *wPortChange)
154 UDEV_T *udev = hub->iface->udev;
159 ret = usbh_ctrl_xfer(udev, REQ_TYPE_IN | REQ_TYPE_CLASS_DEV | REQ_TYPE_TO_OTHER,
160 USB_REQ_GET_STATUS, 0, port, 4,
161 buff, &read_len, 200);
167 USB_error(
"HUB [%s] get_port_status read_len!=4. (%d).\n", hub->pos_id, read_len);
171 *wPortStatus = (buff[1] << 8) | buff[0];
172 *wPortChange = (buff[3] << 8) | buff[2];
176static void hub_status_irq(UTR_T *utr)
183 hub = (HUB_DEV_T *)utr->context;
185 if (utr->status != 0)
187 USB_error(
"hub_status_irq - has error: 0x%x\n", utr->status);
193 for (i = 0; i < utr->xfer_len; i++)
195 hub->sc_bitmap |= (utr->buff[i] << (i * 8));
201int hub_probe(IFACE_T *iface)
203 UDEV_T *udev = iface->udev;
204 ALT_IFACE_T *aif = iface->aif;
214 if (aif->ifd->bInterfaceClass != USB_CLASS_HUB)
220 for (i = 0; i < aif->ifd->bNumEndpoints; i++)
222 if (((aif->ep[i].bmAttributes & EP_ATTR_TT_MASK) == EP_ATTR_TT_INT) &&
223 ((aif->ep[i].bEndpointAddress & EP_ADDR_DIR_MASK) == EP_ADDR_DIR_IN))
233 hub = alloc_hub_device();
238 iface->context = (
void *)hub;
240 str[0] += udev->port_num;
241 if (udev->parent ==
NULL)
242 strcpy(hub->pos_id, str);
245 strcpy(hub->pos_id, udev->parent->pos_id);
246 strcat(hub->pos_id, str);
249 HUB_DBGMSG(
"hub found is:[%s] - device (vid=0x%x, pid=0x%x), interface %d.\n", hub->pos_id,
250 udev->descriptor.idVendor, udev->descriptor.idProduct, iface->if_num);
255 ret = usbh_ctrl_xfer(udev, REQ_TYPE_IN | REQ_TYPE_CLASS_DEV | REQ_TYPE_TO_DEV,
256 USB_REQ_GET_DESCRIPTOR,
257 ((USB_DT_CLASS | 0x9) << 8),
259 (uint8_t *)&desc_hub, &read_len, 200);
262 USB_error(
"Failed to get hub descriptor!\n");
266 hub->bNbrPorts = desc_hub.bNbrPorts;
267 hub->bPwrOn2PwrGood = desc_hub.bPwrOn2PwrGood * 2;
268 HUB_DBGMSG(
"Hub has %d ports, power-to-power-good time is %d ms.\n", hub->bNbrPorts, hub->bPwrOn2PwrGood);
274 for (i = 1; i <= hub->bNbrPorts; i++)
276 ret = set_port_feature(hub, FS_PORT_POWER, i);
278 HUB_DBGMSG(
"Hub [%s] port %d power enabled.\n", hub->pos_id, i);
280 HUB_DBGMSG(
"Hub [%s] port %d power enabling failed!\n", hub->pos_id, i);
283 delay_us(hub->bPwrOn2PwrGood * 1000 + 100000);
285 utr = alloc_utr(udev);
288 free_hub_device(hub);
294 utr->buff = hub->buff;
295 utr->data_len = HUB_STATUS_MAX_BYTE;
297 utr->func = hub_status_irq;
299 ret = usbh_int_xfer(utr);
302 HUB_DBGMSG(
"Error - failed to submit interrupt read request (%d)", ret);
304 free_hub_device(hub);
307 HUB_DBGMSG(
"hub_probe OK.\n");
311void hub_disconnect(IFACE_T *iface)
317 hub = find_hub_device(iface);
320 HUB_DBGMSG(
"hub_disconnect - hub not found!\n");
327 for (port = 1; port <= hub->bNbrPorts; port++)
332 HUB_DBGMSG(
"Disconnect HUB [%s] port %d device 0x%x:0x%x\n", hub->pos_id, port, udev->descriptor.idVendor, udev->descriptor.idProduct);
333 disconnect_device(udev);
339 usbh_quit_utr(hub->utr);
343 HUB_DBGMSG(
"Disconnect HUB [%s].\n", hub->pos_id);
344 free_hub_device(hub);
348UDEV_DRV_T hub_driver =
357static int hub_status_change(HUB_DEV_T *hub)
359 uint16_t wHubStatus, wHubChange;
362 HUB_DBGMSG(
"Hub [%s] hub status change 0x%x.\n", hub->pos_id, hub->sc_bitmap);
364 ret = get_hub_status(hub, &wHubStatus, &wHubChange);
367 USB_error(
"Failed to get Hub [%s] status! (%d)\n", hub->pos_id, ret);
371 printf(
"Hub [%s] status: 0x%x, change: 0x%x\n", hub->pos_id, wHubStatus, wHubChange);
373 if (wHubChange & HUB_C_LOCAL_POWER)
375 ret = clear_hub_feature(hub, FS_C_HUB_LOCAL_POWER);
380 if (wHubChange & HUB_C_OVERCURRENT)
382 ret = clear_hub_feature(hub, FS_C_HUB_OVER_CURRENT);
390static int do_port_reset(HUB_DEV_T *hub,
int port)
395 uint16_t wPortStatus, wPortChange;
398 reset_time = PORT_RESET_TIME_MS;
400 for (retry = 0; retry < PORT_RESET_RETRY; retry++)
402 ret = set_port_feature(hub, FS_PORT_RESET, port);
407 while (
get_ticks() - t0 < (reset_time/10)+1)
411 ret = get_port_status(hub, port, &wPortStatus, &wPortChange);
414 USB_error(
"Failed to get Hub [%s] port %d status! (%d)\n", hub->pos_id, port, ret);
421 if (((wPortStatus & PORT_S_CONNECTION) == 0) ||
422 ((wPortStatus & (PORT_S_CONNECTION | PORT_S_ENABLE)) == (PORT_S_CONNECTION | PORT_S_ENABLE)))
424 clear_port_feature(hub, FS_C_PORT_ENABLE, port);
428 reset_time += PORT_RESET_RETRY_INC_MS;
430 USB_debug(
"HUB [%s] port %d - port reset failed!\n", hub->pos_id, port);
434static int port_connect_change(HUB_DEV_T *hub,
int port, uint16_t wPortStatus)
437 uint16_t wPortChange;
440 if (wPortStatus & PORT_S_CONNECTION)
448 disconnect_device(udev);
454 ret = do_port_reset(hub, port);
458 ret = get_port_status(hub, port, &wPortStatus, &wPortChange);
461 USB_error(
"Failed to get Hub [%s] port %d status! (%d)\n", hub->pos_id, port, ret);
464 printf(
"Hub [%s] port %d, status: 0x%x, change: 0x%x\n", hub->pos_id, port, wPortStatus, wPortChange);
469 udev = alloc_device();
474 udev->port_num = port;
476 if (wPortStatus & PORT_S_HIGH_SPEED)
477 udev->speed = SPEED_HIGH;
478 else if (wPortStatus & PORT_S_LOW_SPEED)
479 udev->speed = SPEED_LOW;
481 udev->speed = SPEED_FULL;
483 udev->hc_driver = hub->iface->udev->hc_driver;
485 ret = connect_device(udev);
488 USB_error(
"connect_device error! [%d]\n", ret);
500 disconnect_device(udev);
506static int port_status_change(HUB_DEV_T *hub,
int port)
508 uint16_t wPortStatus, wPortChange;
511 ret = get_port_status(hub, port, &wPortStatus, &wPortChange);
514 USB_error(
"Failed to get Hub [%s] port %d status! (%d)\n", hub->pos_id, port, ret);
517 printf(
"Hub [%s] port %d, status: 0x%x, change: 0x%x\n", hub->pos_id, port, wPortStatus, wPortChange);
519 if (wPortChange & PORT_C_CONNECTION)
521 ret = clear_port_feature(hub, FS_C_PORT_CONNECTION, port);
525 port_connect_change(hub, port, wPortStatus);
528 if (wPortChange & PORT_C_ENABLE)
530 ret = clear_port_feature(hub, FS_C_PORT_ENABLE, port);
535 if (wPortChange & PORT_C_SUSPEND)
537 ret = clear_port_feature(hub, FS_C_PORT_SUSPEND, port);
542 if (wPortChange & PORT_C_OVERCURRENT)
544 ret = clear_port_feature(hub, FS_C_PORT_OVER_CURRENT, port);
549 if (wPortChange & PORT_C_RESET)
551 ret = clear_port_feature(hub, FS_C_PORT_RESET, port);
558static volatile uint8_t _hub_polling_mutex = 0;
560static int hub_polling(
void)
564 int i, ret, port, change = 0;
566 if (_hub_polling_mutex)
569 _hub_polling_mutex = 1;
571 for (i = 0; i < MAX_HUB_DEVICE; i++)
573 if ((g_hub_dev[i].iface !=
NULL) && (g_hub_dev[i].sc_bitmap))
583 if (hub->sc_bitmap & 0x1)
584 hub_status_change(hub);
586 for (port = 1; port <= hub->bNbrPorts; port++)
588 if (hub->sc_bitmap & (1 << port))
590 ret = port_status_change(hub, port);
601 ret = usbh_int_xfer(utr);
604 USB_error(
"Failed to re-submit HUB [%s] interrupt-in request (%d)", hub->pos_id, ret);
609 _hub_polling_mutex = 0;
618void usbh_hub_init(
void)
620 memset((
char *)&g_hub_dev[0], 0,
sizeof(g_hub_dev));
621 usbh_register_driver(&hub_driver);
647 ret = ehci_driver.rthub_polling();
658 ret = ohci_driver.rthub_polling();
688 HUB_DEV_T *hub =
NULL;
691 for (i = 0; i < MAX_HUB_DEVICE; i++)
693 if ((g_hub_dev[i].iface !=
NULL) && (strcmp(g_hub_dev[i].pos_id, hub_id) == 0))
705 if ((udev->parent == hub) && (udev->port_num == port))
NuMicro peripheral access layer header file.
#define NULL
NULL pointer.
#define SYS_CSERVER_VERSION_Msk
#define HSUSBH_UPSCR_PP_Msk
#define HSUSBH_UPSCR_PO_Msk
#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.