DM USB: introduce struct usb_devpath and releted functions

This patch introduce struct usb_devpath to indentify uniquely an USB
device, which is basic element for multiple hub support.

Tracked-On: #1434
Signed-off-by: Liang Yang <liang3.yang@intel.com>
Signed-off-by: Xiaoguang Wu <xiaoguang.wu@intel.com>
Acked-by: Yu Wang <yu1.wang@intel.com>
This commit is contained in:
Liang Yang 2018-10-09 23:44:03 +08:00 committed by Xie, Nanlin
parent 14bc961f03
commit e8f7b6fa74
4 changed files with 124 additions and 78 deletions

View File

@ -534,32 +534,32 @@ pci_xhci_native_usb_dev_conn_cb(void *hci_data, void *dev_data)
di = dev_data; di = dev_data;
/* print physical information about new device */ /* print physical information about new device */
UPRINTF(LDBG, "%04x:%04x %d-%d connecting.\r\n", UPRINTF(LDBG, "%04x:%04x %d-%s connecting.\r\n", di->vid, di->pid,
di->vid, di->pid, di->bus, di->port); di->path.bus, usb_dev_path(&di->path));
if (VPORT_STATE(xdev->port_map_tbl[di->bus][di->port]) == if (VPORT_STATE(xdev->port_map_tbl[di->path.bus]
VPORT_FREE) { [ROOTHUB_PORT(di->path)]) == VPORT_FREE) {
UPRINTF(LDBG, "%04x:%04x %d-%d doesn't belong to this" UPRINTF(LDBG, "%04x:%04x %d-%d doesn't belong to this"
" vm, bye.\r\n", di->vid, di->pid, " vm, bye.\r\n", di->vid, di->pid,
di->bus, di->port); di->path.bus, ROOTHUB_PORT(di->path));
goto errout; goto errout;
} }
UPRINTF(LDBG, "%04x:%04x %d-%s belong to this vm.\r\n", di->vid,
UPRINTF(LDBG, "%04x:%04x %d-%d belong to this vm.\r\n", di->vid, di->pid, di->path.bus, usb_dev_path(&di->path));
di->pid, di->bus, di->port);
port = pci_xhci_get_free_rh_port(xdev, di); port = pci_xhci_get_free_rh_port(xdev, di);
if (port < 0) { if (port < 0) {
UPRINTF(LFTL, "no free virtual port for native device %d-%d" UPRINTF(LFTL, "no free virtual port for native device %d-%s"
"\r\n", di->bus, di->port); "\r\n", di->path.bus, usb_dev_path(&di->path));
goto errout; goto errout;
} }
UPRINTF(LDBG, "%04X:%04X %d-%d is attached to virtual port %d.\r\n", UPRINTF(LDBG, "%04X:%04X %d-%s is attached to virtual port %d.\r\n",
di->vid, di->pid, di->bus, di->port, port); di->vid, di->pid, di->path.bus,
usb_dev_path(&di->path), port);
xdev->native_dev_info[di->bus][di->port] = *di; xdev->native_dev_info[di->path.bus][ROOTHUB_PORT(di->path)] = *di;
xdev->port_map_tbl[di->bus][di->port] = xdev->port_map_tbl[di->path.bus][ROOTHUB_PORT(di->path)] =
VPORT_NUM_STATE(VPORT_CONNECTED, port); VPORT_NUM_STATE(VPORT_CONNECTED, port);
/* TODO: should revisit in deeper level */ /* TODO: should revisit in deeper level */
@ -593,12 +593,13 @@ pci_xhci_native_usb_dev_disconn_cb(void *hci_data, void *dev_data)
assert(xdev->devices); assert(xdev->devices);
di = *((struct usb_native_devinfo *)dev_data); di = *((struct usb_native_devinfo *)dev_data);
if (!pci_xhci_is_valid_portnum(di.port)) { if (!pci_xhci_is_valid_portnum(ROOTHUB_PORT(di.path))) {
UPRINTF(LFTL, "invalid physical port %d\r\n", di.port); UPRINTF(LFTL, "invalid physical port %d\r\n",
ROOTHUB_PORT(di.path));
return -1; return -1;
} }
status = xdev->port_map_tbl[di.bus][di.port]; status = xdev->port_map_tbl[di.path.bus][ROOTHUB_PORT(di.path)];
for (port = 1; port <= XHCI_MAX_DEVS; ++port) { for (port = 1; port <= XHCI_MAX_DEVS; ++port) {
edev = xdev->devices[port]; edev = xdev->devices[port];
@ -606,7 +607,7 @@ pci_xhci_native_usb_dev_disconn_cb(void *hci_data, void *dev_data)
continue; continue;
udev = edev->dev_instance; udev = edev->dev_instance;
if (udev->info.port == di.port) if (ROOTHUB_PORT(udev->info.path) == ROOTHUB_PORT(di.path))
break; break;
} }
@ -620,14 +621,17 @@ pci_xhci_native_usb_dev_disconn_cb(void *hci_data, void *dev_data)
* cleared for future connecting. * cleared for future connecting.
*/ */
UPRINTF(LFTL, "disconnect VPORT_CONNECTED device: " UPRINTF(LFTL, "disconnect VPORT_CONNECTED device: "
"%d-%d vport %d\r\n", di.bus, di.port, "%d-%s vport %d\r\n", di.path.bus,
usb_dev_path(&di.path),
VPORT_NUM(status)); VPORT_NUM(status));
pci_xhci_disconnect_port(xdev, VPORT_NUM(status), 0); pci_xhci_disconnect_port(xdev, VPORT_NUM(status), 0);
xdev->port_map_tbl[di.bus][di.port] = VPORT_NUM_STATE( xdev->port_map_tbl[di.path.bus][ROOTHUB_PORT(di.path)]
VPORT_ASSIGNED, 0); = VPORT_NUM_STATE(VPORT_ASSIGNED, 0);
} }
UPRINTF(LFTL, "fail to find physical port %d\r\n", di.port); UPRINTF(LFTL, "fail to find physical port %d\r\n",
ROOTHUB_PORT(di.path));
return -1; return -1;
} }
@ -638,8 +642,8 @@ pci_xhci_native_usb_dev_disconn_cb(void *hci_data, void *dev_data)
assert(VPORT_STATE(status) == VPORT_EMULATED || assert(VPORT_STATE(status) == VPORT_EMULATED ||
VPORT_STATE(status) == VPORT_CONNECTED); VPORT_STATE(status) == VPORT_CONNECTED);
xdev->port_map_tbl[di.bus][di.port] = VPORT_NUM_STATE(VPORT_ASSIGNED, xdev->port_map_tbl[di.path.bus][ROOTHUB_PORT(di.path)] =
0); VPORT_NUM_STATE(VPORT_ASSIGNED, 0);
/* TODO: should revisit this in deeper level */ /* TODO: should revisit this in deeper level */
if (vm_get_suspend_mode() != VM_SUSPEND_NONE) { if (vm_get_suspend_mode() != VM_SUSPEND_NONE) {
@ -1539,11 +1543,12 @@ pci_xhci_cmd_disable_slot(struct pci_xhci_vdev *xdev, uint32_t slot)
xdev->slot_allocated[slot] = false; xdev->slot_allocated[slot] = false;
di = &udev->info; di = &udev->info;
xdev->port_map_tbl[di->bus][di->port] = xdev->port_map_tbl[di->path.bus][ROOTHUB_PORT(di->path)] =
VPORT_NUM_STATE(VPORT_ASSIGNED, 0); VPORT_NUM_STATE(VPORT_ASSIGNED, 0);
UPRINTF(LINF, "disable slot %d for native device %d-%d" UPRINTF(LINF, "disable slot %d for native device %d-%s"
"\r\n", slot, di->bus, di->port); "\r\n", slot, di->path.bus,
usb_dev_path(&di->path));
pci_xhci_dev_destroy(dev); pci_xhci_dev_destroy(dev);
} else } else
@ -1662,13 +1667,15 @@ pci_xhci_cmd_address_device(struct pci_xhci_vdev *xdev,
goto done; goto done;
} }
UPRINTF(LDBG, "create virtual device for %d-%d on virtual " UPRINTF(LDBG, "create virtual device for %d-%s on virtual "
"port %d\r\n", di->bus, di->port, rh_port); "port %d\r\n", di->path.bus,
usb_dev_path(&di->path), rh_port);
dev = pci_xhci_dev_create(xdev, di); dev = pci_xhci_dev_create(xdev, di);
if (!dev) { if (!dev) {
UPRINTF(LFTL, "fail to create device for %d-%d\r\n", UPRINTF(LFTL, "fail to create device for %d-%s\r\n",
di->bus, di->port); di->path.bus,
usb_dev_path(&di->path));
goto done; goto done;
} }

