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

Guannan Ren gren at redhat.com
Thu May 3 10:51:53 UTC 2012


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/util/hostusb.c       |  209 +++++++++++++++++++++++++++++++++-------------
 src/util/hostusb.h       |   22 ++++--
 3 files changed, 170 insertions(+), 63 deletions(-)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 025816a..b9f9015 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1084,6 +1084,8 @@ usbDeviceListGet;
 usbDeviceListNew;
 usbDeviceListSteal;
 usbDeviceSetUsedBy;
+usbFindDeviceByBus;
+usbFindDeviceByVendor;
 usbFindDevice;
 usbFreeDevice;
 usbGetDevice;
diff --git a/src/util/hostusb.c b/src/util/hostusb.c
index 92f52a2..cad0a6c 100644
--- a/src/util/hostusb.c
+++ b/src/util/hostusb.c
@@ -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,
+    USB_DEVICE_FIND_BY_BUS = 2,
+} 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,48 +126,71 @@ 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;
+
+        /*
+         * Don't set found to true in order to continue the loop
+         * to find multiple USB devices with same idVendor and idProduct
+         */
+        if (flags && !(flags & ~USB_DEVICE_FIND_BY_VENDOR))
+            if (found_prod != product || found_vend != vendor)
+                continue;
+
+        if (flags && !(flags & ~USB_DEVICE_FIND_BY_BUS)) {
+            if (found_bus != bus || found_devno != devno)
+                continue;
+            found = true;
+        }
 
-            if (STRPREFIX(de->d_name, "usb"))
-                tmpstr += 3;
+        if ((flags & USB_DEVICE_FIND_BY_BUS)
+             && (flags & USB_DEVICE_FIND_BY_VENDOR)) {
+            if (found_prod != product ||
+                found_vend != vendor  ||
+                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) {
@@ -160,12 +198,84 @@ cleanup:
         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 +317,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 +342,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..0c43e3f 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




More information about the libvir-list mailing list