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

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



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;
+
+    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)
+{
+    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);
+
+    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;
+
+    if (usbctrl->devid == -1) {
+        if ((usbctrl->devid = libxl__device_nextid(gc, domid, "vusb")) < 0) {
+            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)++) {
+            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;
+
+    /* Remove usb devives first */
+    rc  = libxl__device_usb_list(gc, domid, usbctrl->devid, &usbs, &numusb);
+    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);
+    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;
+    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");
+    rc = fscanf(fd, "%s", buf);
+    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;
+
+        if(is_usb_assignable(gc, de->d_name))
+            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)
+        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;
+
+    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;
+
+    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;
+
+    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;
+
+    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;
+
+    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;
+
+    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;
+}
+
+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:
+ */
diff --git a/tools/libxl/libxlu_cfg_y.c b/tools/libxl/libxlu_cfg_y.c
index 07b5a1d..78eccf2 100644
--- a/tools/libxl/libxlu_cfg_y.c
+++ b/tools/libxl/libxlu_cfg_y.c
@@ -1,8 +1,8 @@
-/* A Bison parser, made by GNU Bison 2.5.  */
+/* A Bison parser, made by GNU Bison 2.7.  */
 
 /* Bison implementation for Yacc-like parsers in C
    
-      Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc.
+      Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation, Inc.
    
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -44,7 +44,7 @@
 #define YYBISON 1
 
 /* Bison version.  */
-#define YYBISON_VERSION "2.5"
+#define YYBISON_VERSION "2.7"
 
 /* Skeleton name.  */
 #define YYSKELETON_NAME "yacc.c"
@@ -58,8 +58,6 @@
 /* Pull parsers.  */
 #define YYPULL 1
 
-/* Using locations.  */
-#define YYLSP_NEEDED 1
 
 /* Substitute the variable and function names.  */
 #define yyparse         xlu__cfg_yyparse
@@ -72,22 +70,23 @@
 #define yylloc          xlu__cfg_yylloc
 
 /* Copy the first part of user declarations.  */
-
-/* Line 268 of yacc.c  */
+/* Line 371 of yacc.c  */
 #line 19 "libxlu_cfg_y.y"
 
 #define ctx_scanner ctx->scanner
 #include "libxlu_cfg_i.h"
 #include "libxlu_cfg_l.h"
 
+/* Line 371 of yacc.c  */
+#line 82 "libxlu_cfg_y.c"
 
-/* Line 268 of yacc.c  */
-#line 86 "libxlu_cfg_y.c"
-
-/* Enabling traces.  */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
+# ifndef YY_NULL
+#  if defined __cplusplus && 201103L <= __cplusplus
+#   define YY_NULL nullptr
+#  else
+#   define YY_NULL 0
+#  endif
+# endif
 
 /* Enabling verbose error messages.  */
 #ifdef YYERROR_VERBOSE
@@ -97,11 +96,17 @@
 # define YYERROR_VERBOSE 1
 #endif
 
-/* Enabling the token table.  */
-#ifndef YYTOKEN_TABLE
-# define YYTOKEN_TABLE 0
+/* In a future release of Bison, this section will be replaced
+   by #include "libxlu_cfg_y.h".  */
+#ifndef YY_XLU_CFG_YY_LIBXLU_CFG_Y_H_INCLUDED
+# define YY_XLU_CFG_YY_LIBXLU_CFG_Y_H_INCLUDED
+/* Enabling traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+#if YYDEBUG
+extern int xlu__cfg_yydebug;
 #endif
-
 
 /* Tokens.  */
 #ifndef YYTOKENTYPE
@@ -117,21 +122,18 @@
 #endif
 
 
