static void qemuDomainReAttachHostUsbDevices(struct qemud_driver *driver, const char *name, virDomainHostdevDefPtr *hostdevs, int nhostdevs) { int i; for (i = 0; i < nhostdevs; i++) { virDomainHostdevDefPtr hostdev = hostdevs[i]; usbDevice *usb, *tmp; const char *used_by = NULL; if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) continue; if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) continue; if (hostdev->missing) continue; usb = usbGetDevice(hostdev->source.subsys.u.usb.bus, hostdev->source.subsys.u.usb.device); if (!usb) { VIR_WARN("Unable to reattach USB device %03d.%03d on domain %s", hostdev->source.subsys.u.usb.bus, hostdev->source.subsys.u.usb.device, name); continue; } /* Delete only those USB devices which belongs * to domain @name because qemuProcessStart() might * have failed because USB device is already taken. * Therefore we want to steal only those devices from * the list which were taken by @name */ tmp = usbDeviceListFind(driver->activeUsbHostdevs, usb); usbFreeDevice(usb); if (!tmp) { VIR_WARN("Unable to find device %03d.%03d " "in list of active USB devices", hostdev->source.subsys.u.usb.bus, hostdev->source.subsys.u.usb.device); continue; } used_by = usbDeviceGetUsedBy(tmp); if (STREQ_NULLABLE(used_by, name)) { VIR_DEBUG("Removing %03d.%03d dom=%s from activeUsbHostdevs", hostdev->source.subsys.u.usb.bus, hostdev->source.subsys.u.usb.device, name); usbDeviceListDel(driver->activeUsbHostdevs, tmp); } } }
int qemuUpdateActiveUsbHostdevs(struct qemud_driver *driver, virDomainDefPtr def) { virDomainHostdevDefPtr hostdev = NULL; int i; if (!def->nhostdevs) return 0; for (i = 0; i < def->nhostdevs; i++) { usbDevice *usb = NULL; hostdev = def->hostdevs[i]; if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) continue; if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) continue; usb = usbGetDevice(hostdev->source.subsys.u.usb.bus, hostdev->source.subsys.u.usb.device); if (!usb) { VIR_WARN("Unable to reattach USB device %03d.%03d on domain %s", hostdev->source.subsys.u.usb.bus, hostdev->source.subsys.u.usb.device, def->name); continue; } usbDeviceSetUsedBy(usb, def->name); if (usbDeviceListAdd(driver->activeUsbHostdevs, usb) < 0) { usbFreeDevice(usb); return -1; } } return 0; }
static usbDeviceList * usbDeviceSearch(unsigned int vendor, unsigned int product, unsigned int bus, unsigned int devno, const char *vroot, unsigned int flags) { DIR *dir = NULL; bool found = false; char *ignore = NULL; struct dirent *de; usbDeviceList *list = NULL, *ret = NULL; usbDevice *usb; if (!(list = usbDeviceListNew())) goto cleanup; dir = opendir(USB_SYSFS "/devices"); if (!dir) { virReportSystemError(errno, _("Could not open directory %s"), USB_SYSFS "/devices"); goto cleanup; } while ((de = readdir(dir))) { unsigned int found_prod, found_vend, found_bus, found_devno; char *tmpstr = de->d_name; if (de->d_name[0] == '.' || strchr(de->d_name, ':')) continue; if (usbSysReadFile("idVendor", de->d_name, 16, &found_vend) < 0) goto cleanup; if (usbSysReadFile("idProduct", de->d_name, 16, &found_prod) < 0) goto cleanup; if (STRPREFIX(de->d_name, "usb")) tmpstr += 3; if (virStrToLong_ui(tmpstr, &ignore, 10, &found_bus) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Failed to parse dir name '%s'"), de->d_name); goto cleanup; } if (usbSysReadFile("devnum", de->d_name, 10, &found_devno) < 0) goto cleanup; if ((flags & USB_DEVICE_FIND_BY_VENDOR) && (found_prod != product || found_vend != vendor)) continue; if (flags & USB_DEVICE_FIND_BY_BUS) { if (found_bus != bus || found_devno != devno) continue; found = true; } usb = usbGetDevice(found_bus, found_devno, vroot); if (!usb) goto cleanup; if (usbDeviceListAdd(list, usb) < 0) { usbFreeDevice(usb); goto cleanup; } if (found) break; } ret = list; cleanup: if (dir) { int saved_errno = errno; closedir(dir); errno = saved_errno; } if (!ret) usbDeviceListFree(list); return ret; }