From: "Daniel P. Berrange" <berra...@redhat.com>

---
 po/POTFILES.in                   |   2 +-
 src/Makefile.am                  |   2 +-
 src/qemu/qemu_cgroup.h           |   2 +-
 src/qemu/qemu_conf.h             |   2 +-
 src/qemu/qemu_driver.c           |   2 +-
 src/qemu/qemu_hostdev.c          |   2 +-
 src/security/security_apparmor.c |   2 +-
 src/security/security_dac.c      |   2 +-
 src/security/security_selinux.c  |   2 +-
 src/security/virt-aa-helper.c    |   2 +-
 src/util/hostusb.c               | 506 ---------------------------------------
 src/util/hostusb.h               |  87 -------
 src/util/virusb.c                | 506 +++++++++++++++++++++++++++++++++++++++
 src/util/virusb.h                |  87 +++++++
 14 files changed, 603 insertions(+), 603 deletions(-)
 delete mode 100644 src/util/hostusb.c
 delete mode 100644 src/util/hostusb.h
 create mode 100644 src/util/virusb.c
 create mode 100644 src/util/virusb.h

diff --git a/po/POTFILES.in b/po/POTFILES.in
index 18d96c8..3f3362c 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -137,7 +137,6 @@ src/storage/storage_driver.c
 src/test/test_driver.c
 src/uml/uml_conf.c
 src/uml/uml_driver.c
-src/util/hostusb.c
 src/util/iohelper.c
 src/util/iptables.c
 src/util/json.c
@@ -181,6 +180,7 @@ src/util/virterror_internal.h
 src/util/virtime.c
 src/util/virtypedparam.c
 src/util/viruri.c
+src/util/virusb.c
 src/util/xml.c
 src/vbox/vbox_MSCOMGlue.c
 src/vbox/vbox_XPCOMCGlue.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 07ace32..4f89bdc 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -59,7 +59,6 @@ UTIL_SOURCES =                                                
        \
                util/memory.c util/memory.h                     \
                util/pci.c util/pci.h                           \
                util/processinfo.c util/processinfo.h           \
-               util/hostusb.c util/hostusb.h                   \
                util/sexpr.c util/sexpr.h                       \
                util/stats_linux.c util/stats_linux.h           \
                util/storage_file.c util/storage_file.h         \
@@ -115,6 +114,7 @@ UTIL_SOURCES =                                              
        \
                util/virsocketaddr.h util/virsocketaddr.c \
                util/virstring.h util/virstring.c \
                util/virtime.h util/virtime.c \
+               util/virusb.c util/virusb.h                     \
                util/viruri.h util/viruri.c
 
 EXTRA_DIST += $(srcdir)/util/virkeymaps.h $(srcdir)/util/keymaps.csv \
diff --git a/src/qemu/qemu_cgroup.h b/src/qemu/qemu_cgroup.h
index e212581..75ef514 100644
--- a/src/qemu/qemu_cgroup.h
+++ b/src/qemu/qemu_cgroup.h
@@ -24,7 +24,7 @@
 #ifndef __QEMU_CGROUP_H__
 # define __QEMU_CGROUP_H__
 
-# include "hostusb.h"
+# include "virusb.h"
 # include "domain_conf.h"
 # include "qemu_conf.h"
 
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index 5499203..283251a 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -36,7 +36,7 @@
 # include "security/security_manager.h"
 # include "vircgroup.h"
 # include "pci.h"
-# include "hostusb.h"
+# include "virusb.h"
 # include "cpu_conf.h"
 # include "driver.h"
 # include "virbitmap.h"
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 0733f4e..79f42fb 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -73,7 +73,7 @@
 #include "domain_audit.h"
 #include "node_device_conf.h"
 #include "pci.h"
-#include "hostusb.h"
+#include "virusb.h"
 #include "processinfo.h"
 #include "libvirt_internal.h"
 #include "xml.h"
diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c
index a748b8b..aa000d1 100644
--- a/src/qemu/qemu_hostdev.c
+++ b/src/qemu/qemu_hostdev.c
@@ -28,7 +28,7 @@
 #include "virterror_internal.h"
 #include "memory.h"
 #include "pci.h"
-#include "hostusb.h"
+#include "virusb.h"
 #include "virnetdev.h"
 
 #define VIR_FROM_THIS VIR_FROM_QEMU
diff --git a/src/security/security_apparmor.c b/src/security/security_apparmor.c
index ff8aea1..034eb04 100644
--- a/src/security/security_apparmor.c
+++ b/src/security/security_apparmor.c
@@ -44,7 +44,7 @@
 #include "datatypes.h"
 #include "uuid.h"
 #include "pci.h"
-#include "hostusb.h"
+#include "virusb.h"
 #include "virfile.h"
 #include "configmake.h"
 #include "vircommand.h"
diff --git a/src/security/security_dac.c b/src/security/security_dac.c
index b07c132..9f5d39d 100644
--- a/src/security/security_dac.c
+++ b/src/security/security_dac.c
@@ -29,7 +29,7 @@
 #include "memory.h"
 #include "logging.h"
 #include "pci.h"
-#include "hostusb.h"
+#include "virusb.h"
 #include "storage_file.h"
 
 #define VIR_FROM_THIS VIR_FROM_SECURITY
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
index 287312a..eb4f253 100644
--- a/src/security/security_selinux.c
+++ b/src/security/security_selinux.c
@@ -38,7 +38,7 @@
 #include "memory.h"
 #include "logging.h"
 #include "pci.h"
-#include "hostusb.h"
+#include "virusb.h"
 #include "storage_file.h"
 #include "virfile.h"
 #include "virhash.h"
diff --git a/src/security/virt-aa-helper.c b/src/security/virt-aa-helper.c
index bfd6305..d92b3d4 100644
--- a/src/security/virt-aa-helper.c
+++ b/src/security/virt-aa-helper.c
@@ -50,7 +50,7 @@
 #include "domain_conf.h"
 #include "xml.h"
 #include "uuid.h"
-#include "hostusb.h"
+#include "virusb.h"
 #include "pci.h"
 #include "virfile.h"
 #include "configmake.h"