-
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 typedef union YYSTYPE
 {
-
-/* Line 293 of yacc.c  */
+/* Line 387 of yacc.c  */
 #line 25 "libxlu_cfg_y.y"
 
   char *string;
   XLU_ConfigSetting *setting;
 
 
-
-/* Line 293 of yacc.c  */
-#line 135 "libxlu_cfg_y.c"
+/* Line 387 of yacc.c  */
+#line 137 "libxlu_cfg_y.c"
 } YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
@@ -152,11 +154,26 @@ typedef struct YYLTYPE
 #endif
 
 
-/* Copy the second part of user declarations.  */
+#ifdef YYPARSE_PARAM
+#if defined __STDC__ || defined __cplusplus
+int xlu__cfg_yyparse (void *YYPARSE_PARAM);
+#else
+int xlu__cfg_yyparse ();
+#endif
+#else /* ! YYPARSE_PARAM */
+#if defined __STDC__ || defined __cplusplus
+int xlu__cfg_yyparse (CfgParseContext *ctx);
+#else
+int xlu__cfg_yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
 
+#endif /* !YY_XLU_CFG_YY_LIBXLU_CFG_Y_H_INCLUDED  */
+
+/* Copy the second part of user declarations.  */
 
-/* Line 343 of yacc.c  */
-#line 160 "libxlu_cfg_y.c"
+/* Line 390 of yacc.c  */
+#line 177 "libxlu_cfg_y.c"
 
 #ifdef short
 # undef short
@@ -209,24 +226,24 @@ typedef short int yytype_int16;
 # if defined YYENABLE_NLS && YYENABLE_NLS
 #  if ENABLE_NLS
 #   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
-#   define YY_(msgid) dgettext ("bison-runtime", msgid)
+#   define YY_(Msgid) dgettext ("bison-runtime", Msgid)
 #  endif
 # endif
 # ifndef YY_
-#  define YY_(msgid) msgid
+#  define YY_(Msgid) Msgid
 # endif
 #endif
 
 /* Suppress unused-variable warnings by "using" E.  */
 #if ! defined lint || defined __GNUC__
-# define YYUSE(e) ((void) (e))
+# define YYUSE(E) ((void) (E))
 #else
-# define YYUSE(e) /* empty */
+# define YYUSE(E) /* empty */
 #endif
 
 /* Identity function, used to suppress warnings about constant conditions.  */
 #ifndef lint
-# define YYID(n) (n)
+# define YYID(N) (N)
 #else
 #if (defined __STDC__ || defined __C99__FUNC__ \
      || defined __cplusplus || defined _MSC_VER)
@@ -262,6 +279,7 @@ YYID (yyi)
 #    if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || 
defined __C99__FUNC__ \
      || defined __cplusplus || defined _MSC_VER)
 #     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+      /* Use EXIT_SUCCESS as a witness for stdlib.h.  */
 #     ifndef EXIT_SUCCESS
 #      define EXIT_SUCCESS 0
 #     endif
@@ -355,20 +373,20 @@ union yyalloc
 #endif
 
 #if defined YYCOPY_NEEDED && YYCOPY_NEEDED
-/* Copy COUNT objects from FROM to TO.  The source and destination do
+/* Copy COUNT objects from SRC to DST.  The source and destination do
    not overlap.  */
 # ifndef YYCOPY
 #  if defined __GNUC__ && 1 < __GNUC__
-#   define YYCOPY(To, From, Count) \
-      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+#   define YYCOPY(Dst, Src, Count) \
+      __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src)))
 #  else
-#   define YYCOPY(To, From, Count)             \
-      do                                       \
-       {                                       \
-         YYSIZE_T yyi;                         \
-         for (yyi = 0; yyi < (Count); yyi++)   \
-           (To)[yyi] = (From)[yyi];            \
-       }                                       \
+#   define YYCOPY(Dst, Src, Count)              \
+      do                                        \
+        {                                       \
+          YYSIZE_T yyi;                         \
+          for (yyi = 0; yyi < (Count); yyi++)   \
+            (Dst)[yyi] = (Src)[yyi];            \
+        }                                       \
       while (YYID (0))
 #  endif
 # endif
