}
}
+static void
+virDomainHostdevSubsysUSBClear(virDomainHostdevSubsysUSB *usbsrc)
+{
+ if (!usbsrc)
+ return;
+
+ VIR_FREE(usbsrc->port);
+}
+
static void
virDomainHostdevDefClear(virDomainHostdevDef *def)
g_clear_pointer(&def->source.subsys.u.pci.origstates, virBitmapFree);
break;
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
+ virDomainHostdevSubsysUSBClear(&def->source.subsys.u.usb);
+ break;
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV:
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST:
break;
}
if ((addressNode = virXPathNode("./address", ctxt))) {
+ bool foundDevice = false;
+ bool foundPort = false;
+ g_autofree char *port = NULL;
+ int rc = -1;
+
if (virXMLPropUInt(addressNode, "bus", 0,
- VIR_XML_PROP_REQUIRED, &usbsrc->bus) < 0)
+ VIR_XML_PROP_REQUIRED, &usbsrc->bus) < 0) {
return -1;
+ }
- if (virXMLPropUInt(addressNode, "device", 0,
- VIR_XML_PROP_REQUIRED, &usbsrc->device) < 0)
+ rc = virXMLPropUInt(addressNode, "device", 0,
+ VIR_XML_PROP_NONE, &usbsrc->device);
+ if (rc < 0)
return -1;
+ else if (rc > 0)
+ foundDevice = true;
+
+ port = virXMLPropString(addressNode, "port");
+ if (port && *port) {
+ usbsrc->port = g_steal_pointer(&port);
+ foundPort = true;
+ }
+
+ if (!foundDevice && !foundPort) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("usb address needs either device id or port"));
+ return -1;
+ } else if (foundDevice && foundPort) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("found both device id and port in usb address (ambiguous setting)"));
+ return -1;
+ }
}
return 0;
virDomainHostdevSubsysUSB *first_usbsrc = &first->source.subsys.u.usb;
virDomainHostdevSubsysUSB *second_usbsrc = &second->source.subsys.u.usb;
- if (first_usbsrc->bus && first_usbsrc->device) {
- /* specified by bus location on host */
+ if (first_usbsrc->bus && first_usbsrc->port) {
+ /* specified by bus and port on host */
+ if (first_usbsrc->bus == second_usbsrc->bus &&
+ STREQ_NULLABLE(first_usbsrc->port, second_usbsrc->port))
+ return 1;
+ } else if (first_usbsrc->bus && first_usbsrc->device) {
+ /* specified by bus and device id on host */
if (first_usbsrc->bus == second_usbsrc->bus &&
first_usbsrc->device == second_usbsrc->device)
return 1;
virBufferAsprintf(&sourceChildBuf, "<product id='0x%.4x'/>\n", usbsrc->product);
}
- if (usbsrc->bus || usbsrc->device)
+ if (usbsrc->bus && usbsrc->port) {
+ virBufferAsprintf(&sourceChildBuf, "<address %sbus='%d' port='%s'/>\n",
+ includeTypeInAddr ? "type='usb' " : "",
+ usbsrc->bus, usbsrc->port);
+ } else if (usbsrc->bus || usbsrc->device) {
virBufferAsprintf(&sourceChildBuf, "<address %sbus='%d' device='%d'/>\n",
includeTypeInAddr ? "type='usb' " : "",
usbsrc->bus, usbsrc->device);
+ }
virXMLFormatElement(buf, "source", &sourceAttrBuf, &sourceChildBuf);
}
unsigned vendor = usbsrc->vendor;
unsigned product = usbsrc->product;
unsigned bus = usbsrc->bus;
+ const char *port = usbsrc->port;
unsigned device = usbsrc->device;
g_autoptr(virUSBDeviceList) devs = NULL;
int rc;
- rc = virUSBDeviceFind(vendor, product, bus, device, NULL, NULL,
+ rc = virUSBDeviceFind(vendor, product, bus, device, port, NULL,
mandatory, flags, &devs);
if (rc < 0)
return -1;
unsigned vendor = usbsrc->vendor;
unsigned bus = usbsrc->bus;
unsigned device = usbsrc->device;
+ const char *port = usbsrc->port;
bool autoAddress = usbsrc->autoAddress;
unsigned int flags = 0;
int rc;
flags |= USB_DEVICE_FIND_BY_VENDOR;
if (device)
flags |= USB_DEVICE_FIND_BY_DEVICE;
+ if (port)
+ flags |= USB_DEVICE_FIND_BY_PORT;
/* Rule out invalid cases. */
- if (vendor && device) {
+ if (vendor && device && port) {
virReportError(VIR_ERR_OPERATION_FAILED, "%s",
- _("Cannot match USB device on vendor/product and bus/device at once"));
- } else if (!vendor && !device) {
+ _("Cannot match USB device on vendor/product, bus/device, and bus/port at once."));
+ } else if (device && port) {
virReportError(VIR_ERR_OPERATION_FAILED, "%s",
- _("No matching fields for USB device found, vendor/product or bus/device required"));
+ _("Cannot match USB device on bus/device and bus/port at once."));
+ } else if (!vendor && !device && !port) {
+ virReportError(VIR_ERR_OPERATION_FAILED, "%s",
+ _("No matching fields for USB device found. Vendor/product, bus/device, or bus/port required."));
return -1;
}