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

Guannan Ren gren at redhat.com
Sat Apr 28 10:13:05 UTC 2012


usbFindDevice():get usb device according to
                idVendor, idProduct, bus, device
                it is the most strict search

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

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

usbDeivceSearch(): a helper function to do the actual search
---
 src/util/hostusb.c |  162 ++++++++++++++++++++++++++++++++++++++-------------
 src/util/hostusb.h |   20 ++++++-
 2 files changed, 138 insertions(+), 44 deletions(-)

diff --git a/src/util/hostusb.c b/src/util/hostusb.c
index 92f52a2..73dc959 100644
--- a/src/util/hostusb.c
+++ b/src/util/hostusb.c
@@ -94,13 +94,22 @@ cleanup:
     return ret;
 }
 
-static int usbFindBusByVendor(unsigned vendor, unsigned product,
-                              unsigned *bus, unsigned *devno)
+static usbDeviceList *
+usbDeivceSearch(unsigned vendor,
+                unsigned product,
+                unsigned bus,
+                unsigned devno,
+                unsigned flags)
 {
     DIR *dir = NULL;
-    int ret = -1, found = 0;
+    int found = 0;
     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,48 +120,72 @@ static int usbFindBusByVendor(unsigned vendor, unsigned product,
     }
 
     while ((de = readdir(dir))) {
-        unsigned found_prod, found_vend;
+        unsigned 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 (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 (virStrToLong_ui(tmpstr, &ignore, 10, &found_bus) < 0) {
-                usbReportError(VIR_ERR_INTERNAL_ERROR,
-                               _("Failed to parse dir name '%s'"),
-                               de->d_name);
-                goto cleanup;
-            }
+        switch (flags) {
+        /*
+         * Don't set found to 1 in order to continue the loop
+         * to find multiple USB devices with same idVendor and idProduct
+         */
+        case USB_DEVICE_FIND_BY_VENDOR:
+            if (found_prod != product || found_vend != vendor)
+                continue;
+            break;
 
-            if (usbSysReadFile("devnum", de->d_name,
-                               10, &found_addr) < 0)
-                goto cleanup;
+        case USB_DEVICE_FIND_BY_BUS:
+            if (found_bus != bus || found_devno != devno)
+                continue;
+            found = 1;
+            break;
 
-            *bus = found_bus;
-            *devno = found_addr;
+        case USB_DEVICE_FIND_BY_ALL:
+            if (found_prod != product
+                || found_vend != vendor
+                || found_bus != bus
+                || found_devno != devno)
+                continue;
             found = 1;
             break;
         }
-    }
 
-    if (!found)
-        usbReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("Did not find USB device %x:%x"), vendor, product);
-    else
-        ret = 0;
+        usb = usbGetDevice(found_bus, found_devno);
+        if (!usb)
+            goto cleanup;
+
+        if (usbDeviceListAdd(list, usb) < 0) {
+            usbFreeDevice(usb);
+            goto cleanup;
+        }
+
+        if (found) break;
+    }
+    ret = list;
 
 cleanup:
     if (dir) {
@@ -160,9 +193,69 @@ cleanup:
         closedir (dir);
         errno = saved_errno;
     }
+
+    if (!ret)
+        usbDeviceListFree(list);
     return ret;
 }
 
+usbDeviceList *
+usbFindDevByVendor(unsigned vendor, unsigned product)
+{
+
+    usbDeviceList *list;
+    if (!(list = usbDeivceSearch(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 *
+usbFindDevByBus(unsigned bus, unsigned devno)
+{
+    usbDeviceList *list;
+    if (!(list = usbDeivceSearch(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;
+    }
+
+    return usbDeviceListGet(list, 0);
+}
+
+usbDevice *
+usbFindDevice(unsigned vendor,
+              unsigned product,
+              unsigned bus,
+              unsigned devno)
+{
+    usbDeviceList *list;
+    if (!(list = usbDeivceSearch(vendor, product,
+                                 bus, devno, USB_DEVICE_FIND_BY_ALL)))
+        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;
+    }
+
+    return usbDeviceListGet(list, 0);
+}
+
 usbDevice *
 usbGetDevice(unsigned bus,
              unsigned devno)
@@ -207,21 +300,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)
 {
diff --git a/src/util/hostusb.h b/src/util/hostusb.h
index afaa32f..7f18bce 100644
--- a/src/util/hostusb.h
+++ b/src/util/hostusb.h
@@ -28,10 +28,26 @@
 typedef struct _usbDevice usbDevice;
 typedef struct _usbDeviceList usbDeviceList;
 
+typedef enum {
+    USB_DEVICE_FIND_BY_VENDOR = 0,
+    USB_DEVICE_FIND_BY_BUS = 1 << 0,
+    USB_DEVICE_FIND_BY_ALL = 1 << 1,
+} usbDeviceFindFlags;
+
 usbDevice *usbGetDevice(unsigned bus,
                         unsigned devno);
-usbDevice *usbFindDevice(unsigned vendor,
-                         unsigned product);
+
+usbDevice * usbFindDevByBus(unsigned bus,
+                            unsigned devno);
+
+usbDeviceList * usbFindDevByVendor(unsigned vendor,
+                                   unsigned product);
+
+usbDevice * usbFindDevice(unsigned vendor,
+                          unsigned product,
+                          unsigned bus,
+                          unsigned devno);
+
 void       usbFreeDevice (usbDevice *dev);
 void       usbDeviceSetUsedBy(usbDevice *dev, const char *name);
 const char *usbDeviceGetUsedBy(usbDevice *dev);
-- 
1.7.7.5




More information about the libvir-list mailing list