@@ -457,14 +475,14 @@ static const yytype_uint8 yyrline[] =
 };
 #endif
 
-#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+#if YYDEBUG || YYERROR_VERBOSE || 1
 /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
    First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
 static const char *const yytname[] =
 {
   "$end", "error", "$undefined", "IDENT", "STRING", "NUMBER", "NEWLINE",
   "'='", "';'", "'['", "']'", "','", "$accept", "file", "stmts", "stmt",
-  "assignment", "endstmt", "value", "atom", "valuelist", "values", "nlok", 0
+  "assignment", "endstmt", "value", "atom", "valuelist", "values", "nlok", 
YY_NULL
 };
 #endif
 
@@ -539,10 +557,10 @@ static const yytype_int8 yytable[] =
       16,    26,    25,    20,    13
 };
 
-#define yypact_value_is_default(yystate) \
-  ((yystate) == (-18))
+#define yypact_value_is_default(Yystate) \
+  (!!((Yystate) == (-18)))
 
-#define yytable_value_is_error(yytable_value) \
+#define yytable_value_is_error(Yytable_value) \
   YYID (0)
 
 static const yytype_uint8 yycheck[] =
@@ -588,23 +606,24 @@ static const yytype_uint8 yystos[] =
 
 #define YYRECOVERING()  (!!yyerrstatus)
 
