DM USB: add support for multi-layers hubs

This patch is used to support emulation of multiple layers of hubs
under Flat Mode.

Tracked-On: #1434
Signed-off-by: Xiaoguang Wu <xiaoguang.wu@intel.com>
Signed-off-by: Liang Yang <liang3.yang@intel.com>
Acked-by: Yu Wang <yu1.wang@intel.com>
This commit is contained in:
Xiaoguang Wu 2018-10-10 12:02:16 +08:00 committed by Xie, Nanlin
parent f533a07af1
commit 6b2a18a866
1 changed files with 54 additions and 42 deletions

View File

@ -59,7 +59,7 @@ usb_get_native_devinfo(struct libusb_device *ldev,
if (info->type == USB_TYPE_EXTHUB) {
info->maxchild = usb_get_hub_port_num(&info->path);
if (info->maxchild < 0)
UPRINTF(LFTL, "fail to get count of numbers of hub"
UPRINTF(LDBG, "fail to get count of numbers of hub"
" %d-%s\r\n", info->path.bus,
usb_dev_path(&info->path));
}
@ -74,15 +74,61 @@ usb_get_native_devinfo(struct libusb_device *ldev,
return true;
}
static void
internal_scan(struct libusb_device ***list, int list_sz, int depth,
int8_t *visit, int visit_sz)
{
int i;
struct libusb_device **devlist;
struct usb_native_devinfo di;
assert(visit);
assert(list);
assert(visit_sz >= list_sz);
devlist = *list;
if (depth >= USB_MAX_TIERS) {
UPRINTF(LFTL, "max hub layers(7) reached, stop scan\r\n");
return;
}
/* The scanning must be done according to the order from depth 1 to
* USB_MAX_TIERS. The reason is if hub exist in the USB device tree,
* the ports of hub should be assigned first, and then its child
* is scanned. The reason is external hub ports are dyanmically
* assigned.
*/
/* scan devices and assign ports if hub is found */
for (i = 0; i < list_sz; i++) {
if (usb_get_native_devinfo(devlist[i], &di, NULL) == false)
continue;
if (!visit[i] && di.path.depth == depth &&
ROOTHUB_PORT(di.path)) {
visit[i] = 1;
if (g_ctx.conn_cb)
g_ctx.conn_cb(g_ctx.hci_data, &di);
}
}
/* do the scanning in deeper depth */
for (i = 0; i < list_sz; i++) {
if (usb_get_native_devinfo(devlist[i], &di, NULL) == false)
continue;
if (!visit[i] && di.path.depth > depth && ROOTHUB_PORT(di.path))
internal_scan(list, list_sz, depth + 1, visit,
visit_sz);
}
}
static int
usb_dev_scan_dev()
{
int i, num_devs;
int num_devs;
struct libusb_device **devlist;
struct libusb_device *ldev;
struct usb_native_devinfo di;
struct libusb_device_descriptor d;
bool ret;
int8_t visit[USB_MAX_DEVICES];
if (!g_ctx.libusb_ctx)
return -1;
@ -91,42 +137,8 @@ usb_dev_scan_dev()
if (num_devs < 0)
return -1;
/* first pass, process external hubs */
for (i = 0; i < num_devs; ++i) {
ldev = devlist[i];
ret = usb_get_native_devinfo(ldev, &di, &d);
if (ret == false)
continue;
if (ROOTHUB_PORT(di.path) == 0)
continue;
if (di.type != USB_TYPE_EXTHUB)
continue;
if (g_ctx.conn_cb)
g_ctx.conn_cb(g_ctx.hci_data, &di);
}
/* second pass, process devices */
for (i = 0; i < num_devs; ++i) {
ldev = devlist[i];
ret = usb_get_native_devinfo(ldev, &di, &d);
if (ret == false)
continue;
if (ROOTHUB_PORT(di.path) == 0)
continue;
if (di.type == USB_TYPE_EXTHUB)
continue;
if (g_ctx.conn_cb)
g_ctx.conn_cb(g_ctx.hci_data, &di);
}
memset(visit, 0, sizeof(visit));
internal_scan(&devlist, num_devs, 1, visit, USB_MAX_DEVICES);
return num_devs;
}