[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH RFC 2/6] libxl: implementation of PV audio device interface
From: Pavlo Suikov <pavlo.suikov@xxxxxxxxxxxxxxx> PV Audio device interface is implemented in libxl and xl with full support for device control Signed-off-by: Pavlo Suikov <pavlo.suikov@xxxxxxxxxxxxxxx> Signed-off-by: Glib Golubytskyi <glib.golubytskyi@xxxxxxxxxxxxxxx> Signed-off-by: Iurii Konovalenko <iurii.konovalenko@xxxxxxxxxxxxxxx> --- tools/libxl/libxl.c | 351 ++++++++++++++++++++++++++++++++++- tools/libxl/libxl.h | 16 ++ tools/libxl/libxl_create.c | 39 +++- tools/libxl/libxl_device.c | 2 + tools/libxl/libxl_internal.c | 4 + tools/libxl/libxl_internal.h | 20 +- tools/libxl/libxl_types.idl | 32 ++++ tools/libxl/libxl_types_internal.idl | 1 + tools/libxl/libxl_utils.h | 3 + tools/libxl/xl.h | 3 + tools/libxl/xl_cmdimpl.c | 229 ++++++++++++++++++++++- tools/libxl/xl_cmdtable.c | 20 ++ 12 files changed, 715 insertions(+), 5 deletions(-) diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c index 09c4bc7..d96172d 100644 --- a/tools/libxl/libxl.c +++ b/tools/libxl/libxl.c @@ -2593,7 +2593,344 @@ exit: return rc; } +/******************************************************************************/ + +int libxl__device_vsnd_setdefault(libxl__gc *gc, libxl_device_vsnd *vsnd) +{ + int rc; + + rc = libxl__resolve_domid(gc, vsnd->backend_domname, &vsnd->backend_domid); + + return rc; +} + +static int libxl__device_from_vsnd(libxl__gc *gc, uint32_t domid, libxl_device_vsnd *vsnd, libxl__device *device) +{ + device->backend_devid = vsnd->devid; + device->backend_domid = vsnd->backend_domid; + device->backend_kind = LIBXL__DEVICE_KIND_VSND; + device->devid = vsnd->devid; + device->domid = domid; + device->kind = LIBXL__DEVICE_KIND_VSND; + + return 0; +} + +static int libxl__device_vsnd_from_xs_be(libxl__gc *gc, + const char *be_path, + libxl_device_vsnd *vsnd) +{ + const char *tmp; + int rc; + + libxl_device_vsnd_init(vsnd); + + tmp = READ_BACKEND(gc, "device-id"); + if (tmp) + vsnd->devid = atoi(tmp); + else + vsnd->devid = 0; + + vsnd->short_name = READ_BACKEND(gc, "short-name"); + vsnd->long_name = READ_BACKEND(gc, "long-name"); + vsnd->sample_formats = READ_BACKEND(gc, "sample-formats"); + vsnd->rates = READ_BACKEND(gc, "rates"); + + tmp = READ_BACKEND(gc, "channels-min"); + if (tmp) + vsnd->channels_min = atoi(tmp); + else + vsnd->channels_min = 0; + + tmp = READ_BACKEND(gc, "channels-max"); + if (tmp) + vsnd->channels_max = atoi(tmp); + else + vsnd->channels_max = 0; + + tmp = READ_BACKEND(gc, "priority"); + if (tmp) + vsnd->priority = atoi(tmp); + else + vsnd->priority = 0; + + vsnd->slave_device = READ_BACKEND(gc, "slave-device"); + + rc = 0; + out: + return rc; +} + +int libxl_devid_to_device_vsnd(libxl_ctx *ctx, uint32_t domid, + int devid, libxl_device_vsnd *vsnd) +{ + GC_INIT(ctx); + char *dompath, *path; + int rc = ERROR_FAIL; + + libxl_device_vsnd_init(vsnd); + dompath = libxl__xs_get_dompath(gc, domid); + if (!dompath) + goto out; + + path = libxl__xs_read(gc, XBT_NULL, + libxl__sprintf(gc, "%s/device/vsnd/%d/backend", + dompath, devid)); + if (!path) + goto out; + + rc = libxl__device_vsnd_from_xs_be(gc, path, vsnd); + if (rc) goto out; + + rc = 0; +out: + GC_FREE; + return rc; +} + + +void libxl__device_vsnd_add(libxl__egc *egc, uint32_t domid, libxl_device_vsnd *vsnd, libxl__ao_device *aodev) +{ + STATE_AO_GC(aodev->ao); + flexarray_t *front; + flexarray_t *back; + libxl__device *device; + int rc; + xs_transaction_t t = XBT_NULL; + libxl_domain_config d_config; + libxl_device_vsnd vsnd_saved; + libxl__domain_userdata_lock *lock = NULL; + + libxl_domain_config_init(&d_config); + libxl_device_vsnd_init(&vsnd_saved); + libxl_device_vsnd_copy(CTX, &vsnd_saved, vsnd); + + rc = libxl__device_vsnd_setdefault(gc, vsnd); + if (rc) goto out; + + front = flexarray_make(gc, 32, 1); + back = flexarray_make(gc, 32, 1); + if (vsnd->devid == -1) { + if ((vsnd->devid = libxl__device_nextid(gc, domid, "vsnd")) < 0) { + rc = ERROR_FAIL; + goto out; + } + } + + libxl__update_config_vsnd(gc, &vsnd_saved, vsnd); + + GCNEW(device); + rc = libxl__device_from_vsnd(gc, domid, vsnd, device); + if ( rc != 0 ) goto out; + + flexarray_append(back, "DomD"); + flexarray_append(back, "1"); + flexarray_append(back, "DomU"); + flexarray_append(back, "2"); + flexarray_append(back, "device-id"); + flexarray_append(back, GCSPRINTF("%d", vsnd->devid)); + flexarray_append(back, "short-name"); + flexarray_append(back, vsnd->short_name); + flexarray_append(back, "long-name"); + flexarray_append(back, vsnd->long_name); + flexarray_append(back, "sample-formats"); + flexarray_append(back, vsnd->sample_formats); + flexarray_append(back, "rates"); + flexarray_append(back, vsnd->rates); + flexarray_append(back, "channels-min"); + flexarray_append(back, GCSPRINTF("%d", vsnd->channels_min)); + flexarray_append(back, "channels-max"); + flexarray_append(back, GCSPRINTF("%d", vsnd->channels_max)); + flexarray_append(back, "priority"); + flexarray_append(back, GCSPRINTF("%d", vsnd->priority)); + flexarray_append(back, "frontend-id"); + flexarray_append(back, GCSPRINTF("%d", domid)); + flexarray_append(back, "online"); + flexarray_append(back, "1"); + flexarray_append(back, "state"); + flexarray_append(back, GCSPRINTF("%d", 1)); + flexarray_append(back, "slave-device"); + flexarray_append(back, vsnd->slave_device); + + flexarray_append(front, "device-id"); + flexarray_append(front, GCSPRINTF("%d", vsnd->devid)); + flexarray_append(front, "backend-id"); + flexarray_append(front, GCSPRINTF("%d", vsnd->backend_domid)); + flexarray_append(front, "state"); + flexarray_append(front, GCSPRINTF("%d", 1)); + flexarray_append(front, "alsa-card-id"); + flexarray_append(front, GCSPRINTF("%d", vsnd->alsa_card_id)); + flexarray_append(front, "short-name"); + flexarray_append(front, vsnd->short_name); + flexarray_append(front, "long-name"); + flexarray_append(front, vsnd->long_name); + flexarray_append(front, "sample-formats"); + flexarray_append(front, vsnd->sample_formats); + flexarray_append(front, "rates"); + flexarray_append(front, vsnd->rates); + flexarray_append(front, "channels-min"); + flexarray_append(front, GCSPRINTF("%d", vsnd->channels_min)); + flexarray_append(front, "channels-max"); + flexarray_append(front, GCSPRINTF("%d", vsnd->channels_max)); + flexarray_append(front, "buffer-bytes-max"); + flexarray_append(front, GCSPRINTF("%d", vsnd->buffer_bytes_max)); + flexarray_append(front, "period-bytes-min"); + flexarray_append(front, GCSPRINTF("%d", vsnd->period_bytes_min)); + flexarray_append(front, "period-bytes-max"); + flexarray_append(front, GCSPRINTF("%d", vsnd->period_bytes_max)); + flexarray_append(front, "period-min"); + flexarray_append(front, GCSPRINTF("%d", vsnd->period_min)); + flexarray_append(front, "period-max"); + flexarray_append(front, GCSPRINTF("%d", vsnd->period_max)); + + if (aodev->update_json) { + lock = libxl__lock_domain_userdata(gc, domid); + if (!lock) { + rc = ERROR_LOCK_FAIL; + goto out; + } + + rc = libxl__get_domain_configuration(gc, domid, &d_config); + LOG(INFO, "aodev updates JSON, libxl__get_domain_configuration returned %d", rc); + if (rc) goto out; + + DEVICE_ADD(vsnd, vsnds, domid, &vsnd_saved, COMPARE_DEVID, &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"); + aodev->action = LIBXL__DEVICE_ACTION_ADD; /* for error message */ + rc = ERROR_DEVICE_EXISTS; + goto out; + } + if (aodev->update_json) { + 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); + + rc = libxl__xs_transaction_commit(gc, &t); + + if (!rc) break; + if (rc < 0) goto out; + } + + aodev->dev = device; + aodev->action = LIBXL__DEVICE_ACTION_ADD; + libxl__wait_device_connection(egc, aodev); + + rc = 0; +out: + libxl__xs_transaction_abort(gc, &t); + if (lock) libxl__unlock_domain_userdata(lock); + libxl_device_vsnd_dispose(&vsnd_saved); + libxl_domain_config_dispose(&d_config); + aodev->rc = rc; + if(rc) aodev->callback(egc, aodev); + return; + +} + +libxl_device_vsnd *libxl_device_vsnd_list(libxl_ctx *ctx, uint32_t domid, int *num) +{ + GC_INIT(ctx); + + libxl_device_vsnd* vsnds = NULL; + char* fe_path = NULL; + char** dir = NULL; + unsigned int ndirs = 0; + + *num = 0; + + fe_path = libxl__sprintf(gc, "%s/device/vsnd", libxl__xs_get_dompath(gc, domid)); + dir = libxl__xs_directory(gc, XBT_NULL, fe_path, &ndirs); + if (dir && ndirs) { + vsnds = malloc(sizeof(*vsnds) * ndirs); + libxl_device_vsnd* vsnd; + libxl_device_vsnd* end = vsnds + ndirs; + for(vsnd = vsnds; vsnd < end; ++vsnd, ++dir) { + char* tmp; + + libxl_device_vsnd_init(vsnd); + + vsnd->devid = atoi(*dir); + + tmp = libxl__xs_read(gc, XBT_NULL, + GCSPRINTF("%s/%s/backend-id", + fe_path, *dir)); + vsnd->backend_domid = atoi(tmp); + } + } + *num = ndirs; + + GC_FREE; + return vsnds; +} + +int libxl_device_vsnd_getinfo(libxl_ctx *ctx, uint32_t domid, libxl_device_vsnd *vsnd, libxl_vsndinfo *vsndinfo) +{ + GC_INIT(ctx); + char *dompath, *vsndpath; + char *val; + int rc = 0; + + libxl_vsndinfo_init(vsndinfo); + dompath = libxl__xs_get_dompath(gc, domid); + vsndinfo->devid = vsnd->devid; + + vsndpath = GCSPRINTF("%s/device/vsnd/%d", dompath, vsndinfo->devid); + vsndinfo->backend = xs_read(ctx->xsh, XBT_NULL, + GCSPRINTF("%s/backend", vsndpath), NULL); + if (!vsndinfo->backend) { + goto err; + } + if(!libxl__xs_read(gc, XBT_NULL, vsndinfo->backend)) { + goto err; + } + + val = libxl__xs_read(gc, XBT_NULL, + GCSPRINTF("%s/backend-id", vsndpath)); + vsndinfo->backend_id = val ? strtoul(val, NULL, 10) : -1; + + val = libxl__xs_read(gc, XBT_NULL, + GCSPRINTF("%s/state", vsndpath)); + vsndinfo->state = val ? strtoul(val, NULL, 10) : -1; + + val = libxl__xs_read(gc, XBT_NULL, + GCSPRINTF("%s/event-channel", vsndpath)); + vsndinfo->evtch = val ? strtoul(val, NULL, 10) : -1; + + val = libxl__xs_read(gc, XBT_NULL, + GCSPRINTF("%s/ring-ref", vsndpath)); + vsndinfo->rref = val ? strtoul(val, NULL, 10) : -1; + + vsndinfo->frontend = xs_read(ctx->xsh, XBT_NULL, + GCSPRINTF("%s/frontend", vsndinfo->backend), NULL); + + val = libxl__xs_read(gc, XBT_NULL, + GCSPRINTF("%s/frontend-id", vsndinfo->backend)); + vsndinfo->frontend_id = val ? strtoul(val, NULL, 10) : -1; + + goto exit; +err: + rc = ERROR_FAIL; +exit: + GC_FREE; + return rc; +} /******************************************************************************/ @@ -4410,6 +4747,8 @@ out: * libxl_device_vtpm_destroy * libxl_device_vrtc_remove * libxl_device_vrtc_destroy + * libxl_device_vsnd_remove + * libxl_device_vsnd_destroy */ #define DEFINE_DEVICE_REMOVE(type, removedestroy, f) \ int libxl_device_##type##_##removedestroy(libxl_ctx *ctx, \ @@ -4465,6 +4804,10 @@ DEFINE_DEVICE_REMOVE(vtpm, destroy, 1) DEFINE_DEVICE_REMOVE(vrtc, remove, 0) DEFINE_DEVICE_REMOVE(vrtc, destroy, 1) +/* vsnd */ +DEFINE_DEVICE_REMOVE(vsnd, remove, 0) +DEFINE_DEVICE_REMOVE(vsnd, destroy, 1) + /* channel/console hotunplug is not implemented. There are 2 possibilities: * 1. add support for secondary consoles to xenconsoled * 2. dynamically add/remove qemu chardevs via qmp messages. */ @@ -4479,6 +4822,7 @@ DEFINE_DEVICE_REMOVE(vrtc, destroy, 1) * libxl_device_nic_add * libxl_device_vtpm_add * libxl_device_vrtc_add + * libxl_device_vsnd_add */ #define DEFINE_DEVICE_ADD(type) \ @@ -4513,6 +4857,9 @@ DEFINE_DEVICE_ADD(vtpm) /* vrtc */ DEFINE_DEVICE_ADD(vrtc) +/* vsnd */ +DEFINE_DEVICE_ADD(vsnd) + #undef DEFINE_DEVICE_ADD /******************************************************************************/ @@ -6956,7 +7303,7 @@ int libxl_retrieve_domain_configuration(libxl_ctx *ctx, uint32_t domid, d_config->b_info.max_memkb = max_memkb; } - /* Devices: disk, nic, vtpm, pcidev etc. */ + /* Devices: disk, nic, vtpm, vsnd, pcidev etc. */ /* The MERGE macro implements following logic: * 0. retrieve JSON (done by now) @@ -7030,6 +7377,8 @@ int libxl_retrieve_domain_configuration(libxl_ctx *ctx, uint32_t domid, MERGE(vrtc, vrtcs, COMPARE_DEVID, {}); + MERGE(vsnd, vsnds, COMPARE_DEVID, {}); + MERGE(pci, pcidevs, COMPARE_PCI, {}); /* Take care of removable device. We maintain invariant in the diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h index 9243b86..3cb67e2 100644 --- a/tools/libxl/libxl.h +++ b/tools/libxl/libxl.h @@ -1451,6 +1451,22 @@ int libxl_device_vrtc_destroy(libxl_ctx *ctx, uint32_t domid, libxl_device_vrtc *libxl_device_vrtc_list(libxl_ctx *ctx, uint32_t domid, int *num); int libxl_device_vrtc_getinfo(libxl_ctx *ctx, uint32_t domid, libxl_device_vrtc *vrtc, libxl_vrtcinfo *vrtcinfo); +/* Audio */ +int libxl_device_vsnd_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vsnd *vsnd, + const libxl_asyncop_how *ao_how) + LIBXL_EXTERNAL_CALLERS_ONLY; +int libxl_device_vsnd_remove(libxl_ctx *ctx, uint32_t domid, + libxl_device_vsnd *vsnd, + const libxl_asyncop_how *ao_how) + LIBXL_EXTERNAL_CALLERS_ONLY; +int libxl_device_vsnd_destroy(libxl_ctx *ctx, uint32_t domid, + libxl_device_vsnd *vsnd, + const libxl_asyncop_how *ao_how) + LIBXL_EXTERNAL_CALLERS_ONLY; + +libxl_device_vsnd *libxl_device_vsnd_list(libxl_ctx *ctx, uint32_t domid, int *num); +int libxl_device_vsnd_getinfo(libxl_ctx *ctx, uint32_t domid, + libxl_device_vsnd *vsnd, libxl_vsndinfo *vsndinfo); /* Keyboard */ int libxl_device_vkb_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vkb *vkb, diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c index 1206c34..8ff4178 100644 --- a/tools/libxl/libxl_create.c +++ b/tools/libxl/libxl_create.c @@ -736,6 +736,8 @@ static void domcreate_attach_vtpms(libxl__egc *egc, libxl__multidev *multidev, int ret); static void domcreate_attach_vrtcs(libxl__egc *egc, libxl__multidev *multidev, int ret); +static void domcreate_attach_vsnds(libxl__egc *egc, libxl__multidev *multidev, + int ret); static void domcreate_attach_pci(libxl__egc *egc, libxl__multidev *aodevs, int ret); static void domcreate_attach_dtdev(libxl__egc *egc, @@ -1427,12 +1429,45 @@ static void domcreate_attach_vrtcs(libxl__egc *egc, if (d_config->num_vrtcs > 0) { /* Attach vrtcs */ libxl__multidev_begin(ao, &dcs->multidev); - dcs->multidev.callback = domcreate_attach_pci; + dcs->multidev.callback = domcreate_attach_vsnds; libxl__add_vrtcs(egc, ao, domid, d_config, &dcs->multidev); libxl__multidev_prepared(egc, &dcs->multidev, 0); return; } + domcreate_attach_vsnds(egc, multidev, 0); + return; + +error_out: + assert(ret); + domcreate_complete(egc, dcs, ret); +} + +static void domcreate_attach_vsnds(libxl__egc *egc, + libxl__multidev *multidev, + int ret) +{ + libxl__domain_create_state *dcs = CONTAINER_OF(multidev, *dcs, multidev); + STATE_AO_GC(dcs->ao); + int domid = dcs->guest_domid; + + libxl_domain_config* const d_config = dcs->guest_config; + + if(ret) { + LOG(ERROR, "unable to add vrtc devices"); + goto error_out; + } + + /* Plug vsnd devices */ + if (d_config->num_vsnds > 0) { + /* Attach vsnds */ + libxl__multidev_begin(ao, &dcs->multidev); + dcs->multidev.callback = domcreate_attach_pci; + libxl__add_vsnds(egc, ao, domid, d_config, &dcs->multidev); + libxl__multidev_prepared(egc, &dcs->multidev, 0); + return; + } + domcreate_attach_pci(egc, multidev, 0); return; @@ -1454,7 +1489,7 @@ static void domcreate_attach_pci(libxl__egc *egc, libxl__multidev *multidev, libxl_domain_config *const d_config = dcs->guest_config; if (ret) { - LOG(ERROR, "unable to add vrtc devices"); + LOG(ERROR, "unable to add vsnd devices"); goto error_out; } diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c index 72f09a0..419af16 100644 --- a/tools/libxl/libxl_device.c +++ b/tools/libxl/libxl_device.c @@ -545,6 +545,7 @@ void libxl__multidev_prepared(libxl__egc *egc, * libxl__add_nics * libxl__add_vtpms * libxl__add_vrtcs + * libxl__add_vsnds */ #define DEFINE_DEVICES_ADD(type) \ @@ -565,6 +566,7 @@ DEFINE_DEVICES_ADD(disk) DEFINE_DEVICES_ADD(nic) DEFINE_DEVICES_ADD(vtpm) DEFINE_DEVICES_ADD(vrtc) +DEFINE_DEVICES_ADD(vsnd) #undef DEFINE_DEVICES_ADD diff --git a/tools/libxl/libxl_internal.c b/tools/libxl/libxl_internal.c index 366ea05..f75840d 100644 --- a/tools/libxl/libxl_internal.c +++ b/tools/libxl/libxl_internal.c @@ -547,6 +547,10 @@ void libxl__update_domain_configuration(libxl__gc *gc, for (i = 0; i < src->num_vtpms; i++) libxl__update_config_vtpm(gc, &dst->vtpms[i], &src->vtpms[i]); + /* update vsnd information */ + for (i = 0; i < src->num_vsnds; i++) + libxl__update_config_vsnd(gc, &dst->vsnds[i], &src->vsnds[i]); + /* update guest UUID */ libxl_uuid_copy(CTX, &dst->c_info.uuid, &src->c_info.uuid); diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h index 2a423b5..d78dd79 100644 --- a/tools/libxl/libxl_internal.h +++ b/tools/libxl/libxl_internal.h @@ -477,7 +477,8 @@ typedef struct { (dev)->backend_kind == LIBXL__DEVICE_KIND_QDISK || \ (dev)->backend_kind == LIBXL__DEVICE_KIND_VFB || \ (dev)->backend_kind == LIBXL__DEVICE_KIND_VKBD || \ - (dev)->backend_kind == LIBXL__DEVICE_KIND_VRTC) + (dev)->backend_kind == LIBXL__DEVICE_KIND_VRTC || \ + (dev)->backend_kind == LIBXL__DEVICE_KIND_VSND) #define XC_PCI_BDF "0x%x, 0x%x, 0x%x, 0x%x" #define PCI_DEVFN(slot, func) ((((slot) & 0x1f) << 3) | ((func) & 0x07)) @@ -1188,6 +1189,7 @@ _hidden int libxl__device_nic_setdefault(libxl__gc *gc, libxl_device_nic *nic, uint32_t domid); _hidden int libxl__device_vtpm_setdefault(libxl__gc *gc, libxl_device_vtpm *vtpm); _hidden int libxl__device_vrtc_setdefault(libxl__gc *gc, libxl_device_vrtc *vrtc); +_hidden int libxl__device_vsnd_setdefault(libxl__gc *gc, libxl_device_vsnd *vsnd); _hidden int libxl__device_vfb_setdefault(libxl__gc *gc, libxl_device_vfb *vfb); _hidden int libxl__device_vkb_setdefault(libxl__gc *gc, libxl_device_vkb *vkb); _hidden int libxl__device_pci_setdefault(libxl__gc *gc, libxl_device_pci *pci); @@ -2572,6 +2574,11 @@ _hidden void libxl__device_vrtc_add(libxl__egc *egc, uint32_t domid, libxl_device_vrtc *vrtc, libxl__ao_device *aodev); +/* AO operation to connect a sound device */ +_hidden void libxl__device_vsnd_add(libxl__egc *egc, uint32_t domid, + libxl_device_vsnd *vsnd, + libxl__ao_device *aodev); + /* Internal function to connect a vkb device */ _hidden int libxl__device_vkb_add(libxl__gc *gc, uint32_t domid, libxl_device_vkb *vkb); @@ -3291,6 +3298,10 @@ _hidden void libxl__add_vtpms(libxl__egc *egc, libxl__ao *ao, uint32_t domid, _hidden void libxl__add_vrtcs(libxl__egc *egc, libxl__ao *ao, uint32_t domid, libxl_domain_config *d_config, libxl__multidev *multidev); + +_hidden void libxl__add_vsnds(libxl__egc *egc, libxl__ao *ao, uint32_t domid, + libxl_domain_config *d_config, + libxl__multidev *multidev); /*----- device model creation -----*/ /* First layer; wraps libxl__spawn_spawn. */ @@ -3954,6 +3965,13 @@ static inline void libxl__update_config_vtpm(libxl__gc *gc, libxl_uuid_copy(CTX, &dst->uuid, &src->uuid); } +static inline void libxl__update_config_vsnd(libxl__gc *gc, + libxl_device_vsnd *dst, + libxl_device_vsnd *src) +{ + dst->devid = src->devid; +} + /* Macros used to compare device identifier. Returns true if the two * devices have same identifier. */ #define COMPARE_DEVID(a, b) ((a)->devid == (b)->devid) diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl index 27a750c..8fa29b1 100644 --- a/tools/libxl/libxl_types.idl +++ b/tools/libxl/libxl_types.idl @@ -551,6 +551,26 @@ libxl_device_vrtc = Struct("device_vrtc", [ ("device", string), ]) +libxl_device_vsnd = Struct("device_vsnd", [ + ("backend_domid", libxl_domid), + ("backend_domname", string), + ("devid", libxl_devid), + ("short_name", string), + ("long_name", string), + ("sample_formats", string), + ("rates", string), + ("channels_min", integer), + ("channels_max", integer), + ("priority", integer), + ("slave_device", string), + ("alsa_card_id", integer), + ("buffer_bytes_max", integer), + ("period_bytes_min", integer), + ("period_bytes_max", integer), + ("period_min", integer), + ("period_max", integer), + ]) + libxl_device_disk = Struct("device_disk", [ ("backend_domid", libxl_domid), ("backend_domname", string), @@ -639,6 +659,7 @@ libxl_domain_config = Struct("domain_config", [ ("vkbs", Array(libxl_device_vkb, "num_vkbs")), ("vtpms", Array(libxl_device_vtpm, "num_vtpms")), ("vrtcs", Array(libxl_device_vrtc, "num_vrtcs")), + ("vsnds", Array(libxl_device_vsnd, "num_vsnds")), # a channel manifests as a console with a name, # see docs/misc/channels.txt ("channels", Array(libxl_device_channel, "num_channels")), @@ -695,6 +716,17 @@ libxl_vrtcinfo = Struct("vrtcinfo", [ ("rref", integer), ], dir=DIR_OUT) +libxl_vsndinfo = Struct("vsndinfo", [ + ("backend", string), + ("backend_id", uint32), + ("frontend", string), + ("frontend_id", uint32), + ("devid", libxl_devid), + ("state", integer), + ("evtch", integer), + ("rref", integer), + ], dir=DIR_OUT) + libxl_vcpuinfo = Struct("vcpuinfo", [ ("vcpuid", uint32), ("cpu", uint32), diff --git a/tools/libxl/libxl_types_internal.idl b/tools/libxl/libxl_types_internal.idl index 764efb8..ec63e23 100644 --- a/tools/libxl/libxl_types_internal.idl +++ b/tools/libxl/libxl_types_internal.idl @@ -23,6 +23,7 @@ libxl__device_kind = Enumeration("device_kind", [ (7, "CONSOLE"), (8, "VTPM"), (9, "VRTC"), + (10, "VSND"), ]) libxl__console_backend = Enumeration("console_backend", [ diff --git a/tools/libxl/libxl_utils.h b/tools/libxl/libxl_utils.h index d1b825c..f6532ce 100644 --- a/tools/libxl/libxl_utils.h +++ b/tools/libxl/libxl_utils.h @@ -80,6 +80,9 @@ int libxl_devid_to_device_vtpm(libxl_ctx *ctx, uint32_t domid, int libxl_devid_to_device_vrtc(libxl_ctx *ctx, uint32_t domid, int devid, libxl_device_vrtc *vrtc); +int libxl_devid_to_device_vsnd(libxl_ctx *ctx, uint32_t domid, + int devid, libxl_device_vsnd *vsnd); + int libxl_bitmap_alloc(libxl_ctx *ctx, libxl_bitmap *bitmap, int n_bits); /* Allocated bimap is from malloc, libxl_bitmap_dispose() to be * called by the application when done. */ diff --git a/tools/libxl/xl.h b/tools/libxl/xl.h index 3d46efb..81a78c0 100644 --- a/tools/libxl/xl.h +++ b/tools/libxl/xl.h @@ -85,6 +85,9 @@ int main_blockdetach(int argc, char **argv); int main_vrtcattach(int argc, char **argv); int main_vrtclist(int argc, char **argv); int main_vrtcdetach(int argc, char **argv); +int main_vsndattach(int argc, char **argv); +int main_vsndlist(int argc, char **argv); +int main_vsnddetach(int argc, char **argv); int main_vtpmattach(int argc, char **argv); int main_vtpmlist(int argc, char **argv); int main_vtpmdetach(int argc, char **argv); diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c index 77701e0..cb2d8c6 100644 --- a/tools/libxl/xl_cmdimpl.c +++ b/tools/libxl/xl_cmdimpl.c @@ -627,6 +627,15 @@ static void set_default_nic_values(libxl_device_nic *nic) } } +static void set_default_vsnd_values(libxl_device_vsnd *vsnd) +{ + vsnd->short_name = "Unknown"; + vsnd->long_name = "Unknown"; + vsnd->sample_formats = ""; + vsnd->rates = ""; + vsnd->slave_device = ""; +} + static void split_string_into_string_list(const char *str, const char *delim, libxl_string_list *psl) @@ -1262,7 +1271,7 @@ static void parse_config_data(const char *config_source, const char *buf; long l, vcpus = 0; XLU_Config *config; - XLU_ConfigList *cpus, *vbds, *nics, *pcis, *cvfbs, *cpuids, *vtpms, *vrtcs; + XLU_ConfigList *cpus, *vbds, *nics, *pcis, *cvfbs, *cpuids, *vtpms, *vrtcs, *vsnds; XLU_ConfigList *channels, *ioports, *irqs, *iomem, *viridian, *dtdevs; int num_ioports, num_irqs, num_iomem, num_cpus, num_viridian; int pci_power_mgmt = 0; @@ -1892,6 +1901,83 @@ static void parse_config_data(const char *config_source, } } + if (!xlu_cfg_get_list(config, "vsnd", &vsnds, 0, 0)) { + d_config->num_vsnds = 0; + d_config->vsnds = NULL; + while ((buf = xlu_cfg_get_listitem(vsnds, d_config->num_vsnds)) != NULL) { + libxl_device_vsnd *vsnd; + libxl_string_list pairs; + char *path = NULL; + int len; + + vsnd = ARRAY_EXTEND_INIT(d_config->vsnds, d_config->num_vsnds, + libxl_device_vsnd_init); + + split_string_into_string_list(buf, ",", &pairs); + len = libxl_string_list_length(&pairs); + + for (i = 0; i < len; i++) { + char *key, *key_untrimmed, *value, *value_untrimmed; + int rc; + rc = split_string_into_pair(pairs[i], "=", + &key_untrimmed, + &value_untrimmed); + if (rc != 0) { + fprintf(stderr, "failed to parse vsnd configuration: %s", + pairs[i]); + exit(1); + } + trim(isspace, key_untrimmed, &key); + trim(isspace, value_untrimmed, &value); + + if (!strcmp(key, "backendid")) { + vsnd->backend_domid = atoi(value); + } else if (!strcmp(key, "backend")) { + replace_string(&vsnd->backend_domname, value); + } else if (!strcmp(key, "devid")) { + vsnd->devid = atoi(value); + } else if (!strcmp(key, "shortname")) { + replace_string(&vsnd->short_name, value); + } else if (!strcmp(key, "longname")) { + replace_string(&vsnd->long_name, value); + } else if (!strcmp(key, "sampleformats")) { + replace_string(&vsnd->sample_formats, value); + } else if (!strcmp(key, "rates")) { + replace_string(&vsnd->rates, value); + } else if (!strcmp(key, "channels_min")) { + vsnd->channels_min = atoi(value); + } else if (!strcmp(key, "channels_max")) { + vsnd->channels_max = atoi(value); + } else if (!strcmp(key, "priority")) { + vsnd->priority = atoi(value); + } else if (!strcmp(key, "slave")) { + replace_string(&vsnd->slave_device, value); + } else if (!strcmp(key, "alsacardid")) { + vsnd->alsa_card_id = atoi(value); + } else if (!strcmp(key, "bufferbytesmax")) { + vsnd->buffer_bytes_max = atoi(value); + } else if (!strcmp(key, "periodbytesmin")) { + vsnd->period_bytes_min = atoi(value); + } else if (!strcmp(key, "periodbytesmax")) { + vsnd->period_bytes_max = atoi(value); + } else if (!strcmp(key, "periodmin")) { + vsnd->period_min = atoi(value); + } else if (!strcmp(key, "periodmax")) { + vsnd->period_max = atoi(value); + } else { + fprintf(stderr, "unknown vsnd parameter '%s'," + " ignoring\n", key); + } + free(key); + free(key_untrimmed); + free(value); + free(value_untrimmed); + } + libxl_string_list_dispose(&pairs); + free(path); + } + } + if (!xlu_cfg_get_list (config, "channel", &channels, 0, 0)) { d_config->num_channels = 0; d_config->channels = NULL; @@ -6894,6 +6980,147 @@ int main_vrtcdetach(int argc, char **argv) return rc; } + +int main_vsndattach(int argc, char **argv) +{ + int opt; + uint32_t fe_domid; + libxl_device_vsnd vsnd; + char *oparg; + + SWITCH_FOREACH_OPT(opt, "", NULL, "vsnd-attach", 1) { + /* No options */ + } + + if (libxl_domain_qualifier_to_domid(ctx, argv[optind], &fe_domid) < 0) { + fprintf(stderr, "%s is an invalid domain identifier\n", argv[optind]); + return 1; + } + optind++; + + libxl_device_vsnd_init(&vsnd); + set_default_vsnd_values(&vsnd); + + for (argv += optind+1, argc -= optind+1; argc > 0; ++argv, --argc) { + if (MATCH_OPTION("backend", *argv, oparg)) { + replace_string(&vsnd.backend_domname, oparg); + } else if (MATCH_OPTION("devid", *argv, oparg)) { + vsnd.devid = atoi(oparg); + } else if (MATCH_OPTION("shortname", *argv, oparg)) { + replace_string(&vsnd.short_name, oparg); + } else if (MATCH_OPTION("longname", *argv, oparg)) { + replace_string(&vsnd.long_name, oparg); + } else if (MATCH_OPTION("sampleformats", *argv, oparg)) { + replace_string(&vsnd.sample_formats, oparg); + } else if (MATCH_OPTION("rates", *argv, oparg)) { + replace_string(&vsnd.rates, oparg); + } else if (MATCH_OPTION("channelsmin", *argv, oparg)) { + vsnd.channels_min = atoi(oparg); + } else if (MATCH_OPTION("channelsmax", *argv, oparg)) { + vsnd.channels_max = atoi(oparg); + } else if (MATCH_OPTION("priority", *argv, oparg)) { + vsnd.priority = atoi(oparg); + } else if (MATCH_OPTION("slave", *argv, oparg)) { + replace_string(&vsnd.slave_device, oparg); + } else if (MATCH_OPTION("alsacardid", *argv, oparg)) { + vsnd.alsa_card_id = atoi(oparg); + } else if (MATCH_OPTION("bufferbytesmax", *argv, oparg)) { + vsnd.buffer_bytes_max = atoi(oparg); + } else if (MATCH_OPTION("periodbytesmin", *argv, oparg)) { + vsnd.period_bytes_min = atoi(oparg); + } else if (MATCH_OPTION("periodbytesmax", *argv, oparg)) { + vsnd.period_bytes_max = atoi(oparg); + } else if (MATCH_OPTION("periodmin", *argv, oparg)) { + vsnd.period_min = atoi(oparg); + } else if (MATCH_OPTION("periodmax", *argv, oparg)) { + vsnd.period_max = atoi(oparg); + } else { + fprintf(stderr, "unrecognized argument `%s'\n", *argv); + return 1; + } + } + + if (dryrun_only) { + char *json = libxl_device_vsnd_to_json(ctx, &vsnd); + printf("vsnd: %s\n", json); + free(json); + if (ferror(stdout) || fflush(stdout)) { perror("stdout"); exit(-1); } + return 0; + } + + if (libxl_device_vsnd_add(ctx, fe_domid, &vsnd, 0)) { + fprintf(stderr, "libxl_device_vsnd_add failed.\n"); + return 1; + } + return 0; +} + +int main_vsndlist(int argc, char **argv) +{ + int opt; + int i, nb; + libxl_device_vsnd *vsnds; + libxl_vsndinfo vsndinfo; + + SWITCH_FOREACH_OPT(opt, "", NULL, "vsnd-list", 1) { + /* No options */ + } + + printf("%-5s %-3s %-6s %-5s %-6s %-8s %-40s %-40s\n", + "Vdev", "BE", "handle", "state", "evt-ch", "ring-ref", "BE-path", "FE-path"); + for (argv += optind, argc -= optind; argc > 0; --argc, ++argv) { + uint32_t domid; + if (libxl_domain_qualifier_to_domid(ctx, *argv, &domid) < 0) { + fprintf(stderr, "%s is an invalid domain identifier\n", *argv); + continue; + } + vsnds = libxl_device_vsnd_list(ctx, domid, &nb); + if (!vsnds) { + continue; + } + for (i=0; i<nb; i++) { + if (!libxl_device_vsnd_getinfo(ctx, domid, &vsnds[i], &vsndinfo)) { + /* Vdev BE hdl st evch rref BE-path FE-path */ + printf("%-5d %-3d %-6d %-5d %-6d %-8d %-40s %-40s\n", + vsndinfo.devid, vsndinfo.backend_id, vsndinfo.frontend_id, + vsndinfo.state, vsndinfo.evtch, vsndinfo.rref, vsndinfo.backend, + vsndinfo.frontend); + libxl_vsndinfo_dispose(&vsndinfo); + } + libxl_device_vsnd_dispose(&vsnds[i]); + } + free(vsnds); + } + return 0; +} + +int main_vsnddetach(int argc, char **argv) +{ + uint32_t domid, devid; + int opt, rc = 0; + libxl_device_vsnd vsnd; + + SWITCH_FOREACH_OPT(opt, "", NULL, "vsnd-detach", 2) { + /* No options */ + } + + domid = find_domain(argv[optind]); + devid = atoi(argv[optind+1]); + + if (libxl_devid_to_device_vsnd(ctx, domid, devid, &vsnd)) { + fprintf(stderr, "Error: Device %s not connected.\n", argv[optind+1]); + return 1; + } + + rc = libxl_device_vsnd_remove(ctx, domid, &vsnd, 0); + if (rc) { + fprintf(stderr, "libxl_device_vsnd_remove failed.\n"); + return 1; + } + libxl_device_vsnd_dispose(&vsnd); + return rc; +} + int main_vtpmattach(int argc, char **argv) { int opt; diff --git a/tools/libxl/xl_cmdtable.c b/tools/libxl/xl_cmdtable.c index 8b8971e..78f0700 100644 --- a/tools/libxl/xl_cmdtable.c +++ b/tools/libxl/xl_cmdtable.c @@ -366,6 +366,26 @@ struct cmd_spec cmd_table[] = { "Destroy a domain's virtual rtc device", "<Domain> <DevId>", }, + { "vsnd-attach", + &main_vsndattach, 1, 1, + "Create a new virtual audio device", + "<Domain> [backend=<BackDomain>] [devid=<DeviceId>] [shortname=<ShortName>]\n" + "[longname=<LongName>] [sampleformats=<SampleFormats>] [rates=<Rates>]\n" + "[channelsmin=<ChannelsMin>] [channelsmax=<ChannelsMax>] [priority=<Priority>]\n" + "[slave=<SlaveDevice>] [alsacardid=<AlsaCardId>] [bufferbytesmax=<BufferBytesMax>]\n" + "[periodbytesmin=<PeriodBytesMin>] [periodbytesmax=<PeriodBytesMax>]\n" + "[periodmin=<PeriodMin>] [periodmax=<PeriodMax>]", + }, + { "vsnd-list", + &main_vsndlist, 0, 0, + "List virtual audio devices for a domain", + "<Domain(s)>", + }, + { "vsnd-detach", + &main_vsnddetach, 0, 1, + "Destroy a domain's virtual audio device", + "<Domain> <DevId|uuid>", + }, { "vtpm-attach", &main_vtpmattach, 1, 1, "Create a new virtual TPM device", -- 2.8.2 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |