[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH RFC V2 3/5] libxl: add pvusb API



On 01/19/2015 09:28 AM, Chunyan Liu wrote:
Add pvusb APIs, including:
  - attach/detach (create/destroy) virtual usb controller.
  - attach/detach usb device
  - list assignable usb devices in host
  - some other helper functions

Signed-off-by: Chunyan Liu <cyliu@xxxxxxxx>
Signed-off-by: Simon Cao <caobosimon@xxxxxxxxx>
---
  tools/libxl/Makefile         |    2 +-
  tools/libxl/libxl.c          |    2 +
  tools/libxl/libxl.h          |   58 ++
  tools/libxl/libxl_internal.h |    6 +
  tools/libxl/libxl_usb.c      | 1277 ++++++++++++++++++++++++++++++++++++++++++
  tools/libxl/libxlu_cfg_y.c   |  464 ++++++++-------
  tools/libxl/libxlu_cfg_y.h   |   38 +-
  7 files changed, 1623 insertions(+), 224 deletions(-)
  create mode 100644 tools/libxl/libxl_usb.c

diff --git a/tools/libxl/Makefile b/tools/libxl/Makefile
index b417372..08cdb12 100644
--- a/tools/libxl/Makefile
+++ b/tools/libxl/Makefile
@@ -95,7 +95,7 @@ LIBXL_OBJS = flexarray.o libxl.o libxl_create.o libxl_dm.o 
libxl_pci.o \
                        libxl_internal.o libxl_utils.o libxl_uuid.o \
                        libxl_json.o libxl_aoutils.o libxl_numa.o \
                        libxl_save_callout.o _libxl_save_msgs_callout.o \
-                       libxl_qmp.o libxl_event.o libxl_fork.o $(LIBXL_OBJS-y)
+                       libxl_qmp.o libxl_event.o libxl_fork.o libxl_usb.o 
$(LIBXL_OBJS-y)
  LIBXL_OBJS += libxl_genid.o
  LIBXL_OBJS += _libxl_types.o libxl_flask.o _libxl_types_internal.o

diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 3cd13db..dd76ac3 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -1594,6 +1594,8 @@ void libxl__destroy_domid(libxl__egc *egc, 
libxl__destroy_domid_state *dis)

      if (libxl__device_pci_destroy_all(gc, domid) < 0)
          LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "pci shutdown failed for domid %d", 
