[PATCH 1/3] usb: create functions to search usb device accurately

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



usbFindDevice():get usb device according to
                idVendor, idProduct, bus, device
                it is the exact match of the four parameters

usbFindDeviceByBus():get usb device according to bus, device
                  it returns only one usb device same as usbFindDevice

usbFindDeviceByVendor():get usb device according to idVendor,idProduct
                     it probably returns multiple usb devices.

usbDeviceSearch(): a helper function to do the actual search
---
 src/libvirt_private.syms |    2 +
 src/qemu/qemu_hostdev.c  |   14 +++-
 src/qemu/qemu_hotplug.c  |   14 +++-
 src/util/hostusb.c       |  202 ++++++++++++++++++++++++++++++++-------------
 src/util/hostusb.h       |   22 ++++--
 5 files changed, 181 insertions(+), 73 deletions(-)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 88f8a21..a4670d3 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1088,6 +1088,8 @@ usbDeviceListNew;
 usbDeviceListSteal;
 usbDeviceSetUsedBy;
 usbFindDevice;
+usbFindDeviceByBus;
+usbFindDeviceByVendor;
 usbFreeDevice;
 usbGetDevice;
 
diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c
index 8594fb2..b98fd8f 100644
--- a/src/qemu/qemu_hostdev.c
+++ b/src/qemu/qemu_hostdev.c
@@ -594,13 +594,19 @@ qemuPrepareHostdevUSBDevices(struct qemud_driver *driver,
 
         /* Resolve a vendor/product to bus/device */
         if (hostdev->source.subsys.u.usb.vendor) {
-            usbDevice *usb
-                = usbFindDevice(hostdev->source.subsys.u.usb.vendor,
-                                hostdev->source.subsys.u.usb.product);
+            usbDevice *usb;
+            usbDeviceList *devs;
 
-            if (!usb)
+            devs = usbFindDeviceByVendor(hostdev->source.subsys.u.usb.vendor,
+                                         hostdev->source.subsys.u.usb.product);
+
+            if (!devs)
                 goto cleanup;
 
+            usb = usbDeviceListGet(devs, 0);
+            usbDeviceListSteal(devs, usb);
+            usbDeviceListFree(devs);
+
             if ((tmp = usbDeviceListFind(driver->activeUsbHostdevs, usb))) {
                 const char *other_name = usbDeviceGetUsedBy(tmp);
 
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 7cf7b90..0f5fed1 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -1131,16 +1131,22 @@ int qemuDomainAttachHostDevice(struct qemud_driver *driver,
     /* Resolve USB product/vendor to bus/device */
     if (hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB &&
         hostdev->source.subsys.u.usb.vendor) {
+        usbDevice *usb;
+        usbDeviceList *list;
+
         if (qemuPrepareHostdevUSBDevices(driver, vm->def->name, &hostdev, 1) < 0)
             goto error;
 
-        usbDevice *usb
-            = usbFindDevice(hostdev->source.subsys.u.usb.vendor,
-                            hostdev->source.subsys.u.usb.product);
+        list = usbFindDeviceByVendor(hostdev->source.subsys.u.usb.vendor,
+                                     hostdev->source.subsys.u.usb.product);
 
-        if (!usb)
+        if (!list)
             return -1;
 
+        usb = usbDeviceListGet(list, 0);
+        usbDeviceListSteal(list, usb);
+        usbDeviceListFree(list);
+
         hostdev->source.subsys.u.usb.bus = usbDeviceGetBus(usb);
         hostdev->source.subsys.u.usb.device = usbDeviceGetDevno(usb);
 
diff --git a/src/util/hostusb.c b/src/util/hostusb.c
index 92f52a2..63b10ef 100644
--- a/src/util/hostusb.c
+++ b/src/util/hostusb.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009-2011 Red Hat, Inc.
+ * Copyright (C) 2009-2012 Red Hat, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -42,9 +42,16 @@
 #define USB_ID_LEN 10 /* "1234 5678" */
 #define USB_ADDR_LEN 8 /* "123:456" */
 
+/* For virReportOOMError()  and virReportSystemError() */
+#define VIR_FROM_THIS VIR_FROM_NONE
+
+#define usbReportError(code, ...)                              \
+    virReportErrorHelper(VIR_FROM_NONE, code, __FILE__,        \
+                         __FUNCTION__, __LINE__, __VA_ARGS__)
+
 struct _usbDevice {
-    unsigned      bus;
-    unsigned      dev;
+    unsigned int      bus;
+    unsigned int      dev;
 
     char          name[USB_ADDR_LEN]; /* domain:bus:slot.function */
     char          id[USB_ID_LEN];     /* product vendor */
@@ -57,15 +64,14 @@ struct _usbDeviceList {
     usbDevice **devs;
 };
 
-/* For virReportOOMError()  and virReportSystemError() */
-#define VIR_FROM_THIS VIR_FROM_NONE
-
-#define usbReportError(code, ...)                              \
-    virReportErrorHelper(VIR_FROM_NONE, code, __FILE__,        \
-                         __FUNCTION__, __LINE__, __VA_ARGS__)
+typedef enum {
+    USB_DEVICE_ALL = 0,
+    USB_DEVICE_FIND_BY_VENDOR = 1 << 0,
+    USB_DEVICE_FIND_BY_BUS = 1 << 1,
+} usbDeviceFindFlags;
 
 static int usbSysReadFile(const char *f_name, const char *d_name,
-                          int base, unsigned *value)
+                          int base, unsigned int *value)
 {
     int ret = -1, tmp;
     char *buf = NULL;
@@ -94,13 +100,22 @@ cleanup:
     return ret;
 }
 
-static int usbFindBusByVendor(unsigned vendor, unsigned product,
-                              unsigned *bus, unsigned *devno)
+static usbDeviceList *
+usbDeviceSearch(unsigned int vendor,
+                unsigned int product,
+                unsigned int bus,
+                unsigned int devno,
+                unsigned int flags)
 {
     DIR *dir = NULL;
-    int ret = -1, found = 0;
+    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) {
@@ -111,61 +126,145 @@ static int usbFindBusByVendor(unsigned vendor, unsigned product,
     }
 
     while ((de = readdir(dir))) {
-        unsigned found_prod, found_vend;
+        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 (found_prod == product && found_vend == vendor) {
-            /* Lookup bus.addr info */
-            char *tmpstr = de->d_name;
-            unsigned found_bus, found_addr;
+        if (STRPREFIX(de->d_name, "usb"))
+            tmpstr += 3;
+
+        if (virStrToLong_ui(tmpstr, &ignore, 10, &found_bus) < 0) {
+            usbReportError(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 (STRPREFIX(de->d_name, "usb"))
-                tmpstr += 3;
+        if (flags & USB_DEVICE_FIND_BY_BUS) {
+            if (found_bus != bus || found_devno != devno)
+                continue;
+            found = true;
+        }
 
-            if (virStrToLong_ui(tmpstr, &ignore, 10, &found_bus) < 0) {
-                usbReportError(VIR_ERR_INTERNAL_ERROR,
-                               _("Failed to parse dir name '%s'"),
-                               de->d_name);
-                goto cleanup;
-            }
+        usb = usbGetDevice(found_bus, found_devno);
+        if (!usb)
+            goto cleanup;
 
-            if (usbSysReadFile("devnum", de->d_name,
-                               10, &found_addr) < 0)
-                goto cleanup;
+        if (usbDeviceListAdd(list, usb) < 0) {
+            usbFreeDevice(usb);
+            goto cleanup;
+        }
 
-            *bus = found_bus;
-            *devno = found_addr;
-            found = 1;
+        if (found)
             break;
-        }
     }
-
-    if (!found)
-        usbReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("Did not find USB device %x:%x"), vendor, product);
-    else
-        ret = 0;
+    ret = list;
 
 cleanup:
     if (dir) {
         int saved_errno = errno;
-        closedir (dir);
+        closedir(dir);
         errno = saved_errno;
     }
+
+    if (!ret)
+        usbDeviceListFree(list);
     return ret;
 }
 
+usbDeviceList *
+usbFindDeviceByVendor(unsigned int vendor, unsigned product)
+{
+
+    usbDeviceList *list;
+    if (!(list = usbDeviceSearch(vendor, product, 0 , 0,
+                                 USB_DEVICE_FIND_BY_VENDOR)))
+        return NULL;
+
+    if (list->count == 0) {
+        usbReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Did not find USB device %x:%x"), vendor, product);
+        usbDeviceListFree(list);
+        return NULL;
+    }
+
+    return list;
+}
+
 usbDevice *
-usbGetDevice(unsigned bus,
-             unsigned devno)
+usbFindDeviceByBus(unsigned int bus, unsigned devno)
+{
+    usbDevice *usb;
+    usbDeviceList *list;
+
+    if (!(list = usbDeviceSearch(0, 0, bus, devno,
+                                 USB_DEVICE_FIND_BY_BUS)))
+        return NULL;
+
+    if (list->count == 0) {
+        usbReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Did not find USB device bus:%u device:%u"),
+                       bus, devno);
+        usbDeviceListFree(list);
+        return NULL;
+    }
+
+    usb = usbDeviceListGet(list, 0);
+    usbDeviceListSteal(list, usb);
+    usbDeviceListFree(list);
+
+    return usb;
+}
+
+usbDevice *
+usbFindDevice(unsigned int vendor,
+              unsigned int product,
+              unsigned int bus,
+              unsigned int devno)
+{
+    usbDevice *usb;
+    usbDeviceList *list;
+
+    unsigned int flags = USB_DEVICE_FIND_BY_VENDOR|USB_DEVICE_FIND_BY_BUS;
+    if (!(list = usbDeviceSearch(vendor, product, bus, devno, flags)))
+        return NULL;
+
+    if (list->count == 0) {
+        usbReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Did not find USB device %x:%x bus:%u device:%u"),
+                       vendor, product, bus, devno);
+        usbDeviceListFree(list);
+        return NULL;
+    }
+
+    usb = usbDeviceListGet(list, 0);
+    usbDeviceListSteal(list, usb);
+    usbDeviceListFree(list);
+
+    return usb;
+}
+
+usbDevice *
+usbGetDevice(unsigned int bus,
+             unsigned int devno)
 {
     usbDevice *dev;
 
@@ -207,21 +306,6 @@ usbGetDevice(unsigned bus,
     return dev;
 }
 
-
-usbDevice *
-usbFindDevice(unsigned vendor,
-              unsigned product)
-{
-    unsigned bus = 0, devno = 0;
-
-    if (usbFindBusByVendor(vendor, product, &bus, &devno) < 0) {
-        return NULL;
-    }
-
-    return usbGetDevice(bus, devno);
-}
-
-
 void
 usbFreeDevice(usbDevice *dev)
 {
@@ -247,13 +331,13 @@ const char *usbDeviceGetName(usbDevice *dev)
     return dev->name;
 }
 
-unsigned usbDeviceGetBus(usbDevice *dev)
+unsigned int usbDeviceGetBus(usbDevice *dev)
 {
     return dev->bus;
 }
 
 
-unsigned usbDeviceGetDevno(usbDevice *dev)
+unsigned int usbDeviceGetDevno(usbDevice *dev)
 {
     return dev->dev;
 }
diff --git a/src/util/hostusb.h b/src/util/hostusb.h
index afaa32f..27e07dc 100644
--- a/src/util/hostusb.h
+++ b/src/util/hostusb.h
@@ -28,17 +28,27 @@
 typedef struct _usbDevice usbDevice;
 typedef struct _usbDeviceList usbDeviceList;
 
-usbDevice *usbGetDevice(unsigned bus,
-                        unsigned devno);
-usbDevice *usbFindDevice(unsigned vendor,
-                         unsigned product);
+usbDevice *usbGetDevice(unsigned int bus,
+                        unsigned int devno);
+
+usbDevice *usbFindDeviceByBus(unsigned int bus,
+                              unsigned int devno);
+
+usbDeviceList *usbFindDeviceByVendor(unsigned int vendor,
+                                     unsigned int product);
+
+usbDevice *usbFindDevice(unsigned int vendor,
+                         unsigned int product,
+                         unsigned int bus,
+                         unsigned int devno);
+
 void       usbFreeDevice (usbDevice *dev);
 void       usbDeviceSetUsedBy(usbDevice *dev, const char *name);
 const char *usbDeviceGetUsedBy(usbDevice *dev);
 const char *usbDeviceGetName(usbDevice *dev);
 
-unsigned usbDeviceGetBus(usbDevice *dev);
-unsigned usbDeviceGetDevno(usbDevice *dev);
+unsigned int usbDeviceGetBus(usbDevice *dev);
+unsigned int usbDeviceGetDevno(usbDevice *dev);
 
 /*
  * Callback that will be invoked once for each file
-- 
1.7.7.5

--
libvir-list mailing list
libvir-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/libvir-list


[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]