Previously, only VID/PID and bus/device matching were supported. Neither
of these provide a stable and persistent way of assigning a guest a
specific host device out of several with the same VID and PID, as device
numbers change on every enumeration.
Add a third method of matching, bus/port, which allows a specific port on
the host to be specified using the dotted notation found in Linux's
"devpath" sysfs attribute.
---
src/conf/domain_conf.c | 36 ++++-
src/conf/domain_conf.h | 2 +
src/libvirt_private.syms | 2 -
src/util/virhostdev.c | 126 ++++++++--------
src/util/virusb.c | 160 ++++++++-------------
src/util/virusb.h | 23 ++-
tests/virusbtest.c | 124 ++++++++++------
.../sys_bus_usb/devices/1-1.5.3.1/devpath | 1 +
.../sys_bus_usb/devices/1-1.5.3.3/devpath | 1 +
.../sys_bus_usb/devices/1-1.5.3/devpath | 1 +
.../sys_bus_usb/devices/1-1.5.4/devpath | 1 +
.../sys_bus_usb/devices/1-1.5.5/devpath | 1 +
.../sys_bus_usb/devices/1-1.5.6/devpath | 1 +
.../sys_bus_usb/devices/1-1.5/devpath | 1 +
.../sys_bus_usb/devices/1-1.6/devpath | 1 +
.../virusbtestdata/sys_bus_usb/devices/1-1/devpath | 1 +
.../sys_bus_usb/devices/2-1.2/devpath | 1 +
.../virusbtestdata/sys_bus_usb/devices/2-1/devpath | 1 +
.../sys_bus_usb/devices/usb1/devpath | 1 +
.../sys_bus_usb/devices/usb2/devpath | 1 +
.../sys_bus_usb/devices/usb3/devpath | 1 +
.../sys_bus_usb/devices/usb4/devpath | 1 +
22 files changed, 266 insertions(+), 222 deletions(-)
create mode 100644 tests/virusbtestdata/sys_bus_usb/devices/1-1.5.3.1/devpath
create mode 100644 tests/virusbtestdata/sys_bus_usb/devices/1-1.5.3.3/devpath
create mode 100644 tests/virusbtestdata/sys_bus_usb/devices/1-1.5.3/devpath
create mode 100644 tests/virusbtestdata/sys_bus_usb/devices/1-1.5.4/devpath
create mode 100644 tests/virusbtestdata/sys_bus_usb/devices/1-1.5.5/devpath
create mode 100644 tests/virusbtestdata/sys_bus_usb/devices/1-1.5.6/devpath
create mode 100644 tests/virusbtestdata/sys_bus_usb/devices/1-1.5/devpath
create mode 100644 tests/virusbtestdata/sys_bus_usb/devices/1-1.6/devpath
create mode 100644 tests/virusbtestdata/sys_bus_usb/devices/1-1/devpath
create mode 100644 tests/virusbtestdata/sys_bus_usb/devices/2-1.2/devpath
create mode 100644 tests/virusbtestdata/sys_bus_usb/devices/2-1/devpath
create mode 100644 tests/virusbtestdata/sys_bus_usb/devices/usb1/devpath
create mode 100644 tests/virusbtestdata/sys_bus_usb/devices/usb2/devpath
create mode 100644 tests/virusbtestdata/sys_bus_usb/devices/usb3/devpath
create mode 100644 tests/virusbtestdata/sys_bus_usb/devices/usb4/devpath
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 9f7b906..a587cc2 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -5531,7 +5531,8 @@ virDomainHostdevSubsysUSBDefParseXML(xmlNodePtr node,
goto out;
}
} else if (xmlStrEqual(cur->name, BAD_CAST "address")) {
- char *bus, *device;
+ char *bus, *device, *port;
+ bool dev_or_port = false;
bus = virXMLPropString(cur, "bus");
if (bus) {
@@ -5557,10 +5558,24 @@ virDomainHostdevSubsysUSBDefParseXML(xmlNodePtr node,
VIR_FREE(device);
goto out;
}
+ dev_or_port = true;
VIR_FREE(device);
- } else {
+ }
+
+ port = virXMLPropString(cur, "port");
+ if (port) {
+ if (*port) {
+ usbsrc->port = port;
+ dev_or_port = true;
+ } else {
+ VIR_FREE(port);
+ }
+ }
+
+ if (!dev_or_port) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("usb address needs device id"));
+ _("usb address needs either device id "
+ "or port"));
goto out;
}
} else {
@@ -20326,10 +20341,17 @@ virDomainHostdevDefFormatSubsys(virBufferPtr buf,
virBufferAsprintf(buf, "<vendor id='0x%.4x'/>\n",
usbsrc->vendor);
virBufferAsprintf(buf, "<product id='0x%.4x'/>\n",
usbsrc->product);
}
- if (usbsrc->bus || usbsrc->device) {
- virBufferAsprintf(buf, "<address %sbus='%d'
device='%d'/>\n",
- includeTypeInAddr ? "type='usb' " :
"",
- usbsrc->bus, usbsrc->device);
+ if (usbsrc->bus || usbsrc->device || usbsrc->port) {
+ virBufferAddLit(buf, "<address");
+ if (includeTypeInAddr)
+ virBufferAddLit(buf, " type='usb'");
+ if (usbsrc->bus)
+ virBufferAsprintf(buf, " bus='%u'", usbsrc->bus);
+ if (usbsrc->device)
+ virBufferAsprintf(buf, " device='%u'",
usbsrc->device);
+ if (usbsrc->port)
+ virBufferAsprintf(buf, " port='%s'", usbsrc->port);
+ virBufferAddLit(buf, "/>\n");
}
break;
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index ba0ad5f..91bd621 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -317,6 +317,8 @@ VIR_ENUM_DECL(virDomainHostdevSubsysSCSIProtocol)
typedef struct _virDomainHostdevSubsysUSB virDomainHostdevSubsysUSB;
typedef virDomainHostdevSubsysUSB *virDomainHostdevSubsysUSBPtr;
struct _virDomainHostdevSubsysUSB {
+ char *port;
+
bool autoAddress; /* bus/device were filled automatically based
on vendor/product */
unsigned bus;
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index ccb4c5e..d412eac 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2511,8 +2511,6 @@ virURIResolveAlias;
# util/virusb.h
virUSBDeviceFileIterate;
virUSBDeviceFind;
-virUSBDeviceFindByBus;
-virUSBDeviceFindByVendor;
virUSBDeviceFree;
virUSBDeviceGetBus;
virUSBDeviceGetDevno;
diff --git a/src/util/virhostdev.c b/src/util/virhostdev.c
index 9b5ca6f..e809c97 100644
--- a/src/util/virhostdev.c
+++ b/src/util/virhostdev.c
@@ -1179,89 +1179,95 @@ virHostdevMarkUSBDevices(virHostdevManagerPtr mgr,
static int
+virHostdevFindUSBDeviceWithFlags(virDomainHostdevDefPtr hostdev,
+ bool mandatory,
+ unsigned int flags,
+ virUSBDevicePtr *usb)
+{
+ virDomainHostdevSubsysUSBPtr usbsrc = &hostdev->source.subsys.u.usb;
+ unsigned vendor = usbsrc->vendor;
+ unsigned product = usbsrc->product;
+ unsigned bus = usbsrc->bus;
+ char *port = usbsrc->port;
+ unsigned device = usbsrc->device;
+ virUSBDeviceListPtr devs;
+ int rc;
+
+ rc = virUSBDeviceFind(vendor, product, bus, device, port, NULL,
+ mandatory, flags, &devs);
+ if (rc < 0)
+ return -1;
+
+ if (rc == 1) {
+ *usb = virUSBDeviceListGet(devs, 0);
+ virUSBDeviceListSteal(devs, *usb);
+ }
+ virObjectUnref(devs);
+
+ if (rc > 1) {
+ virReportError(VIR_ERR_OPERATION_FAILED,
+ _("Multiple USB devices for %x:%x, "
+ "use <address> to specify one"),
+ vendor, product);
+ return -1;
+ }
+
+ return rc;
+}
+
+static int
virHostdevFindUSBDevice(virDomainHostdevDefPtr hostdev,
bool mandatory,
virUSBDevicePtr *usb)
{
virDomainHostdevSubsysUSBPtr usbsrc = &hostdev->source.subsys.u.usb;
unsigned vendor = usbsrc->vendor;
- unsigned product = usbsrc->product;
unsigned bus = usbsrc->bus;
unsigned device = usbsrc->device;
+ char *port = usbsrc->port;
bool autoAddress = usbsrc->autoAddress;
+ unsigned int flags = 0;
int rc;
*usb = NULL;
- if (vendor && bus) {
- rc = virUSBDeviceFind(vendor, product, bus, device,
- NULL,
- autoAddress ? false : mandatory,
- usb);
- if (rc < 0) {
- return -1;
- } else if (!autoAddress) {
- goto out;
- } else {
- VIR_INFO("USB device %x:%x could not be found at previous"
- " address (bus:%u device:%u)",
- vendor, product, bus, device);
- }
- }
+ /* First attempt, matching on all known fields. */
+ if (vendor)
+ flags |= USB_DEVICE_FIND_BY_VENDOR;
+ if (device)
+ flags |= USB_DEVICE_FIND_BY_DEVICE;
+ if (port)
+ flags |= USB_DEVICE_FIND_BY_PORT;
+
+ rc = virHostdevFindUSBDeviceWithFlags(hostdev,
+ autoAddress ? false : mandatory,
+ flags, usb);
+ if (rc < 0)
+ return -1;
- /* When vendor is specified, its USB address is either unspecified or the
- * device could not be found at the USB device where it had been
- * automatically found before.
- */
- if (vendor) {
- virUSBDeviceListPtr devs;
+ if (rc != 1 && autoAddress) {
+ VIR_INFO("USB device could not be found at previous address "
+ "(bus:%u device:%u)", bus, device);
- rc = virUSBDeviceFindByVendor(vendor, product, NULL, mandatory, &devs);
- if (rc < 0)
- return -1;
+ /* Second attempt, for when the device number has changed. */
+ flags &= ~((unsigned int) USB_DEVICE_FIND_BY_DEVICE);
+ usbsrc->device = 0;
- if (rc == 1) {
- *usb = virUSBDeviceListGet(devs, 0);
- virUSBDeviceListSteal(devs, *usb);
- }
- virObjectUnref(devs);
-
- if (rc == 0) {
- goto out;
- } else if (rc > 1) {
- if (autoAddress) {
- virReportError(VIR_ERR_OPERATION_FAILED,
- _("Multiple USB devices for %x:%x were found,"
- " but none of them is at bus:%u device:%u"),
- vendor, product, bus, device);
- } else {
- virReportError(VIR_ERR_OPERATION_FAILED,
- _("Multiple USB devices for %x:%x, "
- "use <address> to specify one"),
- vendor, product);
- }
+ rc = virHostdevFindUSBDeviceWithFlags(hostdev, mandatory,
+ flags, usb);
+
+ if (rc < 0)
return -1;
- }
+ }
+ if (!*usb) {
+ hostdev->missing = true;
+ } else if (!usbsrc->bus || !usbsrc->device) {
usbsrc->bus = virUSBDeviceGetBus(*usb);
usbsrc->device = virUSBDeviceGetDevno(*usb);
usbsrc->autoAddress = true;
-
- if (autoAddress) {
- VIR_INFO("USB device %x:%x found at bus:%u device:%u (moved"
- " from bus:%u device:%u)",
- vendor, product,
- usbsrc->bus, usbsrc->device,
- bus, device);
- }
- } else if (!vendor && bus) {
- if (virUSBDeviceFindByBus(bus, device, NULL, mandatory, usb) < 0)
- return -1;
}
- out:
- if (!*usb)
- hostdev->missing = true;
return 0;
}
diff --git a/src/util/virusb.c b/src/util/virusb.c
index 6a001a7..2e15849 100644
--- a/src/util/virusb.c
+++ b/src/util/virusb.c
@@ -68,12 +68,6 @@ struct _virUSBDeviceList {
virUSBDevicePtr *devs;
};
-typedef enum {
- USB_DEVICE_ALL = 0,
- USB_DEVICE_FIND_BY_VENDOR = 1 << 0,
- USB_DEVICE_FIND_BY_BUS = 1 << 1,
-} virUSBDeviceFindFlags;
-
static virClassPtr virUSBDeviceListClass;
static void virUSBDeviceListDispose(void *obj);
@@ -119,11 +113,33 @@ static int virUSBSysReadFile(const char *f_name, const char
*d_name,
return ret;
}
+static int virUSBSysReadFileStr(const char *f_name, const char *d_name,
+ char **value)
+{
+ int ret = -1, tmp;
+ char *buf = NULL;
+ char *filename = NULL;
+
+ tmp = virAsprintf(&filename, USB_SYSFS "/devices/%s/%s", d_name,
f_name);
+ if (tmp < 0)
+ goto cleanup;
+
+ if (virFileReadAll(filename, 1024, &buf) < 0)
+ goto cleanup;
+
+ *value = buf;
+ ret = 0;
+ cleanup:
+ VIR_FREE(filename);
+ return ret;
+}
+
static virUSBDeviceListPtr
virUSBDeviceSearch(unsigned int vendor,
unsigned int product,
unsigned int bus,
unsigned int devno,
+ const char *port,
const char *vroot,
unsigned int flags)
{
@@ -143,6 +159,8 @@ virUSBDeviceSearch(unsigned int vendor,
while ((direrr = virDirRead(dir, &de, USB_SYSFS "/devices")) > 0) {
unsigned int found_prod, found_vend, found_bus, found_devno;
+ char *found_port;
+ bool port_matches;
char *tmpstr = de->d_name;
if (strchr(de->d_name, ':'))
@@ -170,16 +188,31 @@ virUSBDeviceSearch(unsigned int vendor,
10, &found_devno) < 0)
goto cleanup;
+ if (virUSBSysReadFileStr("devpath", de->d_name,
+ &found_port) < 0) {
+ goto cleanup;
+ } else {
+ found_port[strlen(found_port) - 1] = '\0'; /* remove newline */
+ port_matches = STREQ_NULLABLE(found_port, port);
+ VIR_FREE(found_port);
+ }
+
if ((flags & USB_DEVICE_FIND_BY_VENDOR) &&
(found_prod != product || found_vend != vendor))
continue;
- if (flags & USB_DEVICE_FIND_BY_BUS) {
+ if (flags & USB_DEVICE_FIND_BY_DEVICE) {
if (found_bus != bus || found_devno != devno)
continue;
found = true;
}
+ if (flags & USB_DEVICE_FIND_BY_PORT) {
+ if (found_bus != bus || !port_matches)
+ continue;
+ found = true;
+ }
+
usb = virUSBDeviceNew(found_bus, found_devno, vroot);
if (!usb)
goto cleanup;
@@ -204,36 +237,43 @@ virUSBDeviceSearch(unsigned int vendor,
}
int
-virUSBDeviceFindByVendor(unsigned int vendor,
- unsigned int product,
- const char *vroot,
- bool mandatory,
- virUSBDeviceListPtr *devices)
+virUSBDeviceFind(unsigned int vendor,
+ unsigned int product,
+ unsigned int bus,
+ unsigned int devno,
+ const char *port,
+ const char *vroot,
+ bool mandatory,
+ unsigned int flags,
+ virUSBDeviceListPtr *devices)
{
virUSBDeviceListPtr list;
int count;
- if (!(list = virUSBDeviceSearch(vendor, product, 0, 0,
- vroot,
- USB_DEVICE_FIND_BY_VENDOR)))
+ if (!(list = virUSBDeviceSearch(vendor, product, bus, devno, port,
+ vroot, flags)))
return -1;
- if (list->count == 0) {
+ count = list->count;
+ if (count == 0) {
virObjectUnref(list);
if (!mandatory) {
- VIR_DEBUG("Did not find USB device %x:%x",
- vendor, product);
if (devices)
*devices = NULL;
return 0;
}
virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Did not find USB device %x:%x"), vendor, product);
+ _("Did not find a matching USB device (matching "
+ "on%s%s%s all others ignored): vid:%04x, pid:%04x, "
+ "bus:%u, device:%u, port:%s"),
+ flags & USB_DEVICE_FIND_BY_VENDOR ? " vid/pid," :
"",
+ flags & USB_DEVICE_FIND_BY_DEVICE ? " bus/device," :
"",
+ flags & USB_DEVICE_FIND_BY_PORT ? " bus/port," :
"",
+ vendor, product, bus, devno, port ? port : "(null)");
return -1;
}
- count = list->count;
if (devices)
*devices = list;
else
@@ -242,86 +282,6 @@ virUSBDeviceFindByVendor(unsigned int vendor,
return count;
}
-int
-virUSBDeviceFindByBus(unsigned int bus,
- unsigned int devno,
- const char *vroot,
- bool mandatory,
- virUSBDevicePtr *usb)
-{
- virUSBDeviceListPtr list;
-
- if (!(list = virUSBDeviceSearch(0, 0, bus, devno,
- vroot,
- USB_DEVICE_FIND_BY_BUS)))
- return -1;
-
- if (list->count == 0) {
- virObjectUnref(list);
- if (!mandatory) {
- VIR_DEBUG("Did not find USB device bus:%u device:%u",
- bus, devno);
- if (usb)
- *usb = NULL;
- return 0;
- }
-
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Did not find USB device bus:%u device:%u"),
- bus, devno);
- return -1;
- }
-
- if (usb) {
- *usb = virUSBDeviceListGet(list, 0);
- virUSBDeviceListSteal(list, *usb);
- }
- virObjectUnref(list);
-
- return 0;
-}
-
-int
-virUSBDeviceFind(unsigned int vendor,
- unsigned int product,
- unsigned int bus,
- unsigned int devno,
- const char *vroot,
- bool mandatory,
- virUSBDevicePtr *usb)
-{
- virUSBDeviceListPtr list;
-
- unsigned int flags = USB_DEVICE_FIND_BY_VENDOR|USB_DEVICE_FIND_BY_BUS;
- if (!(list = virUSBDeviceSearch(vendor, product, bus, devno,
- vroot, flags)))
- return -1;
-
- if (list->count == 0) {
- virObjectUnref(list);
- if (!mandatory) {
- VIR_DEBUG("Did not find USB device %x:%x bus:%u device:%u",
- vendor, product, bus, devno);
- if (usb)
- *usb = NULL;
- return 0;
- }
-
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Did not find USB device %x:%x bus:%u device:%u"),
- vendor, product, bus, devno);
- return -1;
- }
-
- if (usb) {
- *usb = virUSBDeviceListGet(list, 0);
- virUSBDeviceListSteal(list, *usb);
- }
- virObjectUnref(list);
-
- return 0;
-}
-
virUSBDevicePtr
virUSBDeviceNew(unsigned int bus,
unsigned int devno,
diff --git a/src/util/virusb.h b/src/util/virusb.h
index f98ea21..0834cd4 100644
--- a/src/util/virusb.h
+++ b/src/util/virusb.h
@@ -35,29 +35,26 @@ typedef virUSBDevice *virUSBDevicePtr;
typedef struct _virUSBDeviceList virUSBDeviceList;
typedef virUSBDeviceList *virUSBDeviceListPtr;
+typedef enum {
+ USB_DEVICE_ALL = 0,
+ USB_DEVICE_FIND_BY_VENDOR = 1 << 0,
+ USB_DEVICE_FIND_BY_DEVICE = 1 << 1,
+ USB_DEVICE_FIND_BY_PORT = 1 << 2,
+} virUSBDeviceFindFlags;
+
virUSBDevicePtr virUSBDeviceNew(unsigned int bus,
unsigned int devno,
const char *vroot);
-int virUSBDeviceFindByBus(unsigned int bus,
- unsigned int devno,
- const char *vroot,
- bool mandatory,
- virUSBDevicePtr *usb);
-
-int virUSBDeviceFindByVendor(unsigned int vendor,
- unsigned int product,
- const char *vroot,
- bool mandatory,
- virUSBDeviceListPtr *devices);
-
int virUSBDeviceFind(unsigned int vendor,
unsigned int product,
unsigned int bus,
unsigned int devno,
+ const char *port,
const char *vroot,
bool mandatory,
- virUSBDevicePtr *usb);
+ unsigned int flags,
+ virUSBDeviceListPtr *devices);
void virUSBDeviceFree(virUSBDevicePtr dev);
int virUSBDeviceSetUsedBy(virUSBDevicePtr dev,
diff --git a/tests/virusbtest.c b/tests/virusbtest.c
index 4bbfe4a..0782b73 100644
--- a/tests/virusbtest.c
+++ b/tests/virusbtest.c
@@ -33,7 +33,8 @@
typedef enum {
FIND_BY_ALL,
FIND_BY_VENDOR,
- FIND_BY_BUS
+ FIND_BY_DEVICE,
+ FIND_BY_PORT
} testUSBFindFlags;
struct findTestInfo {
@@ -42,6 +43,7 @@ struct findTestInfo {
unsigned int product;
unsigned int bus;
unsigned int devno;
+ const char *port;
const char *vroot;
bool mandatory;
int how;
@@ -78,25 +80,31 @@ static int testDeviceFind(const void *opaque)
virUSBDeviceListPtr devs = NULL;
int rv = 0;
size_t i, ndevs = 0;
+ unsigned int flags = 0;
switch (info->how) {
case FIND_BY_ALL:
- rv = virUSBDeviceFind(info->vendor, info->product,
- info->bus, info->devno,
- info->vroot, info->mandatory, &dev);
+ flags = USB_DEVICE_FIND_BY_VENDOR |
+ USB_DEVICE_FIND_BY_DEVICE |
+ USB_DEVICE_FIND_BY_PORT;
break;
case FIND_BY_VENDOR:
- rv = virUSBDeviceFindByVendor(info->vendor, info->product,
- info->vroot, info->mandatory, &devs);
+ flags = USB_DEVICE_FIND_BY_VENDOR;
break;
- case FIND_BY_BUS:
- rv = virUSBDeviceFindByBus(info->bus, info->devno,
- info->vroot, info->mandatory, &dev);
+ case FIND_BY_DEVICE:
+ flags = USB_DEVICE_FIND_BY_DEVICE;
+ break;
+ case FIND_BY_PORT:
+ flags = USB_DEVICE_FIND_BY_PORT;
break;
}
+ rv = virUSBDeviceFind(info->vendor, info->product,
+ info->bus, info->devno, info->port,
+ info->vroot, info->mandatory, flags, &devs);
+
if (info->expectFailure) {
- if (rv == 0) {
+ if (rv >= 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
"unexpected success");
} else {
@@ -107,9 +115,18 @@ static int testDeviceFind(const void *opaque)
goto cleanup;
}
+ if (info->how != FIND_BY_VENDOR) {
+ if (rv == 1) {
+ dev = virUSBDeviceListGet(devs, 0);
+ virUSBDeviceListSteal(devs, dev);
+ } else {
+ goto cleanup;
+ }
+ }
+
switch (info->how) {
case FIND_BY_ALL:
- case FIND_BY_BUS:
+ case FIND_BY_DEVICE:
if (virUSBDeviceFileIterate(dev, testDeviceFileActor, NULL) < 0)
goto cleanup;
break;
@@ -155,14 +172,17 @@ testUSBList(const void *opaque ATTRIBUTE_UNUSED)
virUSBDeviceListPtr list = NULL;
virUSBDeviceListPtr devlist = NULL;
virUSBDevicePtr dev = NULL;
+ virUSBDeviceListPtr devs = NULL;
int ret = -1;
+ int rv;
size_t i, ndevs;
if (!(list = virUSBDeviceListNew()))
goto cleanup;
#define EXPECTED_NDEVS_ONE 3
- if (virUSBDeviceFindByVendor(0x1d6b, 0x0002, NULL, true, &devlist) < 0)
+ if (virUSBDeviceFind(0x1d6b, 0x0002, 0, 0, NULL, NULL, true,
+ USB_DEVICE_FIND_BY_VENDOR, &devlist) < 0)
goto cleanup;
ndevs = virUSBDeviceListCount(devlist);
@@ -186,7 +206,8 @@ testUSBList(const void *opaque ATTRIBUTE_UNUSED)
goto cleanup;
#define EXPECTED_NDEVS_TWO 3
- if (virUSBDeviceFindByVendor(0x18d1, 0x4e22, NULL, true, &devlist) < 0)
+ if (virUSBDeviceFind(0x18d1, 0x4e22, 0, 0, NULL, NULL, true,
+ USB_DEVICE_FIND_BY_VENDOR, &devlist) < 0)
goto cleanup;
ndevs = virUSBDeviceListCount(devlist);
@@ -206,8 +227,17 @@ testUSBList(const void *opaque ATTRIBUTE_UNUSED)
EXPECTED_NDEVS_ONE + EXPECTED_NDEVS_TWO) < 0)
goto cleanup;
- if (virUSBDeviceFind(0x18d1, 0x4e22, 1, 20, NULL, true, &dev) < 0)
+ rv = virUSBDeviceFind(0x18d1, 0x4e22, 1, 20, "1.5.6", NULL, true,
+ USB_DEVICE_FIND_BY_VENDOR |
+ USB_DEVICE_FIND_BY_DEVICE |
+ USB_DEVICE_FIND_BY_PORT, &devs);
+ if (rv != 1) {
goto cleanup;
+ } else {
+ dev = virUSBDeviceListGet(devs, 0);
+ virUSBDeviceListSteal(devs, dev);
+ }
+ virObjectUnref(devs);
if (!virUSBDeviceListFind(list, dev)) {
virReportError(VIR_ERR_INTERNAL_ERROR,
@@ -239,49 +269,63 @@ mymain(void)
{
int rv = 0;
-#define DO_TEST_FIND_FULL(name, vend, prod, bus, devno, vroot, mand, how, fail) \
- do { \
- struct findTestInfo data = { name, vend, prod, bus, \
- devno, vroot, mand, how, fail \
- }; \
- if (virTestRun("USBDeviceFind " name, testDeviceFind, &data) <
0) \
- rv = -1; \
+#define DO_TEST_FIND_FULL(name, vend, prod, bus, devno, \
+ port, vroot, mand, how, fail) \
+ do { \
+ struct findTestInfo data = { name, vend, prod, bus, \
+ devno, port, vroot, mand, how, fail \
+ }; \
+ if (virTestRun("USBDeviceFind " name, testDeviceFind, &data) <
0) \
+ rv = -1; \
} while (0)
-#define DO_TEST_FIND(name, vend, prod, bus, devno) \
- DO_TEST_FIND_FULL(name, vend, prod, bus, devno, NULL, true, \
+#define DO_TEST_FIND(name, vend, prod, bus, devno, port) \
+ DO_TEST_FIND_FULL(name, vend, prod, bus, devno, port, NULL, true, \
FIND_BY_ALL, false)
-#define DO_TEST_FIND_FAIL(name, vend, prod, bus, devno) \
- DO_TEST_FIND_FULL(name, vend, prod, bus, devno, NULL, true, \
+#define DO_TEST_FIND_FAIL(name, vend, prod, bus, devno, port) \
+ DO_TEST_FIND_FULL(name, vend, prod, bus, devno, port, NULL, true, \
FIND_BY_ALL, true)
-#define DO_TEST_FIND_BY_BUS(name, bus, devno) \
- DO_TEST_FIND_FULL(name, 101, 202, bus, devno, NULL, true, \
- FIND_BY_BUS, false)
-#define DO_TEST_FIND_BY_BUS_FAIL(name, bus, devno) \
- DO_TEST_FIND_FULL(name, 101, 202, bus, devno, NULL, true, \
- FIND_BY_BUS, true)
+#define DO_TEST_FIND_BY_DEVICE(name, bus, devno) \
+ DO_TEST_FIND_FULL(name, 101, 202, bus, devno, NULL, NULL, true, \
+ FIND_BY_DEVICE, false)
+#define DO_TEST_FIND_BY_DEVICE_FAIL(name, bus, devno) \
+ DO_TEST_FIND_FULL(name, 101, 202, bus, devno, NULL, NULL, true, \
+ FIND_BY_DEVICE, true)
#define DO_TEST_FIND_BY_VENDOR(name, vend, prod) \
- DO_TEST_FIND_FULL(name, vend, prod, 123, 456, NULL, true, \
+ DO_TEST_FIND_FULL(name, vend, prod, 123, 456, NULL, NULL, true, \
FIND_BY_VENDOR, false)
#define DO_TEST_FIND_BY_VENDOR_FAIL(name, vend, prod) \
- DO_TEST_FIND_FULL(name, vend, prod, 123, 456, NULL, true, \
+ DO_TEST_FIND_FULL(name, vend, prod, 123, 456, NULL, NULL, true, \
FIND_BY_VENDOR, true)
- DO_TEST_FIND("Nexus", 0x18d1, 0x4e22, 1, 20);
- DO_TEST_FIND_FAIL("Nexus wrong devnum", 0x18d1, 0x4e22, 1, 25);
- DO_TEST_FIND_FAIL("Bogus", 0xf00d, 0xbeef, 1024, 768);
+#define DO_TEST_FIND_BY_PORT(name, bus, port) \
+ DO_TEST_FIND_FULL(name, 101, 202, bus, 456, port, NULL, true, \
+ FIND_BY_PORT, false)
+#define DO_TEST_FIND_BY_PORT_FAIL(name, bus, port) \
+ DO_TEST_FIND_FULL(name, 101, 202, bus, 456, port, NULL, true, \
+ FIND_BY_PORT, true)
+
+ DO_TEST_FIND("Nexus", 0x18d1, 0x4e22, 1, 20, "1.5.6");
+ DO_TEST_FIND_FAIL("Nexus wrong devnum", 0x18d1, 0x4e22, 1, 25,
"1.5.6");
+ DO_TEST_FIND_FAIL("Nexus wrong port", 0x18d1, 0x4e22, 1, 25,
"1.5.4");
+ DO_TEST_FIND_FAIL("Bogus", 0xf00d, 0xbeef, 1024, 768,
"1.2.3.4");
- DO_TEST_FIND_BY_BUS("integrated camera", 1, 5);
- DO_TEST_FIND_BY_BUS_FAIL("wrong bus/devno combination", 2, 20);
- DO_TEST_FIND_BY_BUS_FAIL("missing bus", 5, 20);
- DO_TEST_FIND_BY_BUS_FAIL("missing devnum", 1, 158);
+ DO_TEST_FIND_BY_DEVICE("integrated camera", 1, 5);
+ DO_TEST_FIND_BY_DEVICE_FAIL("wrong bus/devno combination", 2, 20);
+ DO_TEST_FIND_BY_DEVICE_FAIL("missing bus", 5, 20);
+ DO_TEST_FIND_BY_DEVICE_FAIL("missing devnum", 1, 158);
DO_TEST_FIND_BY_VENDOR("Nexus (multiple results)", 0x18d1, 0x4e22);
DO_TEST_FIND_BY_VENDOR_FAIL("Bogus vendor and product", 0xf00d, 0xbeef);
DO_TEST_FIND_BY_VENDOR_FAIL("Valid vendor", 0x1d6b, 0xbeef);
+ DO_TEST_FIND_BY_PORT("Logitech mouse", 1, "1.5.3.3");
+ DO_TEST_FIND_BY_PORT_FAIL("wrong bus/port combination", 2,
"1.5.3.3");
+ DO_TEST_FIND_BY_PORT_FAIL("missing bus", 5, "1.5.3.3");
+ DO_TEST_FIND_BY_PORT_FAIL("missing port", 1, "8.2.5");
+
if (virTestRun("USB List test", testUSBList, NULL) < 0)
rv = -1;
diff --git a/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.3.1/devpath
b/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.3.1/devpath
new file mode 100644
index 0000000..02a7fbe
--- /dev/null
+++ b/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.3.1/devpath
@@ -0,0 +1 @@
+1.5.3.1
diff --git a/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.3.3/devpath
b/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.3.3/devpath
new file mode 100644
index 0000000..23ca863
--- /dev/null
+++ b/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.3.3/devpath
@@ -0,0 +1 @@
+1.5.3.3
diff --git a/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.3/devpath
b/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.3/devpath
new file mode 100644
index 0000000..8af85be
--- /dev/null
+++ b/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.3/devpath
@@ -0,0 +1 @@
+1.5.3
diff --git a/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.4/devpath
b/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.4/devpath
new file mode 100644
index 0000000..94fe62c
--- /dev/null
+++ b/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.4/devpath
@@ -0,0 +1 @@
+1.5.4
diff --git a/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.5/devpath
b/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.5/devpath
new file mode 100644
index 0000000..9075be4
--- /dev/null
+++ b/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.5/devpath
@@ -0,0 +1 @@
+1.5.5
diff --git a/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.6/devpath
b/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.6/devpath
new file mode 100644
index 0000000..eac1e0a
--- /dev/null
+++ b/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.6/devpath
@@ -0,0 +1 @@
+1.5.6
diff --git a/tests/virusbtestdata/sys_bus_usb/devices/1-1.5/devpath
b/tests/virusbtestdata/sys_bus_usb/devices/1-1.5/devpath
new file mode 100644
index 0000000..c239c60
--- /dev/null
+++ b/tests/virusbtestdata/sys_bus_usb/devices/1-1.5/devpath
@@ -0,0 +1 @@
+1.5
diff --git a/tests/virusbtestdata/sys_bus_usb/devices/1-1.6/devpath
b/tests/virusbtestdata/sys_bus_usb/devices/1-1.6/devpath
new file mode 100644
index 0000000..810ee4e
--- /dev/null
+++ b/tests/virusbtestdata/sys_bus_usb/devices/1-1.6/devpath
@@ -0,0 +1 @@
+1.6
diff --git a/tests/virusbtestdata/sys_bus_usb/devices/1-1/devpath
b/tests/virusbtestdata/sys_bus_usb/devices/1-1/devpath
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/tests/virusbtestdata/sys_bus_usb/devices/1-1/devpath
@@ -0,0 +1 @@
+1
diff --git a/tests/virusbtestdata/sys_bus_usb/devices/2-1.2/devpath
b/tests/virusbtestdata/sys_bus_usb/devices/2-1.2/devpath
new file mode 100644
index 0000000..5625e59
--- /dev/null
+++ b/tests/virusbtestdata/sys_bus_usb/devices/2-1.2/devpath
@@ -0,0 +1 @@
+1.2
diff --git a/tests/virusbtestdata/sys_bus_usb/devices/2-1/devpath
b/tests/virusbtestdata/sys_bus_usb/devices/2-1/devpath
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/tests/virusbtestdata/sys_bus_usb/devices/2-1/devpath
@@ -0,0 +1 @@
+1
diff --git a/tests/virusbtestdata/sys_bus_usb/devices/usb1/devpath
b/tests/virusbtestdata/sys_bus_usb/devices/usb1/devpath
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/tests/virusbtestdata/sys_bus_usb/devices/usb1/devpath
@@ -0,0 +1 @@
+0
diff --git a/tests/virusbtestdata/sys_bus_usb/devices/usb2/devpath
b/tests/virusbtestdata/sys_bus_usb/devices/usb2/devpath
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/tests/virusbtestdata/sys_bus_usb/devices/usb2/devpath
@@ -0,0 +1 @@
+0
diff --git a/tests/virusbtestdata/sys_bus_usb/devices/usb3/devpath
b/tests/virusbtestdata/sys_bus_usb/devices/usb3/devpath
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/tests/virusbtestdata/sys_bus_usb/devices/usb3/devpath
@@ -0,0 +1 @@
+0
diff --git a/tests/virusbtestdata/sys_bus_usb/devices/usb4/devpath
b/tests/virusbtestdata/sys_bus_usb/devices/usb4/devpath
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/tests/virusbtestdata/sys_bus_usb/devices/usb4/devpath
@@ -0,0 +1 @@
+0
--
2.7.4