From: "Daniel P. Berrange" <berrange@xxxxxxxxxx> --- 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@xxxxxxxxxx> - */ - -#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@xxxxxxxxxx> - * Michal Privoznik <mprivozn@xxxxxxxxxx> - */ - -#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@xxxxxxxxxx> + */ + +#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@xxxxxxxxxx> + * Michal Privoznik <mprivozn@xxxxxxxxxx> + */ + +#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@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list