-#define YYBACKUP(Token, Value)                                 \
-do                                                             \
-  if (yychar == YYEMPTY && yylen == 1)                         \
-    {                                                          \
-      yychar = (Token);                                                \
-      yylval = (Value);                                                \
-      YYPOPSTACK (1);                                          \
-      goto yybackup;                                           \
-    }                                                          \
-  else                                                         \
-    {                                                          \
+#define YYBACKUP(Token, Value)                                  \
+do                                                              \
+  if (yychar == YYEMPTY)                                        \
+    {                                                           \
+      yychar = (Token);                                         \
+      yylval = (Value);                                         \
+      YYPOPSTACK (yylen);                                       \
+      yystate = *yyssp;                                         \
+      goto yybackup;                                            \
+    }                                                           \
+  else                                                          \
+    {                                                           \
       yyerror (&yylloc, ctx, YY_("syntax error: cannot back up")); \
       YYERROR;                                                 \
     }                                                          \
 while (YYID (0))
 
-
+/* Error token number */
 #define YYTERROR       1
 #define YYERRCODE      256
 
@@ -613,27 +632,28 @@ while (YYID (0))
    If N is 0, then set CURRENT to the empty location which ends
    the previous symbol: RHS[0] (always defined).  */
 
-#define YYRHSLOC(Rhs, K) ((Rhs)[K])
 #ifndef YYLLOC_DEFAULT
-# define YYLLOC_DEFAULT(Current, Rhs, N)                               \
-    do                                                                 \
-      if (YYID (N))                                                    \
-       {                                                               \
-         (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;        \
-         (Current).first_column = YYRHSLOC (Rhs, 1).first_column;      \
-         (Current).last_line    = YYRHSLOC (Rhs, N).last_line;         \
-         (Current).last_column  = YYRHSLOC (Rhs, N).last_column;       \
-       }                                                               \
-      else                                                             \
-       {                                                               \
-         (Current).first_line   = (Current).last_line   =              \
-           YYRHSLOC (Rhs, 0).last_line;                                \
-         (Current).first_column = (Current).last_column =              \
-           YYRHSLOC (Rhs, 0).last_column;                              \
-       }                                                               \
+# define YYLLOC_DEFAULT(Current, Rhs, N)                                \
+    do                                                                  \
+      if (YYID (N))                                                     \
+        {                                                               \
+          (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;        \
+          (Current).first_column = YYRHSLOC (Rhs, 1).first_column;      \
+          (Current).last_line    = YYRHSLOC (Rhs, N).last_line;         \
+          (Current).last_column  = YYRHSLOC (Rhs, N).last_column;       \
+        }                                                               \
+      else                                                              \
+        {                                                               \
+          (Current).first_line   = (Current).last_line   =              \
+            YYRHSLOC (Rhs, 0).last_line;                                \
+          (Current).first_column = (Current).last_column =              \
+            YYRHSLOC (Rhs, 0).last_column;                              \
+        }                                                               \
     while (YYID (0))
 #endif
 
+#define YYRHSLOC(Rhs, K) ((Rhs)[K])
+
 
 /* YY_LOCATION_PRINT -- Print the location on the stream.
    This macro was not mandated originally: define only if we know
@@ -641,10 +661,46 @@ while (YYID (0))
 
 #ifndef YY_LOCATION_PRINT
 # if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
-#  define YY_LOCATION_PRINT(File, Loc)                 \
-     fprintf (File, "%d.%d-%d.%d",                     \
-             (Loc).first_line, (Loc).first_column,     \
-             (Loc).last_line,  (Loc).last_column)
+
+/* Print *YYLOCP on YYO.  Private, do not rely on its existence. */
+
+__attribute__((__unused__))
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static unsigned
+yy_location_print_ (FILE *yyo, YYLTYPE const * const yylocp)
+#else
+static unsigned
+yy_location_print_ (yyo, yylocp)
+    FILE *yyo;
+    YYLTYPE const * const yylocp;
+#endif
+{
+  unsigned res = 0;
+  int end_col = 0 != yylocp->last_column ? yylocp->last_column - 1 : 0;
+  if (0 <= yylocp->first_line)
+    {
+      res += fprintf (yyo, "%d", yylocp->first_line);
+      if (0 <= yylocp->first_column)
+        res += fprintf (yyo, ".%d", yylocp->first_column);
+    }
+  if (0 <= yylocp->last_line)
+    {
+      if (yylocp->first_line < yylocp->last_line)
+        {
+          res += fprintf (yyo, "-%d", yylocp->last_line);
+          if (0 <= end_col)
+            res += fprintf (yyo, ".%d", end_col);
+        }
+      else if (0 <= end_col && yylocp->first_column < end_col)
+        res += fprintf (yyo, "-%d", end_col);
+    }
+  return res;
+ }
+
+#  define YY_LOCATION_PRINT(File, Loc)          \
+  yy_location_print_ (File, &(Loc))
+
 # else
 #  define YY_LOCATION_PRINT(File, Loc) ((void) 0)
 # endif
@@ -652,7 +708,6 @@ while (YYID (0))
 
 
 /* YYLEX -- calling `yylex' with the right arguments.  */
-
 #ifdef YYLEX_PARAM
 # define YYLEX yylex (&yylval, &yylloc, YYLEX_PARAM)
 #else
@@ -704,6 +759,8 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep, 
yylocationp, ctx)
     CfgParseContext *ctx;
 #endif
 {
+  FILE *yyo = yyoutput;
+  YYUSE (yyo);
   if (!yyvaluep)
     return;
   YYUSE (yylocationp);
@@ -717,7 +774,7 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep, 
yylocationp, ctx)
   switch (yytype)
     {
       default:
-       break;
+        break;
     }
 }
 
@@ -963,12 +1020,11 @@ static int
 yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
                 yytype_int16 *yyssp, int yytoken)
 {
-  YYSIZE_T yysize0 = yytnamerr (0, yytname[yytoken]);
+  YYSIZE_T yysize0 = yytnamerr (YY_NULL, yytname[yytoken]);
   YYSIZE_T yysize = yysize0;
-  YYSIZE_T yysize1;
   enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
   /* Internationalized format string. */
-  const char *yyformat = 0;
+  const char *yyformat = YY_NULL;
   /* Arguments of yyformat. */
   char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
   /* Number of reported tokens (one for the "unexpected", one per
@@ -1028,11 +1084,13 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
                     break;
                   }
                 yyarg[yycount++] = yytname[yyx];
-                yysize1 = yysize + yytnamerr (0, yytname[yyx]);
-                if (! (yysize <= yysize1
-                       && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
-                  return 2;
-                yysize = yysize1;
+                {
+                  YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULL, 
yytname[yyx]);
+                  if (! (yysize <= yysize1
+                         && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+                    return 2;
+                  yysize = yysize1;
+                }
               }
         }
     }
@@ -1052,10 +1110,12 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
 # undef YYCASE_
     }
 
-  yysize1 = yysize + yystrlen (yyformat);
-  if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
-    return 2;
-  yysize = yysize1;
+  {
+    YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
+    if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+      return 2;
+    yysize = yysize1;
+  }
 
   if (*yymsg_alloc < yysize)
     {
@@ -1117,90 +1177,62 @@ yydestruct (yymsg, yytype, yyvaluep, yylocationp, ctx)
 
   switch (yytype)
     {
-      case 3: /* "IDENT" */
-
-/* Line 1391 of yacc.c  */
+      case 3: /* IDENT */
+/* Line 1398 of yacc.c  */
 #line 40 "libxlu_cfg_y.y"
-       { free((yyvaluep->string)); };
-
-/* Line 1391 of yacc.c  */
-#line 1128 "libxlu_cfg_y.c"
-       break;
-      case 4: /* "STRING" */
-
-/* Line 1391 of yacc.c  */
+        { free(((*yyvaluep).string)); };
+/* Line 1398 of yacc.c  */
+#line 1186 "libxlu_cfg_y.c"
+        break;
+      case 4: /* STRING */
+/* Line 1398 of yacc.c  */
 #line 40 "libxlu_cfg_y.y"
-       { free((yyvaluep->string)); };
-
-/* Line 1391 of yacc.c  */
-#line 1137 "libxlu_cfg_y.c"
-       break;
-      case 5: /* "NUMBER" */
-
-/* Line 1391 of yacc.c  */
+        { free(((*yyvaluep).string)); };
+/* Line 1398 of yacc.c  */
+#line 1193 "libxlu_cfg_y.c"
+        break;
+      case 5: /* NUMBER */
+/* Line 1398 of yacc.c  */
 #line 40 "libxlu_cfg_y.y"
-       { free((yyvaluep->string)); };
-
-/* Line 1391 of yacc.c  */
-#line 1146 "libxlu_cfg_y.c"
-       break;
-      case 18: /* "value" */
-
-/* Line 1391 of yacc.c  */
+        { free(((*yyvaluep).string)); };
+/* Line 1398 of yacc.c  */
+#line 1200 "libxlu_cfg_y.c"
+        break;
+      case 18: /* value */
+/* Line 1398 of yacc.c  */
 #line 43 "libxlu_cfg_y.y"
-       { xlu__cfg_set_free((yyvaluep->setting)); };
-
-/* Line 1391 of yacc.c  */
-#line 1155 "libxlu_cfg_y.c"
-       break;
-      case 19: /* "atom" */
-
-/* Line 1391 of yacc.c  */
+        { xlu__cfg_set_free(((*yyvaluep).setting)); };
+/* Line 1398 of yacc.c  */
+#line 1207 "libxlu_cfg_y.c"
+        break;
+      case 19: /* atom */
+/* Line 1398 of yacc.c  */
 #line 40 "libxlu_cfg_y.y"
-       { free((yyvaluep->string)); };
-
-/* Line 1391 of yacc.c  */
-#line 1164 "libxlu_cfg_y.c"
-       break;
-      case 20: /* "valuelist" */
-
-/* Line 1391 of yacc.c  */
+        { free(((*yyvaluep).string)); };
+/* Line 1398 of yacc.c  */
+#line 1214 "libxlu_cfg_y.c"
+        break;
+      case 20: /* valuelist */
+/* Line 1398 of yacc.c  */
 #line 43 "libxlu_cfg_y.y"
-       { xlu__cfg_set_free((yyvaluep->setting)); };
-
-/* Line 1391 of yacc.c  */
-#line 1173 "libxlu_cfg_y.c"
-       break;
-      case 21: /* "values" */
-
-/* Line 1391 of yacc.c  */
+        { xlu__cfg_set_free(((*yyvaluep).setting)); };
+/* Line 1398 of yacc.c  */
+#line 1221 "libxlu_cfg_y.c"
+        break;
+      case 21: /* values */
+/* Line 1398 of yacc.c  */
 #line 43 "libxlu_cfg_y.y"
-       { xlu__cfg_set_free((yyvaluep->setting)); };
-
-/* Line 1391 of yacc.c  */
-#line 1182 "libxlu_cfg_y.c"
-       break;
+        { xlu__cfg_set_free(((*yyvaluep).setting)); };
+/* Line 1398 of yacc.c  */
+#line 1228 "libxlu_cfg_y.c"
+        break;
 
       default:
-       break;
+        break;
     }
 }
 
 