View File

@ -42,14 +42,15 @@ usb_dev_scan_dev()
ldev = devlist[i]; ldev = devlist[i];
memset(&di, 0, sizeof(di)); memset(&di, 0, sizeof(di));
di.bus = libusb_get_bus_number(ldev); di.path.bus = libusb_get_bus_number(ldev);
di.port = libusb_get_port_number(ldev); di.path.depth = libusb_get_port_numbers(ldev, di.path.path,
USB_MAX_TIERS);
di.speed = libusb_get_device_speed(ldev); di.speed = libusb_get_device_speed(ldev);
rc = libusb_get_device_descriptor(ldev, &d); rc = libusb_get_device_descriptor(ldev, &d);
if (rc) { if (rc) {
UPRINTF(LWRN, "fail to get descriptor for %d-%d\r\n", UPRINTF(LWRN, "fail to get descriptor for %d-%s\r\n",
di.bus, di.port); di.path.bus, usb_dev_path(&di.path));
continue; continue;
} }
@ -58,7 +59,7 @@ usb_dev_scan_dev()
di.bcd = d.bcdUSB; di.bcd = d.bcdUSB;
di.priv_data = ldev; di.priv_data = ldev;
if (di.port == 0) if (ROOTHUB_PORT(di.path) == 0)
continue; continue;
if (d.bDeviceClass == LIBUSB_CLASS_HUB) if (d.bDeviceClass == LIBUSB_CLASS_HUB)
continue; continue;
@ -453,19 +454,19 @@ static int
usb_dev_native_toggle_if(struct usb_dev *udev, int claim) usb_dev_native_toggle_if(struct usb_dev *udev, int claim)
{ {
struct libusb_config_descriptor *config; struct libusb_config_descriptor *config;
uint8_t b, p, c, i; struct usb_devpath *path;
uint8_t c, i;
int rc = 0, r; int rc = 0, r;
assert(udev); assert(udev);
assert(udev->handle); assert(udev->handle);
assert(claim == 1 || claim == 0); assert(claim == 1 || claim == 0);
b = udev->info.bus; path = &udev->info.path;
p = udev->info.port;
r = libusb_get_active_config_descriptor(udev->info.priv_data, &config); r = libusb_get_active_config_descriptor(udev->info.priv_data, &config);
if (r) { if (r) {
UPRINTF(LWRN, "%d-%d: can't get config\r\n", b, p); UPRINTF(LWRN, "%d-%s: can't get config\r\n", path->bus,
usb_dev_path(path));
return -1; return -1;
} }
@ -485,14 +486,16 @@ usb_dev_native_toggle_if(struct usb_dev *udev, int claim)
} }
if (r) { if (r) {
rc = -1; rc = -1;
UPRINTF(LWRN, "%d-%d:%d.%d can't %s if, r %d\r\n", b, UPRINTF(LWRN, "%d-%s:%d.%d can't %s if, r %d\r\n",
p, c, i, claim == 1 ? "claim" : path->bus, usb_dev_path(path), c, i,
"release", r); claim == 1 ? "claim" : "release", r);
} }
} }
if (rc) if (rc)
UPRINTF(LWRN, "%d-%d fail to %s rc %d\r\n", b, p, UPRINTF(LWRN, "%d-%s fail to %s rc %d\r\n", path->bus,
claim == 1 ? "claim" : "release", rc); usb_dev_path(path), claim == 1 ? "claim" :
"release", rc);
libusb_free_config_descriptor(config); libusb_free_config_descriptor(config);
return rc; return rc;
} }
@ -501,19 +504,19 @@ static int
usb_dev_native_toggle_if_drivers(struct usb_dev *udev, int attach) usb_dev_native_toggle_if_drivers(struct usb_dev *udev, int attach)
{ {
struct libusb_config_descriptor *config; struct libusb_config_descriptor *config;
uint8_t b, p, c, i; struct usb_devpath *path;
uint8_t c, i;
int rc = 0, r; int rc = 0, r;
assert(udev); assert(udev);
assert(udev->handle); assert(udev->handle);
assert(attach == 1 || attach == 0); assert(attach == 1 || attach == 0);
b = udev->info.bus; path = &udev->info.path;
p = udev->info.port;
r = libusb_get_active_config_descriptor(udev->info.priv_data, &config); r = libusb_get_active_config_descriptor(udev->info.priv_data, &config);
if (r) { if (r) {
UPRINTF(LWRN, "%d-%d: can't get config\r\n", b, p); UPRINTF(LWRN, "%d-%s: can't get config\r\n", path->bus,
usb_dev_path(path));
return -1; return -1;
} }
@ -531,14 +534,16 @@ usb_dev_native_toggle_if_drivers(struct usb_dev *udev, int attach)
if (r) { if (r) {
rc = -1; rc = -1;
UPRINTF(LWRN, "%d-%d:%d.%d can't %stach if driver, r %d" UPRINTF(LWRN, "%d-%s:%d.%d can't %stach if driver, r %d"
"\r\n", b, p, c, i, attach == 1 ? "at" : "\r\n", path->bus, usb_dev_path(path),
"de", r); c, i, attach == 1 ? "at" : "de", r);
} }
} }
if (rc) if (rc)
UPRINTF(LWRN, "%d-%d fail to %s rc %d\r\n", b, p, UPRINTF(LWRN, "%d-%s fail to %s rc %d\r\n", path->bus,
attach == 1 ? "attach" : "detach", rc); usb_dev_path(path), attach == 1 ? "attach" :
"detach", rc);
libusb_free_config_descriptor(config); libusb_free_config_descriptor(config);
return rc; return rc;
} }
@ -591,8 +596,8 @@ err1:
usb_dev_native_toggle_if(udev, 0); usb_dev_native_toggle_if(udev, 0);
libusb_free_config_descriptor(cfg); libusb_free_config_descriptor(cfg);
err2: err2:
UPRINTF(LWRN, "%d-%d: fail to set config\r\n", udev->info.bus, UPRINTF(LWRN, "%d-%s: fail to set config\r\n", udev->info.path.bus,
udev->info.port); usb_dev_path(&udev->info.path));
xfer->status = USB_ERR_STALLED; xfer->status = USB_ERR_STALLED;
} }
@ -607,8 +612,8 @@ usb_dev_set_if(struct usb_dev *udev, int iface, int alt, struct usb_data_xfer
if (iface >= USB_NUM_INTERFACE) if (iface >= USB_NUM_INTERFACE)
goto errout; goto errout;
UPRINTF(LDBG, "%d-%d set if, iface %d alt %d\r\n", udev->info.bus, UPRINTF(LDBG, "%d-%s set if, iface %d alt %d\r\n", udev->info.path.bus,
udev->info.port, iface, alt); usb_dev_path(&udev->info.path), iface, alt);
if (libusb_set_interface_alt_setting(udev->handle, iface, alt)) if (libusb_set_interface_alt_setting(udev->handle, iface, alt))
goto errout; goto errout;
@ -624,8 +629,11 @@ usb_dev_set_if(struct usb_dev *udev, int iface, int alt, struct usb_data_xfer
errout: errout:
xfer->status = USB_ERR_STALLED; xfer->status = USB_ERR_STALLED;
UPRINTF(LDBG, "%d-%d fail to set if, iface %d alt %d\r\n", UPRINTF(LDBG, "%d-%s fail to set if, iface %d alt %d\r\n",
udev->info.bus, udev->info.port, iface, alt); udev->info.path.bus,
usb_dev_path(&udev->info.path),
iface,
alt);
} }
static struct usb_data_xfer_block * static struct usb_data_xfer_block *
@ -916,10 +924,11 @@ usb_dev_init(void *pdata, char *opt)
di = pdata; di = pdata;
libusb_get_device_descriptor(di->priv_data, &desc); libusb_get_device_descriptor(di->priv_data, &desc);
UPRINTF(LINF, "Found USB device: %d-%d\r\nPID(0x%X), VID(0x%X) CLASS" UPRINTF(LINF, "Found USB device: %d-%s\r\nPID(0x%X), VID(0x%X) CLASS"
"(0x%X) SUBCLASS(0x%X) BCD(0x%X) SPEED(%d)\r\n", "(0x%X) SUBCLASS(0x%X) BCD(0x%X) SPEED(%d)\r\n",
di->bus, di->port, di->pid, di->vid, desc.bDeviceClass, di->path.bus, usb_dev_path(&di->path), di->pid,
desc.bDeviceSubClass, di->bcd, di->speed); di->vid, desc.bDeviceClass, desc.bDeviceSubClass,
di->bcd, di->speed);
/* allocate and populate udev */ /* allocate and populate udev */
udev = calloc(1, sizeof(struct usb_dev)); udev = calloc(1, sizeof(struct usb_dev));
@ -927,7 +936,7 @@ usb_dev_init(void *pdata, char *opt)
goto errout; goto errout;
/* this is a root hub */ /* this is a root hub */
if (di->port == 0) if (ROOTHUB_PORT(di->path) == 0)
goto errout; goto errout;
switch (desc.bcdUSB) { switch (desc.bcdUSB) {
@ -1016,12 +1025,12 @@ usb_dev_info(void *pdata, int type, void *value, int size)
pv = &udev->info.speed; pv = &udev->info.speed;
break; break;
case USB_INFO_BUS: case USB_INFO_BUS:
sz = sizeof(udev->info.bus); sz = sizeof(udev->info.path.bus);
pv = &udev->info.bus; pv = &udev->info.path.bus;
break; break;
case USB_INFO_PORT: case USB_INFO_PORT:
sz = sizeof(udev->info.port); sz = sizeof(udev->info.path.path[0]);
pv = &udev->info.port; pv = &udev->info.path.path[0];
break; break;
case USB_INFO_VID: case USB_INFO_VID:
sz = sizeof(udev->info.vid); sz = sizeof(udev->info.vid);
@ -1069,9 +1078,10 @@ usb_dev_native_sys_conn_cb(struct libusb_context *ctx, struct libusb_device
} }
libusb_get_device_descriptor(ldev, &d); libusb_get_device_descriptor(ldev, &d);
di.bus = libusb_get_bus_number(ldev); di.path.bus = libusb_get_bus_number(ldev);
di.path.depth = libusb_get_port_numbers(ldev, di.path.path,
USB_MAX_TIERS);
di.speed = libusb_get_device_speed(ldev); di.speed = libusb_get_device_speed(ldev);
di.port = libusb_get_port_number(ldev);
di.pid = d.idProduct; di.pid = d.idProduct;
di.vid = d.idVendor; di.vid = d.idVendor;
di.bcd = d.bcdUSB; di.bcd = d.bcdUSB;
@ -1101,11 +1111,11 @@ usb_dev_native_sys_disconn_cb(struct libusb_context *ctx, struct libusb_device
} }
libusb_get_device_descriptor(ldev, &d); libusb_get_device_descriptor(ldev, &d);
di.bus = libusb_get_bus_number(ldev); di.path.bus = libusb_get_bus_number(ldev);
di.speed = libusb_get_device_speed(ldev); di.speed = libusb_get_device_speed(ldev);
di.path.depth = libusb_get_port_numbers(ldev, di.path.path,
USB_MAX_TIERS);
/* FIXME: * should use libusb_get_port_numbers here */
di.port = libusb_get_port_number(ldev);
di.pid = d.idProduct; di.pid = d.idProduct;
di.vid = d.idVendor; di.vid = d.idVendor;
di.bcd = d.bcdUSB; di.bcd = d.bcdUSB;

