priv->dev_descriptor.bNumConfigurations = 1;
priv->active_config = 1;
- if (priv->parent_dev == NULL) {
+ if (dev->parent_dev == NULL) {
usbi_err(ctx, "program assertion failed - HCD hub has no parent");
return LIBUSB_ERROR_NO_DEVICE;
}
- parent_priv = _device_priv(priv->parent_dev);
+ parent_priv = _device_priv(dev->parent_dev);
if (sscanf(parent_priv->path, "\\\\.\\PCI#VEN_%04x&DEV_%04x%*s", &vid, &pid) == 2) {
priv->dev_descriptor.idVendor = (uint16_t)vid;
priv->dev_descriptor.idProduct = (uint16_t)pid;
priv->port = port_number;
dev->port_number = port_number;
priv->depth = parent_priv->depth + 1;
- priv->parent_dev = parent_dev;
dev->parent_dev = parent_dev;
// If the device address is already set, we can stop here
session_id, dev->bus_number, dev->device_address);
priv = _device_priv(dev);
- if (priv->parent_dev != NULL) {
- if (priv->parent_dev != parent_dev) {
- usbi_err(ctx, "program assertion failed - existing device should share parent");
+ if ((parent_dev != NULL) && (dev->parent_dev != NULL)) {
+ if (dev->parent_dev != parent_dev) {
+ // It is possible for the actual parent device to not have existed at the
+ // time of enumeration, so the currently assigned parent may in fact be a
+ // grandparent. If the devices differ, we assume the "new" parent device
+ // is in fact closer to the device.
+ usbi_dbg("updating parent device [session %lX -> %lX]",
+ dev->parent_dev->session_data, parent_dev->session_data);
+ libusb_unref_device(dev->parent_dev);
+ dev->parent_dev = parent_dev;
} else {
// We hold a reference to parent_dev instance, but this device already
// has a parent_dev reference (only one per child)
uint8_t depth; // distance to HCD
uint8_t port; // port number on the hub
uint8_t active_config;
- struct libusb_device *parent_dev; // access to parent is required for usermode ops
struct windows_usb_api_backend const *apib;
char *path; // device interface path
int sub_api; // for WinUSB-like APIs
p->depth = 0;
p->port = 0;
- p->parent_dev = NULL;
p->path = NULL;
p->apib = &usb_api_backend[USB_API_UNSUPPORTED];
p->sub_api = SUB_API_NOTSET;