-/* Prevent warnings from -Wmissing-prototypes.  */
-#ifdef YYPARSE_PARAM
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void *YYPARSE_PARAM);
-#else
-int yyparse ();
-#endif
-#else /* ! YYPARSE_PARAM */
-#if defined __STDC__ || defined __cplusplus
-int yyparse (CfgParseContext *ctx);
-#else
-int yyparse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
 
 
 /*----------.
@@ -1232,11 +1264,40 @@ yyparse (ctx)
 /* The lookahead symbol.  */
 int yychar;
 
+
+#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
+/* Suppress an incorrect diagnostic about yylval being uninitialized.  */
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
+    _Pragma ("GCC diagnostic push") \
+    _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
+    _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
+    _Pragma ("GCC diagnostic pop")
+#else
+/* Default value used for initialization, for pacifying older GCCs
+   or non-GCC compilers.  */
+static YYSTYPE yyval_default;
+# define YY_INITIAL_VALUE(Value) = Value
+#endif
+static YYLTYPE yyloc_default
+# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
+  = { 1, 1, 1, 1 }
+# endif
+;
+#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END
+#endif
+#ifndef YY_INITIAL_VALUE
+# define YY_INITIAL_VALUE(Value) /* Nothing. */
+#endif
+
 /* The semantic value of the lookahead symbol.  */