domid);
+    if (libxl__device_usb_destroy_all(gc, domid) < 0)
+         LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "usb shutdown failed for domid %d", 
domid);
      rc = xc_domain_pause(ctx->xch, domid);
      if (rc < 0) {
          LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc, "xc_domain_pause failed for 
%d", domid);
diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
index 0a123f1..2e89244 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -98,6 +98,12 @@
  #define LIBXL_HAVE_DOMAIN_NODEAFFINITY 1

  /*
+ * LIBXL_HAVE_DEVICE_USB indicates the functions for doing hot-plug of
+ * USB devices.
+ */
+#define LIBXL_HAVE_DEVICE_USB 1
+
+/*
   * LIBXL_HAVE_BUILDINFO_HVM_VENDOR_DEVICE indicates that the
   * libxl_vendor_device field is present in the hvm sections of
   * libxl_domain_build_info. This field tells libxl which
@@ -1168,6 +1174,56 @@ int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, 
libxl_device_disk *disk,
                         const libxl_asyncop_how *ao_how)
                         LIBXL_EXTERNAL_CALLERS_ONLY;

+/* USB Controllers*/
+int libxl_device_usbctrl_add(libxl_ctx *ctx, uint32_t domid,
+                         libxl_device_usbctrl *usbctrl,
+                         const libxl_asyncop_how *ao_how)
+                         LIBXL_EXTERNAL_CALLERS_ONLY;
+
+int libxl_device_usbctrl_remove(libxl_ctx *ctx, uint32_t domid,
+                         libxl_device_usbctrl *usbctrl,
+                         const libxl_asyncop_how *ao_how)
+                         LIBXL_EXTERNAL_CALLERS_ONLY;
+
+int libxl_device_usbctrl_destroy(libxl_ctx *ctx, uint32_t domid,
+                         libxl_device_usbctrl *usbctrl,
+                         const libxl_asyncop_how *ao_how)
+                         LIBXL_EXTERNAL_CALLERS_ONLY;
+
+libxl_device_usbctrl *libxl_device_usbctrl_list(libxl_ctx *ctx,
+                            uint32_t domid, int *num);
+
+int libxl_devid_to_device_usbctrl(libxl_ctx *ctx, uint32_t domid,
+                            int devid, libxl_device_usbctrl *usbctrl)
+                            LIBXL_EXTERNAL_CALLERS_ONLY;
+
+int libxl_device_usbctrl_getinfo(libxl_ctx *ctx, uint32_t domid,
+                                libxl_device_usbctrl *usbctrl,
+                                libxl_usbctrlinfo *usbctrlinfo)
+                                LIBXL_EXTERNAL_CALLERS_ONLY;
+
+/* USB Devices */
+int libxl_device_usb_add(libxl_ctx *ctx, uint32_t domid, libxl_device_usb *usb,
+                         const libxl_asyncop_how *ao_how)
+                         LIBXL_EXTERNAL_CALLERS_ONLY;
+
+int libxl_device_usb_remove(libxl_ctx *ctx, uint32_t domid, libxl_device_usb 
*usb,
+                            const libxl_asyncop_how *ao_how)
+                            LIBXL_EXTERNAL_CALLERS_ONLY;
+
+int libxl_device_usb_destroy(libxl_ctx *ctx, uint32_t domid, libxl_device_usb 
*usb,
+                            const libxl_asyncop_how *ao_how)
+                            LIBXL_EXTERNAL_CALLERS_ONLY;
+
+libxl_device_usb *libxl_device_usb_list(libxl_ctx *ctx, uint32_t domid,
+                                        int usbctrl, int *num);
+
+int libxl_intf_to_device_usb(libxl_ctx *ctx, uint32_t domid,
+                            char *intf, libxl_device_usb *usb)
+                            LIBXL_EXTERNAL_CALLERS_ONLY;
+
+int libxl_device_usb_getinfo(libxl_ctx *ctx, char *intf, libxl_usbinfo 
*usbinfo)
+                             LIBXL_EXTERNAL_CALLERS_ONLY;
  /* Network Interfaces */
  int libxl_device_nic_add(libxl_ctx *ctx, uint32_t domid, libxl_device_nic 
*nic,
                           const libxl_asyncop_how *ao_how)
@@ -1294,6 +1350,8 @@ int libxl_device_pci_assignable_add(libxl_ctx *ctx, 
libxl_device_pci *pcidev, in
  int libxl_device_pci_assignable_remove(libxl_ctx *ctx, libxl_device_pci 
*pcidev, int rebind);
  libxl_device_pci *libxl_device_pci_assignable_list(libxl_ctx *ctx, int *num);

+libxl_device_usb *libxl_device_usb_assignable_list(libxl_ctx *ctx, int *num);
+
  /* CPUID handling */
  int libxl_cpuid_parse_config(libxl_cpuid_policy_list *cpuid, const char* str);
  int libxl_cpuid_parse_config_xend(libxl_cpuid_policy_list *cpuid,
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index bcf43fb..dba1326 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -2395,6 +2395,11 @@ _hidden void libxl__device_vtpm_add(libxl__egc *egc, 
uint32_t domid,
                                     libxl_device_vtpm *vtpm,
                                     libxl__ao_device *aodev);

+/* from libxl_usb */
+_hidden int libxl__device_usb_add(libxl__gc *gc, uint32_t domid,
+                            libxl_device_usb *usb);
+_hidden int libxl__device_usb_destroy_all(libxl__gc *gc, uint32_t domid);
+
  /* Internal function to connect a vkb device */
  _hidden int libxl__device_vkb_add(libxl__gc *gc, uint32_t domid,
                                    libxl_device_vkb *vkb);
@@ -3574,6 +3579,7 @@ static inline void libxl__update_config_vtpm(libxl__gc 
*gc,
  #define COMPARE_PCI(a, b) ((a)->func == (b)->func &&    \
                             (a)->bus == (b)->bus &&      \
                             (a)->dev == (b)->dev)
+#define COMPARE_USB(a, b) (!strcmp((a)->intf, (b)->intf))

  /* DEVICE_ADD
   *
diff --git a/tools/libxl/libxl_usb.c b/tools/libxl/libxl_usb.c
new file mode 100644
index 0000000..830a846
--- /dev/null
+++ b/tools/libxl/libxl_usb.c
@@ -0,0 +1,1277 @@
+/*
+ * This program 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; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program 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.
+ */
+
+#include "libxl_osdeps.h" /* must come before any other headers */
+
+#include "libxl_internal.h"
+
+#define SYSFS_USB_DEVS_PATH "/sys/bus/usb/devices"
+#define SYSFS_USBBACK_DRIVER "/sys/bus/usb/drivers/usbback"
+#define USBBACK_INFO_PATH "/libxl/usbback"
+
+#define USBHUB_CLASS_CODE "09"
+
+static int libxl__device_usbctrl_setdefault(libxl__gc *gc, uint32_t domid,
+                                            libxl_device_usbctrl *usbctrl)
+{
+    int rc;
+
+    if (!usbctrl->usb_version)
+        usbctrl->usb_version = 2;
+
+    if (!usbctrl->num_ports)
+        usbctrl->num_ports = 8;
+
+    if(!usbctrl->backend_domid)
+        usbctrl->backend_domid = 0;

Just use a comment?

+
+    if (!usbctrl->type)
+        usbctrl->type = LIBXL_USBCTRL_TYPE_PV;
+
+    rc = libxl__resolve_domid(gc, usbctrl->backend_domname,
+                              &usbctrl->backend_domid);
+
+    return rc;
+}
+
+static int libxl__device_from_usbctrl(libxl__gc *gc, uint32_t domid,
+                                      libxl_device_usbctrl *usbctrl,
+                                      libxl__device *device)

Make function type void?

+{
+    device->backend_devid   = usbctrl->devid;
+    device->backend_domid   = usbctrl->backend_domid;
+    device->backend_kind    = LIBXL__DEVICE_KIND_VUSB;
+    device->devid           = usbctrl->devid;
+    device->domid           = domid;
+    device->kind            = LIBXL__DEVICE_KIND_VUSB;
+
+    return 0;
+}
+
+static int libxl__usbport_add_xenstore(libxl__gc *gc,
+                                       xs_transaction_t tran,
+                                       uint32_t domid,
+                                       libxl_device_usbctrl *usbctrl)
+{
+    char *path;
+    int i;
+
+    path = GCSPRINTF("%s/backend/vusb/%d/%d/port",
+                     libxl__xs_get_dompath(gc, 0), domid, usbctrl->devid);
+
+    libxl__xs_mkdir(gc, tran, path, NULL, 0);
+
+    for (i = 1; i <= usbctrl->num_ports; i++) {
+        if (libxl__xs_write_checked(gc, tran, GCSPRINTF("%s/%d", path, i), ""))
+            return ERROR_FAIL;
+    }
+
+    return 0;
+}
+
+static int libxl__usbctrl_add_xenstore(libxl__gc *gc, uint32_t domid,
+                                       libxl_device_usbctrl *usbctrl)
+{
+    libxl_ctx *ctx = libxl__gc_owner(gc);
+    flexarray_t *front;
+    flexarray_t *back;
+    libxl__device *device;
+    xs_transaction_t tran;
+    int rc = 0;
+
+    GCNEW(device);
+    rc = libxl__device_from_usbctrl(gc, domid, usbctrl, device);
+    if (rc) goto out;
+
+    front = flexarray_make(gc, 4, 1);
+    back = flexarray_make(gc, 12, 1);
+
+    flexarray_append(back, "frontend-id");
+    flexarray_append(back, libxl__sprintf(gc, "%d", domid));
+    flexarray_append(back, "online");
+    flexarray_append(back, "1");
+    flexarray_append(back, "state");
+    flexarray_append(back, libxl__sprintf(gc, "%d", 1));
+    flexarray_append(back, "usb-ver");
+    flexarray_append(back, libxl__sprintf(gc, "%d", usbctrl->usb_version));
+    flexarray_append(back, "num-ports");
+    flexarray_append(back, libxl__sprintf(gc, "%d", usbctrl->num_ports));
+    flexarray_append(back, "type");
+    switch(usbctrl->type) {
+    case LIBXL_USBCTRL_TYPE_PV:{
+        flexarray_append(back, "PVUSB");
+        break;
+    }
+    case LIBXL_USBCTRL_TYPE_DEVICEMODEL: {
+        flexarray_append(back, "IOEMU");
+        break;
+    }
+    default:
+        /* not supported */
+        rc = ERROR_FAIL;
+        goto out;
+    }
+
+    flexarray_append(front, "backend-id");
+    flexarray_append(front, libxl__sprintf(gc, "%d", usbctrl->backend_domid));
+    flexarray_append(front, "state");
+    flexarray_append(front, libxl__sprintf(gc, "%d", 1));
+
+retry_transaction:
+    tran = xs_transaction_start(ctx->xsh);
+
+    libxl__device_generic_add(gc, tran, device,
+                              libxl__xs_kvs_of_flexarray(gc, back, 
back->count),
+                              libxl__xs_kvs_of_flexarray(gc, front, 
front->count),
+                              NULL);
+    libxl__usbport_add_xenstore(gc, tran, domid, usbctrl);

No check of rc?

+
+    if (!xs_transaction_end(ctx->xsh, tran, 0)) {
+        if (errno == EAGAIN)
+            goto retry_transaction;
+        else {
+            rc = ERROR_FAIL;
+            goto out;
+        }
+    }
+
+out:
+    return rc;
+}
+
+static int libxl__device_usbctrl_add(libxl__gc *gc, uint32_t domid,
+                                     libxl_device_usbctrl *usbctrl)
+{
+    int rc = 0;
+
+    rc = libxl__device_usbctrl_setdefault(gc, domid, usbctrl);
+    if(rc) goto out;

Coding style.

+
+    if (usbctrl->devid == -1) {
+        if ((usbctrl->devid = libxl__device_nextid(gc, domid, "vusb")) < 0) {

Combine above 2 ifs in one?

+            rc = ERROR_FAIL;
+            goto out;
+        }
+    }
+
+    if (libxl__usbctrl_add_xenstore(gc, domid, usbctrl) < 0){
+        rc = ERROR_FAIL;
+        goto out;
+    }
+
+out:
+    return rc;
+}
+
+int libxl_device_usbctrl_add(libxl_ctx *ctx, uint32_t domid,
+                             libxl_device_usbctrl *usbctrl,
+                             const libxl_asyncop_how *ao_how)
+{
+    AO_CREATE(ctx, domid, ao_how);
+    int rc;
+
+    rc = libxl__device_usbctrl_add(gc, domid, usbctrl);
+    libxl__ao_complete(egc, ao, rc);
+    return AO_INPROGRESS;
+}
+
+libxl_device_usbctrl *
+libxl_device_usbctrl_list(libxl_ctx *ctx, uint32_t domid, int *num)
+{
+    GC_INIT(ctx);
+
+    libxl_device_usbctrl *usbctrls = NULL;
+    char *fe_path = NULL;
+    char **dir = NULL;
+    unsigned int ndirs = 0;
+
+    *num = 0;
+
+    fe_path = libxl__sprintf(gc, "%s/device/vusb",
+                             libxl__xs_get_dompath(gc, domid));
+    dir = libxl__xs_directory(gc, XBT_NULL, fe_path, &ndirs);
+
+    if (dir && ndirs) {
+        usbctrls = malloc(sizeof(*usbctrls) * ndirs);
+        libxl_device_usbctrl* usbctrl;
+        libxl_device_usbctrl* end = usbctrls + ndirs;
+        for(usbctrl = usbctrls; usbctrl < end; usbctrl++, dir++, (*num)++) {

Coding style.

Why (*num)++? *num is set at end of loop.

+            char *tmp;
+            const char *be_path = libxl__xs_read(gc, XBT_NULL,
+                                    GCSPRINTF("%s/%s/backend", fe_path, *dir));
+
+            libxl_device_usbctrl_init(usbctrl);
+
+            usbctrl->devid = atoi(*dir);
+
+            tmp = libxl__xs_read(gc, XBT_NULL,
+                                 GCSPRINTF("%s/%s/backend-id", fe_path, *dir));
+            if (!tmp) goto outerr;
+            usbctrl->backend_domid = atoi(tmp);
+
+            tmp = libxl__xs_read(gc, XBT_NULL,
+                                 GCSPRINTF("%s/usb-ver", be_path));
+            if (!tmp) goto outerr;
+            usbctrl->usb_version = atoi(tmp);
+
+            tmp = libxl__xs_read(gc, XBT_NULL,
+                                 GCSPRINTF("%s/num-ports", be_path));
+            if (!tmp) goto outerr;
+            usbctrl->num_ports = atoi(tmp);
+       }
+    }
+    *num = ndirs;
+
+    return usbctrls;
+
+outerr:
+    LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "Unable to list USB Controllers");
+    for (int i = 0; i < *num; i++) {
+        libxl_device_usbctrl_dispose(usbctrls + i);
+    }
+    free(usbctrls);
+    *num = 0;
+    return NULL;
+}
+
+static int libxl__device_usb_list(libxl__gc *gc, uint32_t domid, int usbctrl,
+                                  libxl_device_usb **usbs, int *num);
+
+static int libxl__device_usb_remove_common(libxl__gc *gc, uint32_t domid,
+                                libxl_device_usb *usb, int force);
+
+static int
+libxl__device_usbctrl_remove_common(libxl_ctx *ctx, uint32_t domid,
+                                    libxl_device_usbctrl *usbctrl,
+                                    const libxl_asyncop_how *ao_how,
+                                    int force)
+{
+    AO_CREATE(ctx, domid, ao_how);
+    libxl__device *device;
+    libxl__ao_device *aodev;
+    libxl_device_usb *usbs = NULL;
+    int numusb = 0;
+    int i, rc;
+
+    GCNEW(device);
+    rc = libxl__device_from_usbctrl(gc, domid, usbctrl, device);
+    if(rc) goto out;

Coding style, but rc check can be probably removed.

+
+    /* Remove usb devives first */
+    rc  = libxl__device_usb_list(gc, domid, usbctrl->devid, &usbs, &numusb);

Coding style.

+    if (rc) goto out;
+    for (i = 0; i < numusb; i++) {
+        if (libxl__device_usb_remove_common(gc, domid, &usbs[i], 0)) {
+            fprintf(stderr, "libxl_device_usb_remove failed.\n");
+            return -1;
+        }
+    }
+    /* remove usbctrl */
+    GCNEW(aodev);
+    libxl__prepare_ao_device(ao, aodev);
+    aodev->action = LIBXL__DEVICE_ACTION_REMOVE;
+    aodev->dev = device;
+    aodev->callback = device_addrm_aocomplete;
+    aodev->force = force;
+    libxl__initiate_device_remove(egc, aodev);
+
+out:
+    if(rc) return AO_ABORT(rc);

Coding style.

+    return AO_INPROGRESS;
+}
+
+int libxl_device_usbctrl_remove(libxl_ctx *ctx, uint32_t domid,
+                                libxl_device_usbctrl *usbctrl,
+                                const libxl_asyncop_how *ao_how)
+{
+    return libxl__device_usbctrl_remove_common(ctx, domid, usbctrl, ao_how, 0);
+}
+
+int libxl_device_usbctrl_destroy(libxl_ctx *ctx, uint32_t domid,
+                                 libxl_device_usbctrl *usbctrl,
+                                 const libxl_asyncop_how *ao_how)
+{
+    return libxl__device_usbctrl_remove_common(ctx, domid, usbctrl, ao_how, 1);
+}
+
+int libxl_device_usbctrl_getinfo(libxl_ctx *ctx, uint32_t domid,
+                                libxl_device_usbctrl *usbctrl,
+                                libxl_usbctrlinfo *usbctrlinfo)
+{
+    GC_INIT(ctx);
+    char *dompath, *usbctrlpath;
+    char *val;
+    int rc = 0;
+
+    dompath = libxl__xs_get_dompath(gc, domid);
+    usbctrlinfo->devid = usbctrl->devid;
+    usbctrlinfo->num_ports = usbctrl->num_ports;
+    usbctrlinfo->version = usbctrl->usb_version;
+
+    usbctrlpath = libxl__sprintf(gc, "%s/device/vusb/%d", dompath, 
usbctrlinfo->devid);
+    usbctrlinfo->backend = libxl__xs_read(gc, XBT_NULL,
+                                libxl__sprintf(gc, "%s/backend", usbctrlpath));
+    if (!usbctrlinfo->backend) {
+        rc = ERROR_FAIL;
+        goto out;
+    }
+
+    val = libxl__xs_read(gc, XBT_NULL,
+                         GCSPRINTF("%s/backend-id", usbctrlpath));
+    usbctrlinfo->backend_id = val ? strtoul(val, NULL, 10) : -1;
+
+    val = libxl__xs_read(gc, XBT_NULL,
+                         GCSPRINTF("%s/state", usbctrlpath));
+    usbctrlinfo->state = val ? strtoul(val, NULL, 10) : -1;
+
+    val = libxl__xs_read(gc, XBT_NULL,
+                         GCSPRINTF("%s/event-channel", usbctrlpath));
+    usbctrlinfo->evtch = val ? strtoul(val, NULL, 10) : -1;
+
+    val = libxl__xs_read(gc, XBT_NULL,
+                         GCSPRINTF("%s/urb-ring-ref", usbctrlpath));
+    usbctrlinfo->ref_urb = val ? strtoul(val, NULL, 10) : -1;
+
+    val = libxl__xs_read(gc, XBT_NULL,
+                         GCSPRINTF("%s/conn-ring-ref", usbctrlpath));
+    usbctrlinfo->ref_conn= val ? strtoul(val, NULL, 10) : -1;
+
+    usbctrlinfo->type = libxl__xs_read(gc, XBT_NULL,
+                                GCSPRINTF("%s/type", usbctrlinfo->backend));
+
+    usbctrlinfo->frontend = libxl__xs_read(gc, XBT_NULL,
+                                GCSPRINTF("%s/frontend", 
usbctrlinfo->backend));
+
+    val = libxl__xs_read(gc, XBT_NULL,
+                         GCSPRINTF("%s/frontend-id", usbctrlinfo->backend));
+    usbctrlinfo->frontend_id = val ? strtoul(val, NULL, 10) : -1;
+
+out:
+    GC_FREE;
+    return rc;
+}
+
+int libxl_devid_to_device_usbctrl(libxl_ctx *ctx, uint32_t domid,
+                                  int devid, libxl_device_usbctrl *usbctrl)
+{
+    GC_INIT(ctx);
+    char* fe_path = NULL, *be_path = NULL, *tmp;
+    int rc = 0;
+
+    libxl_device_usbctrl_init(usbctrl);
+    usbctrl->devid = devid;
+
+    fe_path = libxl__sprintf(gc, "%s/device/vusb",
+                             libxl__xs_get_dompath(gc, domid));
+    be_path = libxl__xs_read(gc, XBT_NULL,
+                             GCSPRINTF("%s/%d/backend", fe_path, devid));
+
+    tmp = libxl__xs_read(gc, XBT_NULL,
+                         GCSPRINTF("%s/%d/backend-id", fe_path, devid));
+    if (!tmp) {
+        rc = ERROR_FAIL;
+        goto out;
+    }
+    usbctrl->backend_domid = atoi(tmp);
+
+    tmp = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/usb-ver", be_path));
+    usbctrl->usb_version = atoi(tmp);
+
+    tmp = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/num-ports", be_path));
+    usbctrl->num_ports = atoi(tmp);
+
+out:
+    GC_FREE;
+    return rc;
+}
+
+/* usb device functions */
+
+/* Following functions are to get assignable usb devices */
+static int
+libxl__device_usb_assigned_list(libxl__gc *gc,
+                                libxl_device_usb **list, int *num)
+{
+    char **domlist;
+    unsigned int nd = 0, i, j;
+    char *be_path;
+    libxl_device_usb *usb;
+
+    *list = NULL;
+    *num = 0;
+
+    domlist = libxl__xs_directory(gc, XBT_NULL, "/local/domain", &nd);
+    be_path = libxl__sprintf(gc,"/local/domain/0/backend/vusb");
+    for (i = 0; i < nd; i++) {
+        char *path, *num_ports, **ctrl_list;
+        unsigned int nc = 0;
+        path = libxl__sprintf(gc, "%s/%s", be_path, domlist[i]);
+        ctrl_list = libxl__xs_directory(gc, XBT_NULL, path , &nc);
+
+        for (j = 0; j < nc; j++) {
+            path = libxl__sprintf(gc, "%s/%s/%s/num-ports", be_path,
+                                  domlist[i], ctrl_list[j]);
+            num_ports = libxl__xs_read(gc, XBT_NULL, path);
+            if ( num_ports ) {
+                int nport = atoi(num_ports), k;
+                char *devpath, *intf;
+
+                for (k = 1; k <= nport; k++) {
+                    devpath = libxl__sprintf(gc, "%s/%s/%s/port/%u", be_path,
+                                             domlist[i], ctrl_list[j], k);
+                    intf = libxl__xs_read(gc, XBT_NULL, devpath);
+                    /* If there are USB device attached, add it to list */
+                    if (intf && strcmp(intf, "") ) {
+                        *list = realloc(*list,
+                                  sizeof(libxl_device_usb) * ((*num) + 1));
+                        if (*list == NULL)
+                            return ERROR_NOMEM;
+                        usb = *list + *num;
+                        usb->ctrl = atoi(ctrl_list[j]);
+                        usb->port = k;
+                        usb->intf = strdup(intf);
+                        (*num)++;
+                    }
+                }
+            }
+        }
+    }
+    libxl__ptr_add(gc, *list);
+
+    return 0;
+}
+
+static bool is_usb_in_array(libxl_device_usb *usbs, int num, char *intf)
+{
+    int i;
+
+    for (i = 0; i < num; i++) {
+        if (!strcmp(usbs[i].intf, intf) )
+            return true;
+    }
+
+    return false;
+}
+
+static int get_usb_bDeviceClass(libxl__gc *gc, char *intf, char *buf)
+{
+    char *path;
+    FILE *fd;

Naming a FILE pointer fd isn't very common. I always think "int" when
I see a file related variable named "fd". Perhaps "fp"?

+3333333333333 (might look strange, but my cat wanted this comment to
go in).

+    int rc;
+
+    path = libxl__sprintf(gc, SYSFS_USB_DEVS_PATH"/%s/bDeviceClass", intf);
+
+    /* Check if this path exist, if not return -1 */
+    if (access(path, R_OK) )
+        return -1;
+
+    fd = popen(GCSPRINTF("cat %s", path), "r");

Why can't you just read from sysfs? Using a pipe here seems overkill.

+    rc = fscanf(fd, "%s", buf);

Is buf always large enough?

+    pclose(fd);
+
+    return (rc > 0) ? 0 : -1;
+}
+
+static bool is_usb_assignable(libxl__gc *gc, char *intf)
+{
+    char buf[5];
+
+    if (get_usb_bDeviceClass(gc, intf, buf) < 0)
+        return false;
+
+    if (strcmp(buf, USBHUB_CLASS_CODE))
+        return false;
+
+    return true;
+}
+
+libxl_device_usb *
+libxl_device_usb_assignable_list(libxl_ctx *ctx, int *num)
+{
+    GC_INIT(ctx);
+    libxl_device_usb *usbs = NULL;
+    libxl_device_usb *assigned;
+    int num_assigned;
+    struct dirent *de;
+    DIR *dir;
+
+    *num = 0;
+
+    if (libxl__device_usb_assigned_list(gc, &assigned, &num_assigned) < 0)
+        goto out;
+
+    if (!(dir = opendir(SYSFS_USB_DEVS_PATH)))
+        goto out;
+
+    while((de = readdir(dir))) {
+        if (!de->d_name)
+            continue;

Check for entry type?

Exclude ".", ".."?

+
+        if(is_usb_assignable(gc, de->d_name))

!is_usb_assignable?

Coding style. There are lots of other style errors more, especially
regarding if statements.

+            continue;
+
+        if (is_usb_in_array(assigned, num_assigned, de->d_name))
+            continue;
+
+        usbs = realloc(usbs, sizeof(*usbs)*((*num) + 1));
+        usbs[*num].intf = strdup(de->d_name);
+        (*num)++;
+    }
+
+    closedir(dir);
+
+out:
+    GC_FREE;
+    return usbs;
+}
+
+/* get usb devices under certain usb controller */
+static int libxl__device_usb_list(libxl__gc *gc, uint32_t domid, int usbctrl,
+                                  libxl_device_usb **usbs, int *num)
+{
+    char *be_path, *num_devs;
+    int n, i;
+    libxl_device_usb *usb = NULL;
+
+    usbs = NULL;
+    *num = 0;
+
+    be_path = libxl__sprintf(gc, "%s/backend/vusb/%d/%d",
+                             libxl__xs_get_dompath(gc, 0), domid, usbctrl);
+    num_devs = libxl__xs_read(gc, XBT_NULL,
+                              libxl__sprintf(gc, "%s/num-ports", be_path));
+    if (!num_devs)
+        return 0;
+
+    n = atoi(num_devs);
+    usb = calloc(n, sizeof(libxl_device_usb));
+    usbs = &usb;
+
+    for (i = 0; i < n; i++) {
+        char *intf;
+        intf = libxl__xs_read(gc, XBT_NULL,
+                              libxl__sprintf(gc,"%s/port/%d", be_path, i + 1));
+        if (intf && strcmp(intf, "") ) {
+            usbs[i]->ctrl = usbctrl;
+            usbs[i]->port = i + 1;
+            usbs[i]->intf = strdup(intf);
+            (*num)++;
+        }
+    }
+
+    return 0;
+}
+
+libxl_device_usb *libxl_device_usb_list(libxl_ctx *ctx, uint32_t domid,
+                                        int usbctrl, int *num)
+{
+    GC_INIT(ctx);
+    libxl_device_usb *usbs = NULL;
+
+    libxl__device_usb_list(gc, domid, usbctrl, &usbs, num);
+
+    GC_FREE;
+    return usbs;
+}
+
+/* get all usb devices of the domain */
+static libxl_device_usb *
+libxl_device_usb_list_all(libxl__gc *gc, uint32_t domid, int *num)
+{
+    char **usbctrls;
+    unsigned int nd, i, j;
+    char *be_path;
+    int rc;
+    libxl_device_usb *usbs = NULL;
+
+    *num = 0;
+
+    be_path = GCSPRINTF("/local/domain/0/backend/vusb/%d", domid);
+    usbctrls = libxl__xs_directory(gc, XBT_NULL, be_path, &nd);
+
+    for (i = 0; i < nd; i++) {
+        int nc = 0;
+        libxl_device_usb *tmp = NULL;
+        rc = libxl__device_usb_list(gc, domid, atoi(usbctrls[i]), &tmp, &nc);
+        if (!nc) continue;
+
+        usbs = realloc(usbs, sizeof(libxl_device_usb)*((*num) + nc));
+        for(j = 0; j < nc; j++) {
+            usbs[*num].ctrl = tmp[j].ctrl;
+            usbs[*num].port = tmp[j].port;
+            usbs[*num].intf = strdup(tmp[j].intf);
+            (*num)++;
+        }
+        free(tmp);
+    }
+    return usbs;
+}
+
+/* set default value */
+
+/* find first unused controller:port and give that to usb device */
+static int
+libxl__device_usb_set_default_usbctrl(libxl__gc *gc, uint32_t domid,
+                                      libxl_device_usb *usb)
+{
+    libxl_ctx *ctx = CTX;
+    libxl_device_usbctrl *usbctrls;
+    libxl_device_usb *usbs = NULL;
+    int numctrl, numusb, i, j, rc = -1;
+    char *be_path, *tmp;
+
+    usbctrls = libxl_device_usbctrl_list(ctx, domid, &numctrl);
+    if ( !numctrl)
+        goto out;
+
+    for (i = 0; i < numctrl; i++) {
+        rc = libxl__device_usb_list(gc, domid, usbctrls[i].devid,
+                                    &usbs, &numusb);
+        if (rc) continue;
+
+        if (!usbctrls[i].num_ports || numusb == usbctrls[i].num_ports)
+            continue;
+
+        for (j = 1; i <= numusb; j++) {
+            be_path = libxl__sprintf(gc, "%s/backend/vusb/%d/%d/port/%d",
+                                     libxl__xs_get_dompath(gc, 0), domid,
+                                     usbctrls[i].devid, j);
+            tmp = libxl__xs_read(gc, XBT_NULL, be_path);
+            if (tmp && !strcmp( tmp, "")) {
+                usb->ctrl = usbctrls[i].devid;
+                usb->port = j;
+                break;
+            }
+        }
+    }
+
+    rc = 0;
+
+out:
+    if (usbctrls)
+        free(usbctrls);
+    if (usbs)
+        free(usbs);
+    return rc;
+}
+
+static int libxl__device_usb_setdefault(libxl__gc *gc, uint32_t domid,
+                                        libxl_device_usb *usb)
+{
+    char *be_path, *tmp;
+
+    if (usb->ctrl == -1) {
+        int ret = libxl__device_usb_set_default_usbctrl(gc, domid, usb);
+        /* If no existing ctrl to host this usb device, setup a new one */
+        if (ret) {
+            libxl_device_usbctrl usbctrl;
+            libxl_device_usbctrl_init(&usbctrl);
+            libxl__device_usbctrl_add(gc, domid, &usbctrl);
+            usb->ctrl = usbctrl.devid;
+            usb->port = 1;
+            libxl_device_usbctrl_dispose(&usbctrl);
+        }
+    }
+
+    be_path = libxl__sprintf(gc, "%s/backend/vusb/%d/path/%d",
+                    libxl__xs_get_dompath(gc, 0), usb->ctrl, usb->port);
+    tmp = libxl__xs_read(gc, XBT_NULL, be_path);
+    if (!tmp || strcmp(tmp, "") ){
+        LOG(ERROR, "The controller port isn't available.");
+        return ERROR_INVAL;
+    }
+
+    return 0;
+}
+
+/* xenstore usb data */
+static int libxl__device_usb_add_xenstore(libxl__gc *gc, uint32_t domid,
+                                          libxl_device_usb *usb)
+{
+    libxl_ctx *ctx = CTX;
+    char *be_path;
+    int rc;
+    libxl_domain_config d_config;
+    libxl_device_usb usb_saved;
+    libxl__domain_userdata_lock *lock = NULL;
+
+    libxl_domain_config_init(&d_config);
+    libxl_device_usb_init(&usb_saved);
+    libxl_device_usb_copy(CTX, &usb_saved, usb);
+
+    be_path = libxl__sprintf(gc, "%s/backend/vusb/%d/%d",
+                        libxl__xs_get_dompath(gc, 0), domid, usb->ctrl);
+    if (libxl__wait_for_backend(gc, be_path, "4") < 0) {
+        rc = ERROR_FAIL;
+        goto out;
+    }
+
+    lock = libxl__lock_domain_userdata(gc, domid);
+    if (!lock) {
+        rc = ERROR_LOCK_FAIL;
+        goto out;
+    }
+
+    rc = libxl__get_domain_configuration(gc, domid, &d_config);
+    if (rc) goto out;
+
+    DEVICE_ADD(usb, usbs, domid, &usb_saved, COMPARE_USB, &d_config);
+
+    rc = libxl__set_domain_configuration(gc, domid, &d_config);
+    if (rc) goto out;
+
+    be_path = libxl__sprintf(gc, "%s/port/%d", be_path, usb->port);
+    LIBXL__LOG(ctx, LIBXL__LOG_DEBUG, "Adding new usb device to xenstore");
+    if (libxl__xs_write_checked(gc, XBT_NULL, be_path, usb->intf)) {
+        rc = ERROR_FAIL;
+        goto out;
+    }
+
+    rc = 0;
+
+out:
+    if (lock) libxl__unlock_domain_userdata(lock);
+    libxl_device_usb_dispose(&usb_saved);
+    libxl_domain_config_dispose(&d_config);
+    return rc;
+
+}
+
+static int libxl__device_usb_remove_xenstore(libxl__gc *gc, uint32_t domid,
+                                             libxl_device_usb *usb)
+{
+    libxl_ctx *ctx = CTX;
+    char *be_path;
+
+    be_path = libxl__sprintf(gc, "%s/backend/vusb/%d/%d",
+                        libxl__xs_get_dompath(gc, 0), domid, usb->ctrl);
+    if (libxl__wait_for_backend(gc, be_path, "4") < 0)
+        return ERROR_FAIL;
+
+    be_path = libxl__sprintf(gc, "%s/port/%d", be_path, usb->port);
+    LIBXL__LOG(ctx, LIBXL__LOG_DEBUG, "Removing USB device from xenstore");
+    if (libxl__xs_write_checked(gc,XBT_NULL, be_path, ""))
+        return ERROR_FAIL;
+
+    return 0;
+}
+
+/* bind/unbind usb device interface */
+static int unbind_usb_intf(libxl__gc *gc, char *intf, char *drvpath)
+{
+    char *path;
+    int fd, rc = 0;
+
+    drvpath = GCSPRINTF(SYSFS_USB_DEVS_PATH"/%s/driver", intf);
+
+    /* if not bound to a driver, return directly */
+    if (!drvpath)
+        return 0;
+
+    /* else, unbind from driver */
+    path = GCSPRINTF("%s/unbind", drvpath);
+    fd = open(path, O_WRONLY);
+    if (fd < 0) {
+        rc = ERROR_FAIL;
+        goto out;
+    }
+    if (write(fd, intf, strlen(intf)) < 0) {
+        rc = ERROR_FAIL;
+        goto out;
+    }
+    close(fd);
+
+out:
+    return rc;
+}
+
+static int bind_usb_intf(libxl__gc *gc, char *intf, char *drvpath)
+{
+    char *path;
+    int fd, rc = 0;
+
+    path = GCSPRINTF("%s/bind", drvpath);
+    fd = open(path, O_WRONLY);
+    if (fd < 0) {
+        rc = ERROR_FAIL;
+        goto out;
+    }
+    if (write(fd, intf, strlen(intf)) < 0) {
+        rc = ERROR_FAIL;
+        goto out;
+    }
+    close(fd);
+
+out:
+    return rc;
+}
+
+static int usb_get_all_interfaces(libxl__gc *gc, libxl_device_usb *usb,
+                                  char **intfs, int *num)
+{
+    DIR *dir;
+    struct dirent *entry;
+    char *buf;
+    int rc = 0;
+
+    intfs = NULL;
+    *num = 0;
+
+    buf = GCSPRINTF("%s:", usb->intf);
+
+    if (!(dir = opendir(SYSFS_USB_DEVS_PATH))) {
+        rc = ERROR_FAIL;
+        goto out;
+    }
+
+    while ((entry = readdir(dir)) != NULL) {
+        if (!strncmp(entry->d_name, buf, strlen(buf))){
+            intfs = realloc(intfs, sizeof(char *) * (*num + 1));
+            if (!intfs) {
+                rc = ERROR_FAIL;
+                goto out;
+            }
+            intfs[*num] = strdup(entry->d_name);
+            (*num)++;
+        }
+    }
+
+    closedir(dir);
+
+out:
+    return rc;
+}
+
+/* unbind usb device from usbback driver, if there are many interfaces
+ * under the usb device, then check each interface, unbind from usbback
+ * driver and rebind to original driver
+ */
+static int unbind_usb_device_from_usbback(libxl__gc *gc, libxl_device_usb *usb)
+{
+    char **intfs = NULL;
+    char *path;
+    int num = 0, i;
+    int rc = 0;
+
+    if (usb_get_all_interfaces(gc, usb, intfs, &num) < 0)
+        return ERROR_FAIL;
+
+    for (i = 0; i < num; i++){
+        char *intf = intfs[i];
+        char *drvpath = NULL;
+        char *tmp = NULL;
+
+        drvpath = GCSPRINTF(SYSFS_USB_DEVS_PATH"/%s/driver", intf);
+        if (!drvpath || strcmp(drvpath, SYSFS_USBBACK_DRIVER))
+            continue;
+
+        /* unbind interface from usbback driver */
+        if (unbind_usb_intf(gc, intf, NULL) < 0) {
+            rc = ERROR_FAIL;
+            goto out;
+        }
+
+        /* bind interface to its originial driver */
+        tmp = libxl__xs_read(gc, XBT_NULL,
+                  GCSPRINTF(USBBACK_INFO_PATH"/%s/%s/driver_path",
+                  usb->intf, intf));
+        if (tmp) {
+            if (bind_usb_intf(gc, intf, GCSPRINTF("%s/bind", tmp)) < 0) {
+                free(tmp);
+                rc = ERROR_FAIL;
+                goto out;
+            }
+            free(tmp);
+        }
+    }
+
+    /* finally, remove xs driver path */
+    path = GCSPRINTF(USBBACK_INFO_PATH"/%s", usb->intf);
+    if (libxl__xs_rm_checked(gc, XBT_NULL, path) < 0)
+        rc = ERROR_FAIL;
+
+out:
+    if (intfs) {
+        for (i = 0; i < num; i++)
+            free(intfs[i]);
+        free(intfs);
+    }
+    return rc;
+}
+
+/* bind usb device to "usbback" driver, if there are many interfaces
+ * under the usb device, check each interface, unbind from original
+ * driver and bind to usbback driver.
+ */
+static int bind_usb_device_to_usbback(libxl__gc *gc, libxl_device_usb *usb)
+{
+    char **intfs = NULL;
+    int num = 0, i;
+    int rc = 0;
+
+    if (usb_get_all_interfaces(gc, usb, intfs, &num) < 0)
+        return ERROR_FAIL;
+
+    for (i = 0; i < num; i++){
+        char *intf = intfs[i];
+        char *path = NULL;
+        char *drvpath = NULL;
+
+        /* unbind interface from original driver */
+        if (unbind_usb_intf(gc, intf, drvpath) < 0) {
+            rc = ERROR_FAIL;
+            goto out_rebind;
+        }
+
+        if (drvpath) {
+            /* write driver path to xenstore for later rebinding */
+            path = GCSPRINTF(USBBACK_INFO_PATH"/%s/%s/driver_path",
+                             usb->intf, intf);
+            if (libxl__xs_write_checked(gc, XBT_NULL, path, drvpath) < 0) {
+                rc = ERROR_FAIL;
+                goto out_rebind;
+            }
+        }
+
+        /* bind interface to usbback */
+        if (bind_usb_intf(gc, intf, SYSFS_USBBACK_DRIVER) < 0){
+            rc = ERROR_FAIL;
+            goto out_rebind;
+        }
+    }
+
+    goto out;
+
+out_rebind:
+    /* some interfaces might be bound to usbback, unbind it then and
+     * rebind to its original driver
+     */
+    unbind_usb_device_from_usbback(gc, usb);
+out:
+    if (intfs) {
+        for (i = 0; i < num; i++)
+            free(intfs[i]);
+        free(intfs);
+    }
+
+    return rc;
+}
+
+static int do_usb_add(libxl__gc *gc, uint32_t domid, libxl_device_usb *usb)
+{
+    int rc = 0;
+
+    rc = libxl__device_usb_add_xenstore(gc, domid, usb);
+    if (rc) goto out;
+
+    rc = bind_usb_device_to_usbback(gc, usb);
+    if (rc)
+        libxl__device_usb_remove_xenstore(gc, domid, usb);
+
+out:
+    return rc;
+}
+
+int libxl__device_usb_add(libxl__gc *gc, uint32_t domid, libxl_device_usb *usb)
+{
+    libxl_ctx *ctx = CTX;
+    libxl_device_usb *usbs;
+    int rc, num;
+
+    rc = libxl__device_usb_setdefault(gc, domid, usb);
+    if (rc) goto out;
+
+    rc = libxl__device_usb_assigned_list(gc, &usbs, &num);
+    if (rc) {
+        LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "Fail to get assigned usb list");
+        goto out;
+    }
+
+    if (is_usb_in_array(usbs, num, usb->intf)) {
+        LIBXL__LOG(ctx, LIBXL__LOG_ERROR,
+                   "USB device is already attached to a domain");
+        rc = ERROR_FAIL;
+        goto out;
+    }
+
+    rc = do_usb_add(gc, domid, usb);
+
+out:
+    return rc;
+}
+
+int libxl_device_usb_add(libxl_ctx *ctx, uint32_t domid,
+                         libxl_device_usb *usb,
+                         const libxl_asyncop_how *ao_how)
+{
+    AO_CREATE(ctx, domid, ao_how);
+    int rc;
+
+    rc = libxl__device_usb_add(gc, domid, usb);
+    libxl__ao_complete(egc, ao, rc);
+    return AO_INPROGRESS;
+}
+
+static int do_usb_remove(libxl__gc *gc, uint32_t domid,
+                         libxl_device_usb *usb, int force)
+{
+
+    libxl_ctx *ctx = CTX;
+    libxl_device_usb *usbs = NULL;
+    int rc = -1, num;
+
+    usbs = libxl_device_usb_list_all(gc, domid, &num);
+    if (!usbs) {
+        LIBXL__LOG(ctx, LIBXL__LOG_ERROR,
+                   "No USB device attached to this domain");
+        goto out;
+    }
+
+    if (!is_usb_in_array(usbs, num, usb->intf)) {
+        LIBXL__LOG(ctx, LIBXL__LOG_ERROR,
+                   "USB device is not attached to this domain");
+        goto out;
+    }
+
+    if (libxl__device_usb_remove_xenstore(gc, domid, usb))
+        goto out;
+
+    if (unbind_usb_device_from_usbback(gc, usb))
+        goto out;
+
+    rc = 0;
+
+out:
+    return rc;
+}
+
+static int libxl__device_usb_remove_common(libxl__gc *gc, uint32_t domid,
+                                           libxl_device_usb *usb, int force)
+{
+    return do_usb_remove(gc, domid, usb, force);
+}
+
+int libxl_device_usb_remove(libxl_ctx *ctx, uint32_t domid,
+                            libxl_device_usb *usb,
+                            const libxl_asyncop_how *ao_how)
+
+{
+    AO_CREATE(ctx, domid, ao_how);
+    int rc;
+
+    rc = libxl__device_usb_remove_common(gc, domid, usb, 0);
+
+    libxl__ao_complete(egc, ao, rc);
+    return AO_INPROGRESS;
+}
+
+int libxl_device_usb_destroy(libxl_ctx *ctx, uint32_t domid,
+                             libxl_device_usb *usb,
+                             const libxl_asyncop_how *ao_how)
+{
+    AO_CREATE(ctx, domid, ao_how);
+    int rc;
+
+    rc = libxl__device_usb_remove_common(gc, domid, usb, 1);
+
+    libxl__ao_complete(egc, ao, rc);
+    return AO_INPROGRESS;
+}
+
+int libxl__device_usb_destroy_all(libxl__gc *gc, uint32_t domid)
+{
+    libxl_ctx *ctx = CTX;
+    libxl_device_usbctrl *usbctrls;
+    int num, i, rc = 0;
+
+    usbctrls = libxl_device_usbctrl_list(ctx, domid, &num);
+    if (!usbctrls)
+        return 0;
+
+    for (i = 0; i < num; i++) {
+        /* Force remove on shutdown since, on HVM, qemu will not always
+         * respond to SCI interrupt because the guest kernel has shut
+         * down the devices by the time we even get here!
+         */
+        if (libxl__device_usbctrl_remove_common(ctx, domid,
+                                          usbctrls + i, 0, 1) < 0) {
+            rc = ERROR_FAIL;
+            goto out;
+        }
+    }
+
+out:
+    if (usbctrls)

Pointless test.

+        free(usbctrls);
+    return rc;
+}
+
+/*Get usb device information */
+static int get_usb_devnum (libxl__gc *gc, const char *intf, char *buf)
+{
+    char *path;
+    int rc = 0;
+    FILE *fd;

Variable naming again.

+
+    path = libxl__sprintf(gc, "cat "SYSFS_USB_DEVS_PATH"/%s/devnum", intf);
+    fd = popen(path, "r");
+    if (fgets(buf, 512, fd) == NULL || ferror(fd))
+        rc = -1;
+    pclose(fd);
+
+    return rc;
+}
+
+static int get_usb_busnum(libxl__gc *gc, const char *intf, char *buf)
+{
+    char *path;
+    int rc = 0;
+    FILE *fd;

And again.

+
+    path = libxl__sprintf(gc, "cat "SYSFS_USB_DEVS_PATH"/%s/busnum", intf);
+    fd = popen(path, "r");
+    if (fgets(buf, 512, fd) == NULL || ferror(fd))
+        rc = -1;
+    pclose(fd);
+
+    return rc;
+}
+
+static int get_usb_idVendor(libxl__gc *gc, const char *intf, char *buf)
+{
+    char *path;
+    int rc = 0;
+    FILE *fd;

Again.

+
+    path = libxl__sprintf(gc, "cat "SYSFS_USB_DEVS_PATH"/%s/idVendor", intf);
+    fd = popen(path, "r");
+    if (fgets(buf, 512, fd) == NULL || ferror(fd))
+        rc = -1;
+    pclose(fd);
+
+    return rc;
+}
+
+static int get_usb_idProduct(libxl__gc *gc, const char *intf, char *buf)
+{
+    char *path;
+    int rc = 0;
+    FILE *fd;

Again.

+
+    path = libxl__sprintf(gc, "cat "SYSFS_USB_DEVS_PATH"/%s/idProduct", intf);
+    fd = popen(path, "r");
+    if (fgets(buf, 512, fd) == NULL || ferror(fd))
+        rc = -1;
+    pclose(fd);
+
+    return rc;
+}
+
+static int get_usb_manufacturer(libxl__gc *gc, const char *intf, char *buf)
+{
+    char *path;
+    int rc = 0;
+    FILE *fd;

Again.

+
+    path = libxl__sprintf(gc, "cat "SYSFS_USB_DEVS_PATH"/%s/manufacturer", 
intf);
+    fd = popen(path, "r");
+    if (fgets(buf, 512, fd) == NULL || ferror(fd))
+        rc = -1;
+    pclose(fd);
+
+    return rc;
+}
+
+static int get_usb_product(libxl__gc *gc, const char *intf, char *buf)
+{
+    char *path;
+    int rc = 0;
+    FILE *fd;

Again.

+
+    path = libxl__sprintf(gc, "cat "SYSFS_USB_DEVS_PATH"/%s/product", intf);
+    fd = popen(path, "r");
+    if (fgets(buf, 512, fd) == NULL || ferror(fd))
+        rc = -1;
+    pclose(fd);
+
+    return rc;
+}

Wouldn't it make sense to have just one generic function taking the leaf
name as additional argument?

Like:

static int get_usb_leaf(libxl__gc *gc, const char *intf, char *buf,
                        char *leaf)
{
    char *path;
    int rc = 0;
    FILE *fp;

    path = libxl__sprintf(gc, "cat "SYSFS_USB_DEVS_PATH"/%s/%s", intf,
                          leaf);
    fp = popen(path, "r"); /* a pipe shouldn't be needed here */
    if (fgets(buf, 512, fp) == NULL || ferror(fp))
        rc = -1;
    pclose(fp);

    return rc;
}

static int get_usb_product(libxl__gc *gc, const char *intf, char *buf)
{
    return get_usb_leaf(gc, intf, buf, "product");
}

+
+int libxl_device_usb_getinfo(libxl_ctx *ctx, char *intf, libxl_usbinfo 
*usbinfo)
+{
+    GC_INIT(ctx);
+    char buf[512];
+
+    if (!get_usb_devnum(gc, intf, buf) )
+        usbinfo->devnum = atoi(buf);
+
+    if ( !get_usb_busnum(gc, intf, buf))
+        usbinfo->bus = atoi(buf);
+
+    if (!get_usb_idVendor(gc, intf, buf) )
+        usbinfo->idVendor = atoi(buf);
+
+    if (!get_usb_idProduct(gc, intf, buf) )
+        usbinfo->idProduct  = atoi(buf);
+
+    if (!get_usb_manufacturer(gc, intf, buf) )
+        usbinfo->manuf = strdup(buf);
+
+    if (!get_usb_product(gc, intf, buf) )
+        usbinfo->prod = strdup(buf);
+
+    GC_FREE;
+    return 0;
+}
+
+int libxl_intf_to_device_usb(libxl_ctx *ctx, uint32_t domid,
+                             char *intf, libxl_device_usb *usb)
+{
+    GC_INIT(ctx);
+    libxl_device_usb *usbs = NULL;
+    int num, i, rc;
+    bool find = false;
+
+    usbs = libxl_device_usb_list_all(gc, domid, &num);
+
+    for (i = 0; i < num; i++) {
+        if (!strcmp(intf, usbs[i].intf) ) {
+            usb->ctrl = usbs[i].ctrl;
+            usb->port = usbs[i].port;
+            usb->intf = strdup(usbs[i].intf);
+            find = 1;
+            break;
+        }
+    }
+
+    /* doesn't find the usb device in domain's usb device list*/
+    if (!find) {
+        rc = ERROR_FAIL;
+        goto out;
+    }
+
+    rc = 0;
+
+out:
+    GC_FREE;
+    if (usbs)
+        free(usbs);
+    return rc;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */


Juergen


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.