View File

@ -243,3 +243,24 @@ void usb_parse_log_level(char level)
usb_set_log_level(LFTL); usb_set_log_level(LFTL);
} }
} }
char *
usb_dev_path(struct usb_devpath *path)
{
static char output[sizeof("01.02.03.04.05.06.07")+1];
int i, r, n;
if (!path)
return NULL;
r = n = sizeof(output);
r -= snprintf(output, n, "%d", path->path[0]);
for (i = 1; i < path->depth; i++) {
r -= snprintf(output + n - r, r, ".%d", path->path[i]);
if (r < 0)
return NULL;
}
return output;
}

View File

@ -84,6 +84,8 @@ enum usb_xfer_blk_stat {
USB_XFER_BLK_HANDLED USB_XFER_BLK_HANDLED
}; };
#define USB_MAX_TIERS 7
struct usb_hci; struct usb_hci;
struct usb_device_request; struct usb_device_request;
struct usb_data_xfer; struct usb_data_xfer;
@ -163,13 +165,19 @@ struct usb_data_xfer {
pthread_mutex_t mtx; pthread_mutex_t mtx;
}; };
struct usb_devpath {
uint8_t bus;
uint8_t depth;
uint8_t path[USB_MAX_TIERS];
};
#define ROOTHUB_PORT(x) ((x).path[0])
struct usb_native_devinfo { struct usb_native_devinfo {
int speed; int speed;
uint8_t bus;
uint8_t port;
uint16_t bcd; uint16_t bcd;
uint16_t pid; uint16_t pid;
uint16_t vid; uint16_t vid;
struct usb_devpath path;
void *priv_data; void *priv_data;
}; };
@ -239,5 +247,5 @@ struct usb_data_xfer_block *usb_data_xfer_append(struct usb_data_xfer *xfer,
int blen, int blen,
void *hci_data, void *hci_data,
int ccs); int ccs);
char *usb_dev_path(struct usb_devpath *path);
#endif /* _USB_CORE_H_ */ #endif /* _USB_CORE_H_ */