-YYSTYPE yylval;
+YYSTYPE yylval YY_INITIAL_VALUE(yyval_default);
 
 /* Location data for the lookahead symbol.  */
-YYLTYPE yylloc;
+YYLTYPE yylloc = yyloc_default;
+
 
     /* Number of syntax errors so far.  */
     int yynerrs;
@@ -1250,7 +1311,7 @@ YYLTYPE yylloc;
        `yyvs': related to semantic values.
        `yyls': related to locations.
 
-       Refer to the stacks thru separate pointers, to allow yyoverflow
+       Refer to the stacks through separate pointers, to allow yyoverflow
        to reallocate them elsewhere.  */
 
     /* The state stack.  */
@@ -1276,7 +1337,7 @@ YYLTYPE yylloc;
   int yyn;
   int yyresult;
   /* Lookahead token as an internal (translated) token number.  */
-  int yytoken;
+  int yytoken = 0;
   /* The variables used to return semantic value and location from the
      action routines.  */
   YYSTYPE yyval;
@@ -1295,10 +1356,9 @@ YYLTYPE yylloc;
      Keep to zero when no symbol should be popped.  */
   int yylen = 0;
 
-  yytoken = 0;
-  yyss = yyssa;
-  yyvs = yyvsa;
-  yyls = yylsa;
+  yyssp = yyss = yyssa;
+  yyvsp = yyvs = yyvsa;
+  yylsp = yyls = yylsa;
   yystacksize = YYINITDEPTH;
 
   YYDPRINTF ((stderr, "Starting parse\n"));
