From nobody Fri May 3 00:39:33 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 216.205.24.124 as permitted sender) client-ip=216.205.24.124; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-delivery-124.mimecast.com; Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of redhat.com designates 216.205.24.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1614702486; cv=none; d=zohomail.com; s=zohoarc; b=WRZE5LB0y5pxyRve3ffwXv+8x0tJoxwFXKyXZx+bFzSfE7ey0X3GtFkcWFMEoX9gVPAq6epUtMK4+Mnh1cvCAK4bVrq/hBYhTV9X9LxzWyTckUwY8vdFY5cGbIjmC/Z55MZe+ftiiC27mtxh3IM+BGcWpssYmLq4hGvcrZcRrf0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1614702486; h=Content-Type:Content-Transfer-Encoding:Date:From:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:To; bh=8PwLbglmjTUqFR2efXuGY1+ZFia1tLtKRp50N4oTlls=; b=lOCrVAHFDXgCYK4Chun+rKYKqfhDZ/0Rdd8ChYOatq0qPuIHadC/kEjQLSdwTUm1AZuf3Jdh7RwA2GiXuDJpwbItKNVl7LRmtyrdmEbiRSFjWr+F+iw7ve1QHYdSeA2YMB/lEXBY3Ey+XlOhU9kruvVCluYtTJ3y09XyjnZmsT0= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=pass (zohomail.com: domain of redhat.com designates 216.205.24.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [216.205.24.124]) by mx.zohomail.com with SMTPS id 1614702486948653.6888346740368; Tue, 2 Mar 2021 08:28:06 -0800 (PST) Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-97-SQdJ2e-1OD2sIaHoN5dTcw-1; Tue, 02 Mar 2021 11:28:03 -0500 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 4F5A8185A0D1; Tue, 2 Mar 2021 16:27:57 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id E56C710023AF; Tue, 2 Mar 2021 16:27:56 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 7216A4EA69; Tue, 2 Mar 2021 16:27:54 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id 122GRq1j025375 for ; Tue, 2 Mar 2021 11:27:53 -0500 Received: by smtp.corp.redhat.com (Postfix) id B05E610624C; Tue, 2 Mar 2021 16:27:52 +0000 (UTC) Received: from mimecast-mx02.redhat.com (mimecast06.extmail.prod.ext.rdu2.redhat.com [10.11.55.22]) by smtp.corp.redhat.com (Postfix) with ESMTPS id AA9A3119036 for ; Tue, 2 Mar 2021 16:27:50 +0000 (UTC) Received: from us-smtp-1.mimecast.com (us-smtp-delivery-1.mimecast.com [205.139.110.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 2DE341871CCA for ; Tue, 2 Mar 2021 16:27:50 +0000 (UTC) Received: from khitomer.mortis.eu (khitomer.mortis.eu [185.27.175.75]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-14-2iRkbyBQPXiV0zM5F5t83g-1; Tue, 02 Mar 2021 11:27:47 -0500 Received: from localhost.localdomain (unknown [IPv6:2001:981:4eab::546]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (Client did not present a certificate) by khitomer.mortis.eu (Postfix) with ESMTPS id BC487BA5; Tue, 2 Mar 2021 17:23:26 +0100 (CET) X-MC-Unique: SQdJ2e-1OD2sIaHoN5dTcw-1 X-MC-Unique: 2iRkbyBQPXiV0zM5F5t83g-1 From: Giel van Schijndel To: libvir-list@redhat.com Subject: [PATCH] feat(usb-hostdev): add ability to filter by USB serial strings too Date: Tue, 2 Mar 2021 17:23:26 +0100 Message-Id: <20210302162326.3998683-1-giel@mortis.eu> MIME-Version: 1.0 X-Mimecast-Impersonation-Protect: Policy=CLT - Impersonation Protection Definition; Similar Internal Domain=false; Similar Monitored External Domain=false; Custom External Domain=false; Mimecast External Domain=false; Newly Observed Domain=false; Internal User Name=false; Custom Display Name List=false; Reply-to Address Mismatch=false; Targeted Threat Dictionary=false; Mimecast Threat Dictionary=false; Custom Threat Dictionary=false X-Mimecast-Spam-Signature: yes X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-MIME-Autoconverted: from quoted-printable to 8bit by lists01.pubmisc.prod.ext.phx2.redhat.com id 122GRq1j025375 X-loop: libvir-list@redhat.com X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=libvir-list-bounces@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" This patch adds the ability to select a specific USB device when multiple are available with the same vendor and product IDs. As an example, I'm using this to pass through a specific USB mouse to my guest VM. I happen to have two of the exact same model (Logitech MX518), differing only in their serial number, and only wish to pass through one of them to my VM. An example of the config snippet I'm using with this: 0D3087538362 Without this patch I would either get an error message on attempted startup, complaining about having found multiple devices with the same product or vendor id. Or alternatively I'd have to set the bus number and device number. Unfortunately the latter tends to change with every reboot, and in my case whenever my monitor comes out of standby (I'm using its builtin USB hub). --- docs/formatdomain.rst | 6 ++ docs/schemas/domaincommon.rng | 10 +++ src/conf/domain_conf.c | 15 ++++ src/conf/domain_conf.h | 3 +- src/hypervisor/virhostdev.c | 14 ++-- src/util/virusb.c | 66 ++++++++++++----- src/util/virusb.h | 2 + tests/virusbtest.c | 71 +++++++++++-------- .../sys_bus_usb/devices/1-1.5.4/serial | 1 + .../sys_bus_usb/devices/1-1.5.5/serial | 1 + .../sys_bus_usb/devices/1-1.5.6/serial | 1 + 11 files changed, 137 insertions(+), 53 deletions(-) create mode 100644 tests/virusbtestdata/sys_bus_usb/devices/1-1.5.4/serial create mode 100644 tests/virusbtestdata/sys_bus_usb/devices/1-1.5.5/serial create mode 100644 tests/virusbtestdata/sys_bus_usb/devices/1-1.5.6/serial diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index 2587106191..6d011cc789 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -3864,6 +3864,7 @@ for PCI (KVM only) and 1.0.6 for SCSI (KVM only)` : + TANT14-B4732 @@ -4041,6 +4042,11 @@ or: optional drop if missing at any start attempt =3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D =20 + :since:`Since 7.1.0`, the ``source`` element of USB devices may cont= ain + the ``serial`` element which can be used in addition to ``vendor`` a= nd + ``product`` to select a specific USB device if multiple devices with= the + same vendor and product id are present. + ``pci`` PCI devices can only be described by their ``address``. :since:`Since 6.8.0 (Xen only)` , the ``source`` element of a PCI de= vice diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index e6de934456..d6eb29a9a8 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -5355,6 +5355,11 @@ + + + + + @@ -7053,6 +7058,11 @@ (0x)?[0-9a-fA-F]{1,4} + + + [A-Za-z0-9_\.\+\- ]+ + + [0-9]{1,2}.[0-9]{1,2} diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index b731744f04..4967d62989 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -3078,6 +3078,8 @@ void virDomainHostdevDefClear(virDomainHostdevDefPtr = def) VIR_FREE(def->source.subsys.u.scsi_host.wwpn); break; case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: + VIR_FREE(def->source.subsys.u.usb.serial); + break; case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV: case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST: @@ -6703,6 +6705,16 @@ virDomainHostdevSubsysUSBDefParseXML(xmlNodePtr node, "%s", _("usb product needs id")); return -1; } + } else if (!usbsrc->serial && + virXMLNodeNameEqual(cur, "serial")) { + g_autofree char *serial =3D virXMLNodeContentString(cur); + if (!serial) { + virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("usb serial needs content")); + return -1; + } + + usbsrc->serial =3D g_steal_pointer(&serial); } else if (virXMLNodeNameEqual(cur, "address")) { g_autofree char *bus =3D NULL; g_autofree char *device =3D NULL; @@ -25089,6 +25101,9 @@ virDomainHostdevDefFormatSubsysUSB(virBufferPtr buf, if (usbsrc->vendor) { virBufferAsprintf(&sourceChildBuf, "\n", us= bsrc->vendor); virBufferAsprintf(&sourceChildBuf, "\n", u= sbsrc->product); + if (usbsrc->serial) { + virBufferEscapeString(&sourceChildBuf, "%s\n"= , usbsrc->serial); + } } =20 if (usbsrc->bus || usbsrc->device) diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 930eed60de..a66b815901 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -227,12 +227,13 @@ VIR_ENUM_DECL(virDomainHostdevSubsysSCSIProtocol); =20 struct _virDomainHostdevSubsysUSB { bool autoAddress; /* bus/device were filled automatically based - on vendor/product */ + on vendor/product (optionally serial) */ unsigned bus; unsigned device; =20 unsigned vendor; unsigned product; + char *serial; }; =20 struct _virDomainHostdevSubsysPCI { diff --git a/src/hypervisor/virhostdev.c b/src/hypervisor/virhostdev.c index 743aaa84d6..f9fd42b24d 100644 --- a/src/hypervisor/virhostdev.c +++ b/src/hypervisor/virhostdev.c @@ -1324,6 +1324,7 @@ virHostdevFindUSBDevice(virDomainHostdevDefPtr hostde= v, virDomainHostdevSubsysUSBPtr usbsrc =3D &hostdev->source.subsys.u.usb; unsigned vendor =3D usbsrc->vendor; unsigned product =3D usbsrc->product; + const char *serial =3D usbsrc->serial; unsigned bus =3D usbsrc->bus; unsigned device =3D usbsrc->device; bool autoAddress =3D usbsrc->autoAddress; @@ -1332,7 +1333,7 @@ virHostdevFindUSBDevice(virDomainHostdevDefPtr hostde= v, *usb =3D NULL; =20 if (vendor && bus) { - rc =3D virUSBDeviceFind(vendor, product, bus, device, + rc =3D virUSBDeviceFind(vendor, product, serial, bus, device, NULL, autoAddress ? false : mandatory, usb); @@ -1354,7 +1355,8 @@ virHostdevFindUSBDevice(virDomainHostdevDefPtr hostde= v, if (vendor) { g_autoptr(virUSBDeviceList) devs =3D NULL; =20 - rc =3D virUSBDeviceFindByVendor(vendor, product, NULL, mandatory, = &devs); + rc =3D virUSBDeviceFindByVendor(vendor, product, serial, NULL, man= datory, + &devs); if (rc < 0) { return -1; } else if (rc =3D=3D 0) { @@ -1362,9 +1364,11 @@ virHostdevFindUSBDevice(virDomainHostdevDefPtr hostd= ev, } else if (rc > 1) { if (autoAddress) { virReportError(VIR_ERR_OPERATION_FAILED, - _("Multiple USB devices for %x:%x were foun= d," - " but none of them is at bus:%u device:%u= "), - vendor, product, bus, device); + _("Multiple USB devices for %x:%x (serial: = %s)" + " were found, but none of them is at bus:= %u" + " device:%u"), + vendor, product, serial ? serial : ""= , bus, + device); } else { virReportError(VIR_ERR_OPERATION_FAILED, _("Multiple USB devices for %x:%x, " diff --git a/src/util/virusb.c b/src/util/virusb.c index 6d897600e5..d945d71b98 100644 --- a/src/util/virusb.c +++ b/src/util/virusb.c @@ -81,21 +81,31 @@ static int virUSBOnceInit(void) =20 VIR_ONCE_GLOBAL_INIT(virUSB); =20 -static int virUSBSysReadFile(const char *f_name, const char *d_name, - int base, unsigned int *value) +static char* virUSBSysReadFile(const char *f_name, const char *d_name) { - g_autofree char *buf =3D NULL; g_autofree char *filename =3D NULL; - char *ignore =3D NULL; + char* buf; =20 filename =3D g_strdup_printf(USB_SYSFS "/devices/%s/%s", d_name, f_nam= e); =20 if (virFileReadAll(filename, 1024, &buf) < 0) + return NULL; + + return buf; +} + +static int virUSBSysReadIntFile(const char *f_name, const char *d_name, + int base, unsigned int *value) +{ + g_autofree char *buf =3D NULL; + char *ignore =3D NULL; + + if (!(buf =3D virUSBSysReadFile(f_name, d_name))) return -1; =20 if (virStrToLong_ui(buf, &ignore, base, value) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, - _("Could not parse usb file %s"), filename); + _("Could not parse usb file %s/%s"), d_name, f_name= ); return -1; } =20 @@ -105,6 +115,7 @@ static int virUSBSysReadFile(const char *f_name, const = char *d_name, static virUSBDeviceListPtr virUSBDeviceSearch(unsigned int vendor, unsigned int product, + const char *serial, unsigned int bus, unsigned int devno, const char *vroot, @@ -132,11 +143,11 @@ virUSBDeviceSearch(unsigned int vendor, if (strchr(de->d_name, ':')) continue; =20 - if (virUSBSysReadFile("idVendor", de->d_name, + if (virUSBSysReadIntFile("idVendor", de->d_name, 16, &found_vend) < 0) goto cleanup; =20 - if (virUSBSysReadFile("idProduct", de->d_name, + if (virUSBSysReadIntFile("idProduct", de->d_name, 16, &found_prod) < 0) goto cleanup; =20 @@ -150,13 +161,31 @@ virUSBDeviceSearch(unsigned int vendor, goto cleanup; } =20 - if (virUSBSysReadFile("devnum", de->d_name, + if (virUSBSysReadIntFile("devnum", de->d_name, 10, &found_devno) < 0) goto cleanup; =20 - if ((flags & USB_DEVICE_FIND_BY_VENDOR) && - (found_prod !=3D product || found_vend !=3D vendor)) - continue; + if (flags & USB_DEVICE_FIND_BY_VENDOR) { + if (found_prod !=3D product || found_vend !=3D vendor) + continue; + + if (serial) { + g_autofree char *found_serial =3D virUSBSysReadFile("seria= l", de->d_name); + size_t len; + + if (!found_serial) + continue; + len =3D strlen(found_serial); + if (!len) + continue; + + if (found_serial[len - 1] =3D=3D '\n') + found_serial[len - 1] =3D '\0'; + + if (strcmp(found_serial, serial)) + continue; + } + } =20 if (flags & USB_DEVICE_FIND_BY_BUS) { if (found_bus !=3D bus || found_devno !=3D devno) @@ -188,6 +217,7 @@ virUSBDeviceSearch(unsigned int vendor, int virUSBDeviceFindByVendor(unsigned int vendor, unsigned int product, + const char *serial, const char *vroot, bool mandatory, virUSBDeviceListPtr *devices) @@ -195,7 +225,7 @@ virUSBDeviceFindByVendor(unsigned int vendor, virUSBDeviceListPtr list; int count; =20 - if (!(list =3D virUSBDeviceSearch(vendor, product, 0, 0, + if (!(list =3D virUSBDeviceSearch(vendor, product, serial, 0, 0, vroot, USB_DEVICE_FIND_BY_VENDOR))) return -1; @@ -203,15 +233,16 @@ virUSBDeviceFindByVendor(unsigned int vendor, if (list->count =3D=3D 0) { virObjectUnref(list); if (!mandatory) { - VIR_DEBUG("Did not find USB device %04x:%04x", - vendor, product); + VIR_DEBUG("Did not find USB device %04x:%04x (serial %s)", + vendor, product, serial ? serial : ""); if (devices) *devices =3D NULL; return 0; } =20 virReportError(VIR_ERR_INTERNAL_ERROR, - _("Did not find USB device %04x:%04x"), vendor, pro= duct); + _("Did not find USB device %04x:%04x (serial %s)"), + vendor, product, serial ? serial : ""); return -1; } =20 @@ -233,7 +264,7 @@ virUSBDeviceFindByBus(unsigned int bus, { virUSBDeviceListPtr list; =20 - if (!(list =3D virUSBDeviceSearch(0, 0, bus, devno, + if (!(list =3D virUSBDeviceSearch(0, 0, NULL, bus, devno, vroot, USB_DEVICE_FIND_BY_BUS))) return -1; @@ -266,6 +297,7 @@ virUSBDeviceFindByBus(unsigned int bus, int virUSBDeviceFind(unsigned int vendor, unsigned int product, + const char *serial, unsigned int bus, unsigned int devno, const char *vroot, @@ -275,7 +307,7 @@ virUSBDeviceFind(unsigned int vendor, virUSBDeviceListPtr list; =20 unsigned int flags =3D USB_DEVICE_FIND_BY_VENDOR|USB_DEVICE_FIND_BY_BU= S; - if (!(list =3D virUSBDeviceSearch(vendor, product, bus, devno, + if (!(list =3D virUSBDeviceSearch(vendor, product, serial, bus, devno, vroot, flags))) return -1; =20 diff --git a/src/util/virusb.h b/src/util/virusb.h index 42a3303952..c9d5330fac 100644 --- a/src/util/virusb.h +++ b/src/util/virusb.h @@ -45,12 +45,14 @@ int virUSBDeviceFindByBus(unsigned int bus, =20 int virUSBDeviceFindByVendor(unsigned int vendor, unsigned int product, + const char* serial, const char *vroot, bool mandatory, virUSBDeviceListPtr *devices); =20 int virUSBDeviceFind(unsigned int vendor, unsigned int product, + const char* serial, unsigned int bus, unsigned int devno, const char *vroot, diff --git a/tests/virusbtest.c b/tests/virusbtest.c index 7df4e3aec3..cba4d57d9a 100644 --- a/tests/virusbtest.c +++ b/tests/virusbtest.c @@ -37,12 +37,14 @@ struct findTestInfo { const char *name; unsigned int vendor; unsigned int product; + const char *serial; unsigned int bus; unsigned int devno; const char *vroot; bool mandatory; int how; bool expectFailure; + unsigned int expectResults; }; =20 static int testDeviceFileActor(virUSBDevicePtr dev, @@ -76,12 +78,12 @@ static int testDeviceFind(const void *opaque) =20 switch (info->how) { case FIND_BY_ALL: - rv =3D virUSBDeviceFind(info->vendor, info->product, + rv =3D virUSBDeviceFind(info->vendor, info->product, info->serial, info->bus, info->devno, info->vroot, info->mandatory, &dev); break; case FIND_BY_VENDOR: - rv =3D virUSBDeviceFindByVendor(info->vendor, info->product, + rv =3D virUSBDeviceFindByVendor(info->vendor, info->product, info-= >serial, info->vroot, info->mandatory, &devs); break; case FIND_BY_BUS: @@ -117,6 +119,13 @@ static int testDeviceFind(const void *opaque) if (virUSBDeviceFileIterate(device, testDeviceFileActor, NULL)= < 0) goto cleanup; } + + if (ndevs !=3D info->expectResults) { + virReportError(VIR_ERR_INTERNAL_ERROR, "different amount of re= sults" + " than expected (%zu !=3D %u)", ndevs, + info->expectResults); + goto cleanup; + } break; } =20 @@ -157,7 +166,7 @@ testUSBList(const void *opaque G_GNUC_UNUSED) goto cleanup; =20 #define EXPECTED_NDEVS_ONE 3 - if (virUSBDeviceFindByVendor(0x1d6b, 0x0002, NULL, true, &devlist) < 0) + if (virUSBDeviceFindByVendor(0x1d6b, 0x0002, NULL, NULL, true, &devlis= t) < 0) goto cleanup; =20 ndevs =3D virUSBDeviceListCount(devlist); @@ -181,7 +190,7 @@ testUSBList(const void *opaque G_GNUC_UNUSED) goto cleanup; =20 #define EXPECTED_NDEVS_TWO 3 - if (virUSBDeviceFindByVendor(0x18d1, 0x4e22, NULL, true, &devlist) < 0) + if (virUSBDeviceFindByVendor(0x18d1, 0x4e22, NULL, NULL, true, &devlis= t) < 0) goto cleanup; =20 ndevs =3D virUSBDeviceListCount(devlist); @@ -201,7 +210,7 @@ testUSBList(const void *opaque G_GNUC_UNUSED) EXPECTED_NDEVS_ONE + EXPECTED_NDEVS_TWO) < 0) goto cleanup; =20 - if (virUSBDeviceFind(0x18d1, 0x4e22, 1, 20, NULL, true, &dev) < 0) + if (virUSBDeviceFind(0x18d1, 0x4e22, NULL, 1, 20, NULL, true, &dev) < = 0) goto cleanup; =20 if (!virUSBDeviceListFind(list, dev)) { @@ -235,48 +244,50 @@ mymain(void) { int rv =3D 0; =20 -#define DO_TEST_FIND_FULL(name, vend, prod, bus, devno, vroot, mand, how, = fail) \ +#define DO_TEST_FIND_FULL(name, vend, prod, serial, bus, devno, vroot, man= d, how, fail, expected) \ do { \ - struct findTestInfo data =3D { name, vend, prod, bus, \ - devno, vroot, mand, how, fail \ + struct findTestInfo data =3D { name, vend, prod, serial, bus, \ + devno, vroot, mand, how, fail, expected \ }; \ if (virTestRun("USBDeviceFind " name, testDeviceFind, &data) < 0) \ rv =3D -1; \ } while (0) =20 -#define DO_TEST_FIND(name, vend, prod, bus, devno) \ - DO_TEST_FIND_FULL(name, vend, prod, bus, devno, 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, \ - FIND_BY_ALL, true) +#define DO_TEST_FIND(name, vend, prod, serial, bus, devno, expected) \ + DO_TEST_FIND_FULL(name, vend, prod, serial, bus, devno, NULL, true, \ + FIND_BY_ALL, false, expected) +#define DO_TEST_FIND_FAIL(name, vend, prod, serial, bus, devno) \ + DO_TEST_FIND_FULL(name, vend, prod, serial, bus, devno, NULL, true, \ + FIND_BY_ALL, true, 0) =20 #define DO_TEST_FIND_BY_BUS(name, bus, devno) \ - DO_TEST_FIND_FULL(name, 101, 202, bus, devno, NULL, true, \ - FIND_BY_BUS, false) + DO_TEST_FIND_FULL(name, 101, 202, NULL, bus, devno, NULL, true, \ + FIND_BY_BUS, false, 1) #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) + DO_TEST_FIND_FULL(name, 101, 202, NULL, bus, devno, NULL, true, \ + FIND_BY_BUS, true, 0) =20 -#define DO_TEST_FIND_BY_VENDOR(name, vend, prod) \ - DO_TEST_FIND_FULL(name, vend, prod, 123, 456, 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, \ - FIND_BY_VENDOR, true) +#define DO_TEST_FIND_BY_VENDOR(name, vend, prod, serial, expected) \ + DO_TEST_FIND_FULL(name, vend, prod, serial, 123, 456, NULL, true, \ + FIND_BY_VENDOR, false, expected) +#define DO_TEST_FIND_BY_VENDOR_FAIL(name, vend, prod, serial) \ + DO_TEST_FIND_FULL(name, vend, prod, serial, 123, 456, NULL, true, \ + FIND_BY_VENDOR, true, 0) =20 - 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); + DO_TEST_FIND("Nexus", 0x18d1, 0x4e22, NULL, 1, 20, 1); + DO_TEST_FIND_FAIL("Nexus wrong devnum", 0x18d1, 0x4e22, NULL, 1, 25); + DO_TEST_FIND_FAIL("Bogus", 0xf00d, 0xbeef, NULL, 1024, 768); =20 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); =20 - 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_VENDOR("Nexus (multiple results)", 0x18d1, 0x4e22, NUL= L, 3); + DO_TEST_FIND_BY_VENDOR("Nexus (with serial)", 0x18d1, 0x4e22, "TANT14-= B4732", 1); + DO_TEST_FIND_BY_VENDOR_FAIL("Bogus vendor and product", 0xf00d, 0xbeef= , NULL); + DO_TEST_FIND_BY_VENDOR_FAIL("Valid vendor", 0x1d6b, 0xbeef, NULL); + DO_TEST_FIND_BY_VENDOR_FAIL("Bogus serial", 0x18d1, 0x4e22, "BOGUS"); =20 if (virTestRun("USB List test", testUSBList, NULL) < 0) rv =3D -1; diff --git a/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.4/serial b/test= s/virusbtestdata/sys_bus_usb/devices/1-1.5.4/serial new file mode 100644 index 0000000000..6bee213c08 --- /dev/null +++ b/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.4/serial @@ -0,0 +1 @@ +20200222113321 diff --git a/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.5/serial b/test= s/virusbtestdata/sys_bus_usb/devices/1-1.5.5/serial new file mode 100644 index 0000000000..14764cdc37 --- /dev/null +++ b/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.5/serial @@ -0,0 +1 @@ +0123:4b:01.7 diff --git a/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.6/serial b/test= s/virusbtestdata/sys_bus_usb/devices/1-1.5.6/serial new file mode 100644 index 0000000000..b20f2081b7 --- /dev/null +++ b/tests/virusbtestdata/sys_bus_usb/devices/1-1.5.6/serial @@ -0,0 +1 @@ +TANT14-B4732 --=20 2.27.0