From: "Jürgen Groß" <jgross@suse.com>
To: Chunyan Liu <cyliu@suse.com>, xen-devel@lists.xen.org
Cc: george.dunlap@eu.citrix.com, lars.kurth@citrix.com,
caobosimon@gmail.com, ian.campbell@citrix.com,
ian.jackson@citrix.com
Subject: Re: [PATCH RFC V2 3/5] libxl: add pvusb API
Date: Tue, 10 Feb 2015 11:08:51 +0100 [thread overview]
Message-ID: <54D9D8B3.4060307@suse.com> (raw)
In-Reply-To: <1421656131-19366-4-git-send-email-cyliu@suse.com>
On 01/19/2015 09:28 AM, Chunyan Liu wrote:
> Add pvusb APIs, including:
> - attach/detach (create/destroy) virtual usb controller.
> - attach/detach usb device
> - list assignable usb devices in host
> - some other helper functions
>
> Signed-off-by: Chunyan Liu <cyliu@suse.com>
> Signed-off-by: Simon Cao <caobosimon@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
next prev parent reply other threads:[~2015-02-10 10:08 UTC|newest]
Thread overview: 40+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-01-19 8:28 [PATCH RFC V2 0/5] pvusb toolstack work Chunyan Liu
2015-01-19 8:28 ` [PATCH RFC V2 1/5] libxl: add pvusb definitions Chunyan Liu
2015-03-03 11:10 ` Ian Campbell
2015-03-03 16:45 ` George Dunlap
2015-03-04 7:26 ` Chun Yan Liu
2015-03-04 10:00 ` Ian Campbell
2015-03-04 12:26 ` George Dunlap
2015-03-04 12:33 ` Ian Campbell
2015-03-05 5:04 ` Chun Yan Liu
2015-03-03 17:15 ` George Dunlap
2015-03-04 8:28 ` Chun Yan Liu
2015-03-04 14:41 ` George Dunlap
2015-03-05 6:07 ` Chun Yan Liu
2015-01-19 8:28 ` [PATCH RFC V2 2/5] libxl: export some functions for pvusb use Chunyan Liu
2015-03-03 11:10 ` Ian Campbell
2015-01-19 8:28 ` [PATCH RFC V2 3/5] libxl: add pvusb API Chunyan Liu
2015-01-28 15:54 ` Ian Campbell
2015-01-29 3:24 ` Chun Yan Liu
2015-02-10 10:08 ` Jürgen Groß [this message]
2015-02-10 16:01 ` Jürgen Groß
2015-03-03 11:38 ` Ian Campbell
2015-03-04 7:47 ` Chun Yan Liu
2015-03-06 16:50 ` George Dunlap
2015-03-09 9:39 ` Ian Campbell
2015-03-09 10:17 ` George Dunlap
2015-03-09 10:41 ` Ian Campbell
2015-03-20 9:37 ` Chun Yan Liu
2015-03-17 14:03 ` Juergen Gross
2015-01-19 8:28 ` [PATCH RFC V2 4/5] xl: add pvusb commands Chunyan Liu
2015-02-10 6:25 ` Jürgen Groß
2015-03-03 11:43 ` Ian Campbell
2015-03-04 7:48 ` Chun Yan Liu
2015-03-06 17:25 ` George Dunlap
2015-03-20 9:02 ` Chun Yan Liu
2015-01-19 8:28 ` [PATCH RFC V2 5/5] domcreate: support pvusb in configuration file Chunyan Liu
2015-03-03 11:44 ` Ian Campbell
2015-01-28 15:51 ` [PATCH RFC V2 0/5] pvusb toolstack work Ian Campbell
2015-01-28 16:07 ` Pasi Kärkkäinen
2015-01-28 16:17 ` Ian Campbell
2015-01-29 3:22 ` Chun Yan Liu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=54D9D8B3.4060307@suse.com \
--to=jgross@suse.com \
--cc=caobosimon@gmail.com \
--cc=cyliu@suse.com \
--cc=george.dunlap@eu.citrix.com \
--cc=ian.campbell@citrix.com \
--cc=ian.jackson@citrix.com \
--cc=lars.kurth@citrix.com \
--cc=xen-devel@lists.xen.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.