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 <cy...@suse.com>
Signed-off-by: Simon Cao <caobosi...@gmail.com>
---
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@lists.xen.org
http://lists.xen.org/xen-devel