@@ -1307,21 +1367,7 @@ YYLTYPE yylloc;
   yyerrstatus = 0;
   yynerrs = 0;
   yychar = YYEMPTY; /* Cause a token to be read.  */
-
-  /* Initialize stack pointers.
-     Waste one element of value and location stack
-     so that they stay on the same level as the state stack.
-     The wasted elements are never initialized.  */
-  yyssp = yyss;
-  yyvsp = yyvs;
-  yylsp = yyls;
-
-#if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
-  /* Initialize the default location before parsing starts.  */
-  yylloc.first_line   = yylloc.last_line   = 1;
-  yylloc.first_column = yylloc.last_column = 1;
-#endif
-
+  yylsp[0] = yylloc;
   goto yysetstate;
 
 /*------------------------------------------------------------.
@@ -1467,7 +1513,9 @@ yybackup:
   yychar = YYEMPTY;
 
   yystate = yyn;
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
   *++yyvsp = yylval;
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
   *++yylsp = yylloc;
   goto yynewstate;
 
@@ -1505,79 +1553,68 @@ yyreduce:
   switch (yyn)
     {
         case 9:
-
-/* Line 1806 of yacc.c  */
+/* Line 1792 of yacc.c  */
 #line 57 "libxlu_cfg_y.y"
     { xlu__cfg_set_store(ctx,(yyvsp[(1) - (3)].string),(yyvsp[(3) - 
(3)].setting),(yylsp[(3) - (3)]).first_line); }
     break;
 
   case 12:
-
-/* Line 1806 of yacc.c  */
+/* Line 1792 of yacc.c  */
 #line 62 "libxlu_cfg_y.y"
     { (yyval.setting)= xlu__cfg_set_mk(ctx,1,(yyvsp[(1) - (1)].string)); }
     break;
 
   case 13:
-
-/* Line 1806 of yacc.c  */
+/* Line 1792 of yacc.c  */
 #line 63 "libxlu_cfg_y.y"
     { (yyval.setting)= (yyvsp[(3) - (4)].setting); }
     break;
 
   case 14:
-
-/* Line 1806 of yacc.c  */
+/* Line 1792 of yacc.c  */
 #line 65 "libxlu_cfg_y.y"
     { (yyval.string)= (yyvsp[(1) - (1)].string); }
     break;
 
   case 15:
-
-/* Line 1806 of yacc.c  */
+/* Line 1792 of yacc.c  */
 #line 66 "libxlu_cfg_y.y"
     { (yyval.string)= (yyvsp[(1) - (1)].string); }
     break;
 
   case 16:
-
-/* Line 1806 of yacc.c  */
+/* Line 1792 of yacc.c  */
 #line 68 "libxlu_cfg_y.y"
     { (yyval.setting)= xlu__cfg_set_mk(ctx,0,0); }
     break;
 
   case 17:
-
-/* Line 1806 of yacc.c  */
+/* Line 1792 of yacc.c  */
 #line 69 "libxlu_cfg_y.y"
     { (yyval.setting)= (yyvsp[(1) - (1)].setting); }
     break;
 
   case 18:
-
-/* Line 1806 of yacc.c  */
+/* Line 1792 of yacc.c  */
 #line 70 "libxlu_cfg_y.y"
     { (yyval.setting)= (yyvsp[(1) - (3)].setting); }
     break;
 
   case 19:
-
-/* Line 1806 of yacc.c  */
+/* Line 1792 of yacc.c  */
 #line 72 "libxlu_cfg_y.y"
     { (yyval.setting)= xlu__cfg_set_mk(ctx,2,(yyvsp[(1) - (2)].string)); }
     break;
 
   case 20:
