From: "Daniel P. Berrange" <berrange(a)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 <berrange(a)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 <berrange(a)redhat.com>
- * Michal Privoznik <mprivozn(a)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 <berrange(a)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 <berrange(a)redhat.com>
+ * Michal Privoznik <mprivozn(a)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