From mboxrd@z Thu Jan 1 00:00:00 1970 From: Juergen Gross Subject: Re: [PATCH V3 3/6] libxl: add pvusb API Date: Mon, 20 Apr 2015 07:53:24 +0200 Message-ID: <55349454.30202@suse.com> References: <1429415452-6161-1-git-send-email-cyliu@suse.com> <1429415452-6161-4-git-send-email-cyliu@suse.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii"; Format="flowed" Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: <1429415452-6161-4-git-send-email-cyliu@suse.com> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org To: Chunyan Liu , xen-devel@lists.xen.org Cc: lars.kurth@citrix.com, wei.liu2@citrix.com, ian.campbell@citrix.com, george.dunlap@eu.citrix.com, ian.jackson@citrix.com, caobosimon@gmail.com List-Id: xen-devel@lists.xenproject.org On 04/19/2015 05:50 AM, Chunyan Liu wrote: > Add pvusb APIs, including: > - attach/detach (create/destroy) virtual usb controller. > - attach/detach usb device > - list usb controller and usb devices > - some other helper functions > > Signed-off-by: Chunyan Liu > Signed-off-by: Simon Cao > --- > Changes to v2: > * remove qemu emulated usb related definitions, keep the work pure pvusb. > In last patch, will do all refactor work to unify pvusb and qemu emulated > usb. > * use bus.addr as user interface instead of busid to do usb-attach|detach > * remove usb-assignable-list APIs and some other unnecessary APIs > * reuse libxl_read_file_contents function instead of another new function > to handle getting sysfs file content > * fix build on different platforms as pci does > * fix many coding style problems > * address other comments in last version > * adjust codes to let it look better > > tools/libxl/Makefile | 2 +- > tools/libxl/libxl.c | 2 + > tools/libxl/libxl.h | 45 ++ > tools/libxl/libxl_internal.h | 11 +- > tools/libxl/libxl_osdeps.h | 13 + > tools/libxl/libxl_pvusb.c | 1201 ++++++++++++++++++++++++++++++++++ > tools/libxl/libxl_types.idl | 41 ++ > tools/libxl/libxl_types_internal.idl | 1 + > 8 files changed, 1314 insertions(+), 2 deletions(-) > create mode 100644 tools/libxl/libxl_pvusb.c > ... > diff --git a/tools/libxl/libxl_pvusb.c b/tools/libxl/libxl_pvusb.c > new file mode 100644 > index 0000000..4e4975a > --- /dev/null > +++ b/tools/libxl/libxl_pvusb.c ... > +static int libxl__usbctrl_add_xenstore(libxl__gc *gc, uint32_t domid, > + libxl_device_usbctrl *usbctrl) > +{ > + flexarray_t *front; > + flexarray_t *back; > + libxl__device *device; > + xs_transaction_t t = XBT_NULL; > + int rc = 0; > + libxl_domain_config d_config; > + libxl_device_usbctrl usbctrl_saved; > + libxl__domain_userdata_lock *lock = NULL; > + > + libxl_domain_config_init(&d_config); > + libxl_device_usbctrl_init(&usbctrl_saved); > + libxl_device_usbctrl_copy(CTX, &usbctrl_saved, usbctrl); > + > + GCNEW(device); > + libxl__device_from_usbctrl(gc, domid, usbctrl, device); > + > + front = flexarray_make(gc, 4, 1); > + back = flexarray_make(gc, 12, 1); > + > + flexarray_append_pair(back, "frontend-id", GCSPRINTF("%d", domid)); > + flexarray_append_pair(back, "online", "1"); > + flexarray_append_pair(back, "state", "1"); > + flexarray_append_pair(back, "usb-ver", GCSPRINTF("%d", usbctrl->version)); > + flexarray_append_pair(back, "num-ports", GCSPRINTF("%d", usbctrl->ports)); > + flexarray_append_pair(front, "backend-id", GCSPRINTF("%d", usbctrl->backend_domid)); > + flexarray_append_pair(front, "state", "1"); > + > + 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(usbctrl, usbctrls, domid, &usbctrl_saved, COMPARE_USBCTRL, &d_config); > + > + for (;;) { > + rc = libxl__xs_transaction_start(gc, &t); > + if (rc) goto out; > + > + rc = libxl__device_exists(gc, t, device); > + if (rc < 0) goto out; > + if (rc == 1) { > + /* already exists in xenstore */ > + LOG(ERROR, "device already exists in xenstore"); > + rc = ERROR_DEVICE_EXISTS; > + goto out; > + } > + > + rc = libxl__set_domain_configuration(gc, domid, &d_config); > + if (rc) goto out; > + > + libxl__device_generic_add(gc, t, 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, t, domid, usbctrl); Still no rc check. > + rc = libxl__xs_transaction_commit(gc, &t); > + if (!rc) break; > + if (rc < 0) goto out; > + } > + > +out: > + if (lock) libxl__unlock_domain_userdata(lock); > + libxl_device_usbctrl_dispose(&usbctrl_saved); > + libxl_domain_config_dispose(&d_config); > + return rc; > +} ... > +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_usbctrl *usbctrls = NULL; > + libxl_device_usbctrl *usbctrl_find = NULL; > + int numctrl = 0; > + libxl_device_usb *usbs = NULL; > + int numusb = 0; > + int i, rc; > + > + assert(usbctrl->devid != -1); > + > + usbctrls = libxl_device_usbctrl_list(ctx, domid, &numctrl); > + if (!numctrl) { > + LOG(ERROR, "No USB controller exists in this domain"); > + rc = ERROR_FAIL; > + goto out; > + } > + > + for (i = 0; i < numctrl; i++) { > + if (usbctrl->devid == usbctrls[i].devid) { > + usbctrl_find = usbctrls + i; > + break; > + } > + } > + > + if (!usbctrl_find) { > + LOG(ERROR, "USB controller %d is not attached to this domain", > + usbctrl->devid); > + rc = ERROR_FAIL; > + goto out; > + } > + > + usbctrl = usbctrl_find; > + > + GCNEW(device); > + libxl__device_from_usbctrl(gc, domid, usbctrl, device); > + > + /* 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 (do_usb_remove(gc, domid, &usbs[i])) { > + LOG(ERROR, "do_usb_remove failed"); > + rc = ERROR_FAIL; > + goto out; > + } > + } > + /* 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: > + free(usbctrls); > + free(usbs); > + if(rc) return AO_ABORT(rc); Coding style. > + 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 = GCSPRINTF("%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. > + 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->version = atoi(tmp); > + > + tmp = libxl__xs_read(gc, XBT_NULL, > + GCSPRINTF("%s/num-ports", be_path)); > + if (!tmp) goto outerr; > + usbctrl->ports = atoi(tmp); > + } > + } > + > + return usbctrls; > + > +outerr: > + 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; > +} ... > +/* 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/%d/backend/vusb/%d", > + LIBXL_TOOLSTACK_DOMID, 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++) { Coding style. > + usbs[*num].ctrl = tmp[j].ctrl; > + usbs[*num].port = tmp[j].port; > + usbs[*num].busid = strdup(tmp[j].busid); > + (*num)++; > + } > + free(tmp); > + } > + return usbs; > +} ... > +/* set default value */ > +static char *usb_busaddr_to_busid(libxl__gc *gc, int bus, int addr) > +{ > + libxl_ctx *ctx = libxl__gc_owner(gc); > + struct dirent *de; > + DIR *dir; > + char *busid = NULL; > + > + if (bus < 1 || addr < 1) > + return NULL; > + > + if (!(dir = opendir(SYSFS_USB_DEV))) > + return NULL; > + > + while((de = readdir(dir))) { Coding style. > + char *filename; > + void *buf; > + int busnum = -1; > + int devnum = -1; > + > + if (!de->d_name) > + continue; > + > + filename = GCSPRINTF(SYSFS_USB_DEV"/%s/devnum", de->d_name); > + if (!libxl_read_file_contents(ctx, filename, &buf, NULL)) > + sscanf(buf, "%x", &devnum); > + > + filename = GCSPRINTF(SYSFS_USB_DEV"/%s/busnum", de->d_name); > + if (!libxl_read_file_contents(ctx, filename, &buf, NULL)) > + sscanf(buf, "%x", &busnum); > + > + if (bus == busnum && addr == devnum) { > + busid = strdup(de->d_name); > + break; > + } > + } > + > + closedir(dir); > + return busid; > +} > + > +/* 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) Coding style. > + 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].ports || numusb == usbctrls[i].ports) > + continue; > + > + for (j = 1; i <= numusb; j++) { > + be_path = GCSPRINTF("%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 = GCSPRINTF("%s/backend/vusb/%d/%d/port/%d", > + libxl__xs_get_dompath(gc, 0), > + domid, usb->ctrl, usb->port); > + tmp = libxl__xs_read(gc, XBT_NULL, be_path); > + if (!tmp || strcmp(tmp, "") ){ Coding style. > + LOG(ERROR, "The controller port isn't available"); > + return ERROR_INVAL; > + } > + > + return 0; > +} ... > +static int bind_usb_intf(libxl__gc *gc, char *intf, char *drvpath) > +{ > + char *path; > + struct stat st; > + int fd, rc = 0; > + > + path = GCSPRINTF("%s/%s", drvpath, intf); > + rc = lstat(path, &st); > + /* already bind, return */ > + if(rc == 0) Coding style. > + return 0; > + > + path = GCSPRINTF("%s/bind", drvpath); > + fd = open(path, O_WRONLY); > + if (fd < 0) > + return ERROR_FAIL; > + > + rc = write(fd, intf, strlen(intf)); > + close(fd); > + if (rc < 0) > + return ERROR_FAIL; > + > + return 0; > +} > + > +/* Is usb interface bound to usbback? */ > +static int usb_intf_is_assigned(libxl__gc *gc, char *intf) > +{ > + char *spath; > + int rc; > + struct stat st; > + > + spath = GCSPRINTF(SYSFS_USBBACK_DRIVER"/%s", intf); > + rc = lstat(spath, &st); > + > + if(rc == 0) Coding style. > + return 1; > + if (rc < 0 && errno == ENOENT) > + return 0; > + LOGE(ERROR, "Accessing %s", spath); > + return -1; > +} Juergen