-
-/* Line 1806 of yacc.c  */
+/* Line 1792 of yacc.c  */
 #line 73 "libxlu_cfg_y.y"
     { xlu__cfg_set_add(ctx,(yyvsp[(1) - (5)].setting),(yyvsp[(4) - 
(5)].string)); (yyval.setting)= (yyvsp[(1) - (5)].setting); }
     break;
 
 
-
-/* Line 1806 of yacc.c  */
-#line 1581 "libxlu_cfg_y.c"
+/* Line 1792 of yacc.c  */
+#line 1618 "libxlu_cfg_y.c"
       default: break;
     }
   /* User semantic actions sometimes alter yychar, and that requires
@@ -1742,7 +1779,9 @@ yyerrlab1:
       YY_STACK_PRINT (yyss, yyssp);
     }
 
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
   *++yyvsp = yylval;
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
 
   yyerror_range[2] = yylloc;
   /* Using YYLLOC is tempting, but would change the location of
@@ -1771,7 +1810,7 @@ yyabortlab:
   yyresult = 1;
   goto yyreturn;
 
-#if !defined(yyoverflow) || YYERROR_VERBOSE
+#if !defined yyoverflow || YYERROR_VERBOSE
 /*-------------------------------------------------.
 | yyexhaustedlab -- memory exhaustion comes here.  |
 `-------------------------------------------------*/
@@ -1813,4 +1852,3 @@ yyreturn:
 }
 
 
-
diff --git a/tools/libxl/libxlu_cfg_y.h b/tools/libxl/libxlu_cfg_y.h
index d7dfaf2..54d4f61 100644
--- a/tools/libxl/libxlu_cfg_y.h
+++ b/tools/libxl/libxlu_cfg_y.h
@@ -1,8 +1,8 @@
-/* A Bison parser, made by GNU Bison 2.5.  */
+/* A Bison parser, made by GNU Bison 2.7.  */
 
 /* Bison interface for Yacc-like parsers in C
    
-      Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc.
+      Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation, Inc.
    
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -30,6 +30,15 @@
    This special exception was added by the Free Software Foundation in
    version 2.2 of Bison.  */
 
+#ifndef YY_XLU_CFG_YY_LIBXLU_CFG_Y_H_INCLUDED
+# define YY_XLU_CFG_YY_LIBXLU_CFG_Y_H_INCLUDED
+/* Enabling traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+#if YYDEBUG
+extern int xlu__cfg_yydebug;
+#endif
 
 /* Tokens.  */
 #ifndef YYTOKENTYPE
@@ -45,29 +54,24 @@
 #endif
 
 
-
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 typedef union YYSTYPE
 {
-
-/* Line 2068 of yacc.c  */
+/* Line 2058 of yacc.c  */
 #line 25 "libxlu_cfg_y.y"
 
   char *string;
   XLU_ConfigSetting *setting;
 
 
-
-/* Line 2068 of yacc.c  */
-#line 63 "libxlu_cfg_y.h"
+/* Line 2058 of yacc.c  */
+#line 69 "libxlu_cfg_y.h"
 } YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1
 #endif
 
-
-
 #if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
 typedef struct YYLTYPE
 {
@@ -82,4 +86,18 @@ typedef struct YYLTYPE
 #endif
 
 
+#ifdef YYPARSE_PARAM
+#if defined __STDC__ || defined __cplusplus
+int xlu__cfg_yyparse (void *YYPARSE_PARAM);
+#else
+int xlu__cfg_yyparse ();
+#endif
+#else /* ! YYPARSE_PARAM */
+#if defined __STDC__ || defined __cplusplus
+int xlu__cfg_yyparse (CfgParseContext *ctx);
+#else
+int xlu__cfg_yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
 
+#endif /* !YY_XLU_CFG_YY_LIBXLU_CFG_Y_H_INCLUDED  */
-- 
1.8.4.5


_______________________________________________
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®.