diff --git a/src/util/hostusb.c b/src/util/hostusb.c
deleted file mode 100644
index 81a9f5a..0000000
--- a/src/util/hostusb.c
+++ /dev/null
@@ -1,506 +0,0 @@
-/*
- * 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
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library.  If not, see
- * <http://www.gnu.org/licenses/>.
- *
- * Authors:
- *     Daniel P. Berrange <berra...@redhat.com>
- */
-
-#include <config.h>
-
-#include <dirent.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <limits.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#include "hostusb.h"
-#include "logging.h"
-#include "memory.h"
-#include "util.h"
-#include "virterror_internal.h"
-
-#define USB_SYSFS "/sys/bus/usb"
-#define USB_DEVFS "/dev/bus/usb/"
-#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
-
-struct _usbDevice {
-    unsigned int      bus;
-    unsigned int      dev;
-
-    char          name[USB_ADDR_LEN]; /* domain:bus:slot.function */
-    char          id[USB_ID_LEN];     /* product vendor */
-    char          *path;
-    const char    *used_by;           /* name of the domain using this dev */
-};
-
-struct _usbDeviceList {
-    unsigned int count;
-    usbDevice **devs;
-};
-
-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 int *value)
-{
-    int ret = -1, tmp;
-    char *buf = NULL;
-    char *filename = NULL;
-    char *ignore = NULL;
-
-    tmp = virAsprintf(&filename, USB_SYSFS "/devices/%s/%s", d_name, f_name);
-    if (tmp < 0) {
-        virReportOOMError();
-        goto cleanup;
-    }
-
-    if (virFileReadAll(filename, 1024, &buf) < 0)
-        goto cleanup;
-
-    if (virStrToLong_ui(buf, &ignore, base, value) < 0) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("Could not parse usb file %s"), filename);
-        goto cleanup;
-    }
-
-    ret = 0;
-cleanup:
-    VIR_FREE(filename);
-    VIR_FREE(buf);
-    return ret;
-}
-
-static usbDeviceList *
-usbDeviceSearch(unsigned int vendor,
-                unsigned int product,
-                unsigned int bus,
-                unsigned int devno,
-                unsigned int flags)
-{
-    DIR *dir = NULL;
-    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) {
-        virReportSystemError(errno,
-                             _("Could not open directory %s"),
-                             USB_SYSFS "/devices");
-        goto cleanup;
-    }
-
-    while ((de = readdir(dir))) {
-        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 (STRPREFIX(de->d_name, "usb"))
-            tmpstr += 3;
-
-        if (virStrToLong_ui(tmpstr, &ignore, 10, &found_bus) < 0) {
-            virReportError(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 (flags & USB_DEVICE_FIND_BY_BUS) {
-            if (found_bus != bus || found_devno != devno)
-                continue;
-            found = true;
-        }
-
-        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) {
-        int saved_errno = errno;
-        closedir(dir);
-        errno = saved_errno;
-    }
-
-    if (!ret)
-        usbDeviceListFree(list);
-    return ret;
-}
-
-int
-usbFindDeviceByVendor(unsigned int vendor,
-                      unsigned product,
-                      bool mandatory,
-                      usbDeviceList **devices)
-{
-    usbDeviceList *list;
-    int count;
-
-    if (!(list = usbDeviceSearch(vendor, product, 0 , 0,
-                                 USB_DEVICE_FIND_BY_VENDOR)))
-        return -1;
-
-    if (list->count == 0) {
-        usbDeviceListFree(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);
-        return -1;
-    }
-
-    count = list->count;
-    if (devices)
-        *devices = list;
-    else
-        usbDeviceListFree(list);
-
-    return count;
-}
-
-int
-usbFindDeviceByBus(unsigned int bus,
-                   unsigned devno,
-                   bool mandatory,
-                   usbDevice **usb)
-{
-    usbDeviceList *list;
-
-    if (!(list = usbDeviceSearch(0, 0, bus, devno,
-                                 USB_DEVICE_FIND_BY_BUS)))
-        return -1;
-
-    if (list->count == 0) {
-        usbDeviceListFree(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 = usbDeviceListGet(list, 0);
-        usbDeviceListSteal(list, *usb);
-    }
-    usbDeviceListFree(list);
-
-    return 0;
-}
-
-int
-usbFindDevice(unsigned int vendor,
-              unsigned int product,
-              unsigned int bus,
-              unsigned int devno,
-              bool mandatory,
-              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 -1;
-
-    if (list->count == 0) {
-        usbDeviceListFree(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 = usbDeviceListGet(list, 0);
-        usbDeviceListSteal(list, *usb);
-    }
-    usbDeviceListFree(list);
-
-    return 0;
-}
-
-usbDevice *
-usbGetDevice(unsigned int bus,
-             unsigned int devno)
-{
-    usbDevice *dev;
-
-    if (VIR_ALLOC(dev) < 0) {
-        virReportOOMError();
-        return NULL;
-    }
-
-    dev->bus     = bus;
-    dev->dev     = devno;
-
-    if (snprintf(dev->name, sizeof(dev->name), "%.3o:%.3o",
-                 dev->bus, dev->dev) >= sizeof(dev->name)) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("dev->name buffer overflow: %.3o:%.3o"),
-                       dev->bus, dev->dev);
-        usbFreeDevice(dev);
-        return NULL;
-    }
-    if (virAsprintf(&dev->path, USB_DEVFS "%03d/%03d",
-                    dev->bus, dev->dev) < 0) {
-        virReportOOMError();
-        usbFreeDevice(dev);
-        return NULL;
-    }
-
-    /* XXX fixme. this should be product/vendor */
-    if (snprintf(dev->id, sizeof(dev->id), "%d %d", dev->bus,
-                 dev->dev) >= sizeof(dev->id)) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("dev->id buffer overflow: %d %d"),
-                       dev->bus, dev->dev);
-        usbFreeDevice(dev);
-        return NULL;
-    }
-
-    VIR_DEBUG("%s %s: initialized", dev->id, dev->name);
-
-    return dev;
-}
-
-void
-usbFreeDevice(usbDevice *dev)
-{
-    VIR_DEBUG("%s %s: freeing", dev->id, dev->name);
-    VIR_FREE(dev->path);
-    VIR_FREE(dev);
-}
-
-
-void usbDeviceSetUsedBy(usbDevice *dev,
-                        const char *name)
-{
-    dev->used_by = name;
-}
-
-const char * usbDeviceGetUsedBy(usbDevice *dev)
-{
-    return dev->used_by;
-}
-
-const char *usbDeviceGetName(usbDevice *dev)
-{
-    return dev->name;
-}
-
-unsigned int usbDeviceGetBus(usbDevice *dev)
-{
-    return dev->bus;
-}
-
-
-unsigned int usbDeviceGetDevno(usbDevice *dev)
-{
-    return dev->dev;
-}
-
-
-int usbDeviceFileIterate(usbDevice *dev,
-                         usbDeviceFileActor actor,
-                         void *opaque)
-{
-    return (actor)(dev, dev->path, opaque);
-}
-
-usbDeviceList *
-usbDeviceListNew(void)
-{
-    usbDeviceList *list;
-
-    if (VIR_ALLOC(list) < 0) {
-        virReportOOMError();
-        return NULL;
-    }
-
-    return list;
-}
-
-void
-usbDeviceListFree(usbDeviceList *list)
-{
-    int i;
-
-    if (!list)
-        return;
-
-    for (i = 0; i < list->count; i++)
-        usbFreeDevice(list->devs[i]);
-
-    VIR_FREE(list->devs);
-    VIR_FREE(list);
-}
-
-int
-usbDeviceListAdd(usbDeviceList *list,
-                 usbDevice *dev)
-{
-    if (usbDeviceListFind(list, dev)) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("Device %s is already in use"),
-                       dev->name);
-        return -1;
-    }
-
-    if (VIR_REALLOC_N(list->devs, list->count+1) < 0) {
-        virReportOOMError();
-        return -1;
-    }
-
-    list->devs[list->count++] = dev;
-
-    return 0;
-}
-
-usbDevice *
-usbDeviceListGet(usbDeviceList *list,
-                 int idx)
-{
-    if (idx >= list->count ||
-        idx < 0)
-        return NULL;
-
-    return list->devs[idx];
-}
-
-int
-usbDeviceListCount(usbDeviceList *list)
-{
-    return list->count;
-}
-
-usbDevice *
-usbDeviceListSteal(usbDeviceList *list,
-                   usbDevice *dev)
-{
-    usbDevice *ret = NULL;
-    int i;
-
-    for (i = 0; i < list->count; i++) {
-        if (list->devs[i]->bus != dev->bus ||
-            list->devs[i]->dev != dev->dev)
-            continue;
-
-        ret = list->devs[i];
-
-        if (i != list->count--)
-            memmove(&list->devs[i],
-                    &list->devs[i+1],
-                    sizeof(*list->devs) * (list->count - i));
-
-        if (VIR_REALLOC_N(list->devs, list->count) < 0) {
-            ; /* not fatal */
-        }
-
-        break;
-    }
-    return ret;
-}
-
-void
-usbDeviceListDel(usbDeviceList *list,
-                 usbDevice *dev)
-{
-    usbDevice *ret = usbDeviceListSteal(list, dev);
-    if (ret)
-        usbFreeDevice(ret);
-}
-
-usbDevice *
-usbDeviceListFind(usbDeviceList *list,
-                  usbDevice *dev)
-{
-    int i;
-
-    for (i = 0; i < list->count; i++) {
-        if (list->devs[i]->bus == dev->bus &&
-            list->devs[i]->dev == dev->dev)
-            return list->devs[i];
-    }
-
-    return NULL;
-}
diff --git a/src/util/hostusb.h b/src/util/hostusb.h
deleted file mode 100644
index 4f55fdc..0000000
--- a/src/util/hostusb.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2009 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
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library.  If not, see
- * <http://www.gnu.org/licenses/>.
- *
- * Authors:
- *     Daniel P. Berrange <berra...@redhat.com>
- *     Michal Privoznik <mpriv...@redhat.com>
- */
-
-#ifndef __VIR_USB_H__
-# define __VIR_USB_H__
-
-# include "internal.h"
-
-typedef struct _usbDevice usbDevice;
-typedef struct _usbDeviceList usbDeviceList;
-
-usbDevice *usbGetDevice(unsigned int bus,
-                        unsigned int devno);
-
-int usbFindDeviceByBus(unsigned int bus,
-                       unsigned int devno,
-                       bool mandatory,
-                       usbDevice **usb);
-
-int usbFindDeviceByVendor(unsigned int vendor,
-                          unsigned int product,
-                          bool mandatory,
-                          usbDeviceList **devices);
-
-int usbFindDevice(unsigned int vendor,
-                  unsigned int product,
-                  unsigned int bus,
-                  unsigned int devno,
-                  bool mandatory,
-                  usbDevice **usb);
-
-void       usbFreeDevice (usbDevice *dev);
-void       usbDeviceSetUsedBy(usbDevice *dev, const char *name);
-const char *usbDeviceGetUsedBy(usbDevice *dev);
-const char *usbDeviceGetName(usbDevice *dev);
-
-unsigned int usbDeviceGetBus(usbDevice *dev);
-unsigned int usbDeviceGetDevno(usbDevice *dev);
-
-/*
- * Callback that will be invoked once for each file
- * associated with / used for USB host device access.
- *
- * Should return 0 if successfully processed, or
- * -1 to indicate error and abort iteration
- */
-typedef int (*usbDeviceFileActor)(usbDevice *dev,
-                                  const char *path, void *opaque);
-
-int usbDeviceFileIterate(usbDevice *dev,
-                         usbDeviceFileActor actor,
-                         void *opaque);
-
-usbDeviceList *usbDeviceListNew(void);
-void           usbDeviceListFree(usbDeviceList *list);
-int            usbDeviceListAdd(usbDeviceList *list,
-                                usbDevice *dev);
-usbDevice *    usbDeviceListGet(usbDeviceList *list,
-                                int idx);
-int            usbDeviceListCount(usbDeviceList *list);
-usbDevice *    usbDeviceListSteal(usbDeviceList *list,
-                                  usbDevice *dev);
-void           usbDeviceListDel(usbDeviceList *list,
-                                usbDevice *dev);
-usbDevice *    usbDeviceListFind(usbDeviceList *list,
-                                 usbDevice *dev);
-
-#endif /* __VIR_USB_H__ */
diff --git a/src/util/virusb.c b/src/util/virusb.c
new file mode 100644
index 0000000..b9c81ed
--- /dev/null
+++ b/src/util/virusb.c
@@ -0,0 +1,506 @@
+/*
+ * 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
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *     Daniel P. Berrange <berra...@redhat.com>
+ */
+
+#include <config.h>
+
+#include <dirent.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "virusb.h"
+#include "logging.h"
+#include "memory.h"
+#include "util.h"
+#include "virterror_internal.h"
+
+#define USB_SYSFS "/sys/bus/usb"
+#define USB_DEVFS "/dev/bus/usb/"
+#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
+
+struct _usbDevice {
+    unsigned int      bus;
+    unsigned int      dev;
+
+    char          name[USB_ADDR_LEN]; /* domain:bus:slot.function */
+    char          id[USB_ID_LEN];     /* product vendor */
+    char          *path;
+    const char    *used_by;           /* name of the domain using this dev */
+};
+
+struct _usbDeviceList {
+    unsigned int count;
+    usbDevice **devs;
+};
+
+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 int *value)
+{
+    int ret = -1, tmp;
+    char *buf = NULL;
+    char *filename = NULL;
+    char *ignore = NULL;
+
+    tmp = virAsprintf(&filename, USB_SYSFS "/devices/%s/%s", d_name, f_name);
+    if (tmp < 0) {
+        virReportOOMError();
+        goto cleanup;
+    }
+
+    if (virFileReadAll(filename, 1024, &buf) < 0)
+        goto cleanup;
+
+    if (virStrToLong_ui(buf, &ignore, base, value) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Could not parse usb file %s"), filename);
+        goto cleanup;
+    }
+
+    ret = 0;
+cleanup:
+    VIR_FREE(filename);
+    VIR_FREE(buf);
+    return ret;
+}
+
+static usbDeviceList *
+usbDeviceSearch(unsigned int vendor,
+                unsigned int product,
+                unsigned int bus,
+                unsigned int devno,
+                unsigned int flags)
+{
+    DIR *dir = NULL;
+    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) {
+        virReportSystemError(errno,
+                             _("Could not open directory %s"),
+                             USB_SYSFS "/devices");
+        goto cleanup;
+    }
+
+    while ((de = readdir(dir))) {
+        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 (STRPREFIX(de->d_name, "usb"))
+            tmpstr += 3;
+
+        if (virStrToLong_ui(tmpstr, &ignore, 10, &found_bus) < 0) {
+            virReportError(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 (flags & USB_DEVICE_FIND_BY_BUS) {
+            if (found_bus != bus || found_devno != devno)
+                continue;
+            found = true;
+        }
+
+        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) {
+        int saved_errno = errno;
+        closedir(dir);
+        errno = saved_errno;
+    }
+
+    if (!ret)
+        usbDeviceListFree(list);
+    return ret;
+}
+
+int
+usbFindDeviceByVendor(unsigned int vendor,
+                      unsigned product,
+                      bool mandatory,
+                      usbDeviceList **devices)
+{
+    usbDeviceList *list;
+    int count;
+
+    if (!(list = usbDeviceSearch(vendor, product, 0 , 0,
+                                 USB_DEVICE_FIND_BY_VENDOR)))
+        return -1;
+
+    if (list->count == 0) {
+        usbDeviceListFree(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);
+        return -1;
+    }
+
+    count = list->count;
+    if (devices)
+        *devices = list;
+    else
+        usbDeviceListFree(list);
+
+    return count;
+}
+
+int
+usbFindDeviceByBus(unsigned int bus,
+                   unsigned devno,
+                   bool mandatory,
+                   usbDevice **usb)
+{
+    usbDeviceList *list;
+
+    if (!(list = usbDeviceSearch(0, 0, bus, devno,
+                                 USB_DEVICE_FIND_BY_BUS)))
+        return -1;
+
+    if (list->count == 0) {
+        usbDeviceListFree(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 = usbDeviceListGet(list, 0);
+        usbDeviceListSteal(list, *usb);
+    }
+    usbDeviceListFree(list);
+
+    return 0;
+}
+
+int
+usbFindDevice(unsigned int vendor,
+              unsigned int product,
+              unsigned int bus,
+              unsigned int devno,
+              bool mandatory,
+              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 -1;
+
+    if (list->count == 0) {
+        usbDeviceListFree(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 = usbDeviceListGet(list, 0);
+        usbDeviceListSteal(list, *usb);
+    }
+    usbDeviceListFree(list);
+
+    return 0;
+}
+
+usbDevice *
+usbGetDevice(unsigned int bus,
+             unsigned int devno)
+{
+    usbDevice *dev;
+
+    if (VIR_ALLOC(dev) < 0) {
+        virReportOOMError();
+        return NULL;
+    }
+
+    dev->bus     = bus;
+    dev->dev     = devno;
+
+    if (snprintf(dev->name, sizeof(dev->name), "%.3o:%.3o",
+                 dev->bus, dev->dev) >= sizeof(dev->name)) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("dev->name buffer overflow: %.3o:%.3o"),
+                       dev->bus, dev->dev);
+        usbFreeDevice(dev);
+        return NULL;
+    }
+    if (virAsprintf(&dev->path, USB_DEVFS "%03d/%03d",
+                    dev->bus, dev->dev) < 0) {
+        virReportOOMError();
+        usbFreeDevice(dev);
+        return NULL;
+    }
+
+    /* XXX fixme. this should be product/vendor */
+    if (snprintf(dev->id, sizeof(dev->id), "%d %d", dev->bus,
+                 dev->dev) >= sizeof(dev->id)) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("dev->id buffer overflow: %d %d"),
+                       dev->bus, dev->dev);
+        usbFreeDevice(dev);
+        return NULL;
+    }
+
+    VIR_DEBUG("%s %s: initialized", dev->id, dev->name);
+
+    return dev;
+}
+
+void
+usbFreeDevice(usbDevice *dev)
+{
+    VIR_DEBUG("%s %s: freeing", dev->id, dev->name);
+    VIR_FREE(dev->path);
+    VIR_FREE(dev);
+}
+
+
+void usbDeviceSetUsedBy(usbDevice *dev,
+                        const char *name)
+{
+    dev->used_by = name;
+}
+
+const char * usbDeviceGetUsedBy(usbDevice *dev)
+{
+    return dev->used_by;
+}
+
+const char *usbDeviceGetName(usbDevice *dev)
+{
+    return dev->name;
+}
+
+unsigned int usbDeviceGetBus(usbDevice *dev)
+{
+    return dev->bus;
+}
+
+
+unsigned int usbDeviceGetDevno(usbDevice *dev)
+{
+    return dev->dev;
+}
+
+
+int usbDeviceFileIterate(usbDevice *dev,
+                         usbDeviceFileActor actor,
+                         void *opaque)
+{
+    return (actor)(dev, dev->path, opaque);
+}
+
+usbDeviceList *
+usbDeviceListNew(void)
+{
+    usbDeviceList *list;
+
+    if (VIR_ALLOC(list) < 0) {
+        virReportOOMError();
+        return NULL;
+    }
+
+    return list;
+}
+
+void
+usbDeviceListFree(usbDeviceList *list)
+{
+    int i;
+
+    if (!list)
+        return;
+
+    for (i = 0; i < list->count; i++)
+        usbFreeDevice(list->devs[i]);
+
+    VIR_FREE(list->devs);
+    VIR_FREE(list);
+}
+
+int
+usbDeviceListAdd(usbDeviceList *list,
+                 usbDevice *dev)
+{
+    if (usbDeviceListFind(list, dev)) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Device %s is already in use"),
+                       dev->name);
+        return -1;
+    }
+
+    if (VIR_REALLOC_N(list->devs, list->count+1) < 0) {
+        virReportOOMError();
+        return -1;
+    }
+
+    list->devs[list->count++] = dev;
+
+    return 0;
+}
+
+usbDevice *
+usbDeviceListGet(usbDeviceList *list,
+                 int idx)
+{
+    if (idx >= list->count ||
+        idx < 0)
+        return NULL;
+
+    return list->devs[idx];
+}
+
+int
+usbDeviceListCount(usbDeviceList *list)
+{
+    return list->count;
+}
+
+usbDevice *
+usbDeviceListSteal(usbDeviceList *list,
+                   usbDevice *dev)
+{
+    usbDevice *ret = NULL;
+    int i;
+
+    for (i = 0; i < list->count; i++) {
+        if (list->devs[i]->bus != dev->bus ||
+            list->devs[i]->dev != dev->dev)
+            continue;
+
+        ret = list->devs[i];
+
+        if (i != list->count--)
+            memmove(&list->devs[i],
+                    &list->devs[i+1],
+                    sizeof(*list->devs) * (list->count - i));
+
+        if (VIR_REALLOC_N(list->devs, list->count) < 0) {
+            ; /* not fatal */
+        }
+
+        break;
+    }
+    return ret;
+}
+
+void
+usbDeviceListDel(usbDeviceList *list,
+                 usbDevice *dev)
+{
+    usbDevice *ret = usbDeviceListSteal(list, dev);
+    if (ret)
+        usbFreeDevice(ret);
+}
+
+usbDevice *
+usbDeviceListFind(usbDeviceList *list,
+                  usbDevice *dev)
+{
+    int i;
+
+    for (i = 0; i < list->count; i++) {
+        if (list->devs[i]->bus == dev->bus &&
+            list->devs[i]->dev == dev->dev)
+            return list->devs[i];
+    }
+
+    return NULL;
+}
diff --git a/src/util/virusb.h b/src/util/virusb.h
new file mode 100644
index 0000000..4f55fdc
--- /dev/null
+++ b/src/util/virusb.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2009 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
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *     Daniel P. Berrange <berra...@redhat.com>
+ *     Michal Privoznik <mpriv...@redhat.com>
+ */
+
+#ifndef __VIR_USB_H__
+# define __VIR_USB_H__
+
+# include "internal.h"
+
+typedef struct _usbDevice usbDevice;
+typedef struct _usbDeviceList usbDeviceList;
+
+usbDevice *usbGetDevice(unsigned int bus,
+                        unsigned int devno);
+
+int usbFindDeviceByBus(unsigned int bus,
+                       unsigned int devno,
+                       bool mandatory,
+                       usbDevice **usb);
+
+int usbFindDeviceByVendor(unsigned int vendor,
+                          unsigned int product,
+                          bool mandatory,
+                          usbDeviceList **devices);
+
+int usbFindDevice(unsigned int vendor,
+                  unsigned int product,
+                  unsigned int bus,
+                  unsigned int devno,
+                  bool mandatory,
+                  usbDevice **usb);
+
+void       usbFreeDevice (usbDevice *dev);
+void       usbDeviceSetUsedBy(usbDevice *dev, const char *name);
+const char *usbDeviceGetUsedBy(usbDevice *dev);
+const char *usbDeviceGetName(usbDevice *dev);
+
+unsigned int usbDeviceGetBus(usbDevice *dev);
+unsigned int usbDeviceGetDevno(usbDevice *dev);
+
+/*
+ * Callback that will be invoked once for each file
+ * associated with / used for USB host device access.
+ *
+ * Should return 0 if successfully processed, or
+ * -1 to indicate error and abort iteration
+ */
+typedef int (*usbDeviceFileActor)(usbDevice *dev,
+                                  const char *path, void *opaque);
+
+int usbDeviceFileIterate(usbDevice *dev,
+                         usbDeviceFileActor actor,
+                         void *opaque);
+
+usbDeviceList *usbDeviceListNew(void);
+void           usbDeviceListFree(usbDeviceList *list);
+int            usbDeviceListAdd(usbDeviceList *list,
+                                usbDevice *dev);
+usbDevice *    usbDeviceListGet(usbDeviceList *list,
+                                int idx);
+int            usbDeviceListCount(usbDeviceList *list);
+usbDevice *    usbDeviceListSteal(usbDeviceList *list,
+                                  usbDevice *dev);
+void           usbDeviceListDel(usbDeviceList *list,
+                                usbDevice *dev);
+usbDevice *    usbDeviceListFind(usbDeviceList *list,
+                                 usbDevice *dev);
+
+#endif /* __VIR_USB_H__ */
-- 
1.7.11.7

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

Reply via email to