[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 2/5] libxl: add vsnd list and info
From: Oleksandr Grytsov <oleksandr_grytsov@xxxxxxxx> Add getting vsnd list amd info API Signed-off-by: Oleksandr Grytsov <oleksandr_grytsov@xxxxxxxx> --- tools/libxl/libxl.h | 10 ++ tools/libxl/libxl_types.idl | 19 +++ tools/libxl/libxl_utils.h | 3 + tools/libxl/libxl_vsnd.c | 359 +++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 388 insertions(+), 3 deletions(-) diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h index 7200d49..acb73ce 100644 --- a/tools/libxl/libxl.h +++ b/tools/libxl/libxl.h @@ -1927,6 +1927,16 @@ int libxl_device_vsnd_destroy(libxl_ctx *ctx, uint32_t domid, 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) + LIBXL_EXTERNAL_CALLERS_ONLY; +void libxl_device_vsnd_list_free(libxl_device_vsnd* list, int num) + LIBXL_EXTERNAL_CALLERS_ONLY; +int libxl_device_vsnd_getinfo(libxl_ctx *ctx, uint32_t domid, + libxl_device_vsnd *vsnd, + libxl_vsndinfo *vsndlinfo) + LIBXL_EXTERNAL_CALLERS_ONLY; + /* Keyboard */ int libxl_device_vkb_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vkb *vkb, const libxl_asyncop_how *ao_how) diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl index fb3e5e8..cd0c06f 100644 --- a/tools/libxl/libxl_types.idl +++ b/tools/libxl/libxl_types.idl @@ -988,6 +988,25 @@ libxl_vdisplinfo = Struct("vdisplinfo", [ ("connectors", Array(libxl_connectorinfo, "num_connectors")) ], dir=DIR_OUT) +libxl_streaminfo = Struct("streaminfo", [ + ("req_evtch", integer), + ("req_rref", integer) + ]) + +libxl_pcminfo = Struct("pcminfo", [ + ("streams", Array(libxl_streaminfo, "num_vsnd_streams")) + ]) + +libxl_vsndinfo = Struct("vsndinfo", [ + ("backend", string), + ("backend_id", uint32), + ("frontend", string), + ("frontend_id", uint32), + ("devid", libxl_devid), + ("state", integer), + ("pcms", Array(libxl_pcminfo, "num_vsnd_pcms")) + ]) + # NUMA node characteristics: size and free are how much memory it has, and how # much of it is free, respectively. dists is an array of distances from this # node to each other node. diff --git a/tools/libxl/libxl_utils.h b/tools/libxl/libxl_utils.h index 9e743dc..5455752 100644 --- a/tools/libxl/libxl_utils.h +++ b/tools/libxl/libxl_utils.h @@ -82,6 +82,9 @@ int libxl_devid_to_device_usbctrl(libxl_ctx *ctx, uint32_t domid, int libxl_devid_to_device_vdispl(libxl_ctx *ctx, uint32_t domid, int devid, libxl_device_vdispl *vdispl); +int libxl_devid_to_device_vsnd(libxl_ctx *ctx, uint32_t domid, + int devid, libxl_device_vsnd *vsnd); + int libxl_ctrlport_to_device_usbdev(libxl_ctx *ctx, uint32_t domid, int ctrl, int port, libxl_device_usbdev *usbdev); diff --git a/tools/libxl/libxl_vsnd.c b/tools/libxl/libxl_vsnd.c index 26885f9..0e7b29c 100644 --- a/tools/libxl/libxl_vsnd.c +++ b/tools/libxl/libxl_vsnd.c @@ -37,20 +37,239 @@ static int libxl__device_from_vsnd(libxl__gc *gc, uint32_t domid, return 0; } +static int libxl__sample_rates_from_string(libxl__gc *gc, const char *str, + libxl_vsnd_params *params) +{ + char *tmp = libxl__strdup(gc, str); + + params->num_sample_rates = 0; + params->sample_rates = NULL; + + char *p = strtok(tmp, " ,"); + + while (p != NULL) { + params->sample_rates = realloc(params->sample_rates, + sizeof(*params->sample_rates) * + (params->num_sample_rates + 1)); + params->sample_rates[params->num_sample_rates++] = strtoul(p, NULL, 0); + p = strtok(NULL, " ,"); + } + + return 0; +} + +static int libxl__sample_formats_from_string(libxl__gc *gc, const char *str, + libxl_vsnd_params *params) +{ + int rc; + char *tmp = libxl__strdup(gc, str); + + params->num_sample_formats = 0; + params->sample_formats = NULL; + + char *p = strtok(tmp, " ,"); + + while (p != NULL) { + params->sample_formats = realloc(params->sample_formats, + sizeof(*params->sample_formats) * + (params->num_sample_formats + 1)); + + libxl_vsnd_pcm_format format; + + rc = libxl_vsnd_pcm_format_from_string(p, &format); + if (rc) return rc; + + params->sample_formats[params->num_sample_formats++] = format; + p = strtok(NULL, " ,"); + } + + return 0; +} + +static int libxl__params_from_xenstore(libxl__gc *gc, const char *path, + libxl_vsnd_params *params) +{ + const char *tmp; + int rc; + + rc = libxl__xs_read_checked(gc, XBT_NULL, + GCSPRINTF("%s/"XENSND_FIELD_SAMPLE_RATES, + path), &tmp); + if (rc) return rc; + + if (tmp) { + rc = libxl__sample_rates_from_string(gc, tmp, params); + if (rc) return rc; + } + + rc = libxl__xs_read_checked(gc, XBT_NULL, + GCSPRINTF("%s/"XENSND_FIELD_SAMPLE_FORMATS, + path), &tmp); + if (rc) return rc; + + if (tmp) { + rc = libxl__sample_formats_from_string(gc, tmp, params); + if (rc) return rc; + } + + rc = libxl__xs_read_checked(gc, XBT_NULL, + GCSPRINTF("%s/"XENSND_FIELD_CHANNELS_MIN, + path), &tmp); + if (rc) return rc; + + if (tmp) { + params->channels_min = strtoul(tmp, NULL, 0); + } + + rc = libxl__xs_read_checked(gc, XBT_NULL, + GCSPRINTF("%s/"XENSND_FIELD_CHANNELS_MAX, + path), &tmp); + if (rc) return rc; + + if (tmp) { + params->channels_max = strtoul(tmp, NULL, 0); + } + + rc = libxl__xs_read_checked(gc, XBT_NULL, + GCSPRINTF("%s/"XENSND_FIELD_BUFFER_SIZE, + path), &tmp); + if (rc) return rc; + + if (tmp) { + params->buffer_size = strtoul(tmp, NULL, 0); + } + + return 0; +} + +static int libxl__stream_from_xenstore(libxl__gc *gc, const char *path, + libxl_vsnd_stream *stream) +{ + const char *tmp; + int rc; + + rc = libxl__xs_read_checked(gc, XBT_NULL, + GCSPRINTF("%s/"XENSND_FIELD_STREAM_UNIQUE_ID, + path), &tmp); + if (rc) return rc; + + if (tmp) { + stream->id = strtoul(tmp, NULL, 0); + } + + rc = libxl__xs_read_checked(gc, XBT_NULL, + GCSPRINTF("%s/"XENSND_FIELD_TYPE, + path), &tmp); + if (rc) return rc; + + if (tmp) { + libxl_vsnd_stream_type type; + + rc = libxl_vsnd_stream_type_from_string(tmp, &type); + if (rc) return rc; + + stream->type = type; + } + + rc = libxl__params_from_xenstore(gc, path, &stream->params); + if (rc) return rc; + + return 0; +} + +static int libxl__pcm_from_xenstore(libxl__gc *gc, const char *path, + libxl_vsnd_pcm *pcm) +{ + libxl_ctx *ctx = libxl__gc_owner(gc); + const char *tmp; + int rc; + + pcm->name = xs_read(ctx->xsh, XBT_NULL, + GCSPRINTF("%s/"XENSND_FIELD_DEVICE_NAME, path), NULL); + + rc = libxl__params_from_xenstore(gc, path, &pcm->params); + + pcm->streams = NULL; + pcm->num_vsnd_streams = 0; + + do { + char *stream_path = GCSPRINTF("%s/%d", path, pcm->num_vsnd_streams); + + rc = libxl__xs_read_checked(gc, XBT_NULL, stream_path, &tmp); + if (rc) return rc; + + if (tmp) { + pcm->streams = realloc(pcm->streams, sizeof(*pcm->streams) * + (++pcm->num_vsnd_streams)); + + libxl_vsnd_stream_init(&pcm->streams[pcm->num_vsnd_streams - 1]); + + rc = libxl__stream_from_xenstore(gc, stream_path, + &pcm->streams[pcm->num_vsnd_streams + - 1]); + if (rc) return rc; + } + } while (tmp); + + + return 0; +} + static int libxl__vsnd_from_xenstore(libxl__gc *gc, const char *libxl_path, libxl_devid devid, libxl_device_vsnd *vsnd) { - const char *be_path; + libxl_ctx *ctx = libxl__gc_owner(gc); + const char *tmp; + const char *fe_path; int rc; vsnd->devid = devid; rc = libxl__xs_read_mandatory(gc, XBT_NULL, GCSPRINTF("%s/backend", libxl_path), - &be_path); + &tmp); + if (rc) return rc; + + rc = libxl__backendpath_parse_domid(gc, tmp, &vsnd->backend_domid); + if (rc) return rc; + + rc = libxl__xs_read_mandatory(gc, XBT_NULL, + GCSPRINTF("%s/frontend", libxl_path), + &fe_path); if (rc) return rc; - return libxl__backendpath_parse_domid(gc, be_path, &vsnd->backend_domid); + vsnd->short_name = xs_read(ctx->xsh, XBT_NULL, + GCSPRINTF("%s/"XENSND_FIELD_VCARD_SHORT_NAME, + fe_path), NULL); + + vsnd->long_name = xs_read(ctx->xsh, XBT_NULL, + GCSPRINTF("%s/"XENSND_FIELD_VCARD_LONG_NAME, + fe_path), NULL); + + rc = libxl__params_from_xenstore(gc, fe_path, &vsnd->params); + + vsnd->pcms = NULL; + vsnd->num_vsnd_pcms = 0; + + do { + char *pcm_path = GCSPRINTF("%s/%d", fe_path, vsnd->num_vsnd_pcms); + + rc = libxl__xs_read_checked(gc, XBT_NULL, pcm_path, &tmp); + if (rc) return rc; + + if (tmp) { + vsnd->pcms = realloc(vsnd->pcms, sizeof(*vsnd->pcms) * + (++vsnd->num_vsnd_pcms)); + + libxl_vsnd_pcm_init(&vsnd->pcms[vsnd->num_vsnd_pcms - 1]); + + rc = libxl__pcm_from_xenstore(gc, pcm_path, + &vsnd->pcms[vsnd->num_vsnd_pcms - 1]); + if (rc) return rc; + } + } while (tmp); + + return 0; } static void libxl__update_config_vsnd(libxl__gc *gc, @@ -286,10 +505,144 @@ static int libxl__set_xenstore_vsnd(libxl__gc *gc, uint32_t domid, return 0; } +static int libxl__device_stream_getinfo(libxl__gc *gc, const char *path, + libxl_vsnd_pcm* pcm, + libxl_pcminfo *info) +{ + const char *tmp; + int i; + int rc; + + info->num_vsnd_streams = pcm->num_vsnd_streams; + info->streams = malloc(sizeof(*info->streams) * info->num_vsnd_streams); + + for (i = 0; i < info->num_vsnd_streams; i++) + { + libxl_streaminfo_init(&info->streams[i]); + + rc = libxl__xs_read_checked(gc, XBT_NULL, + GCSPRINTF("%s/%d/"XENSND_FIELD_RING_REF, + path, i), &tmp); + if (rc) return rc; + + info->streams[i].req_rref = tmp ? strtoul(tmp, NULL, 10) : -1; + + rc = libxl__xs_read_checked(gc, XBT_NULL, + GCSPRINTF("%s/%d/"XENSND_FIELD_EVT_CHNL, + path, i), &tmp); + if (rc) return rc; + + info->streams[i].req_evtch = tmp ? strtoul(tmp, NULL, 10) : -1; + } + + return 0; +} + +static int libxl__device_pcm_getinfo(libxl__gc *gc, const char *path, + libxl_device_vsnd *vsnd, + libxl_vsndinfo *info) +{ + int i; + int rc; + + info->num_vsnd_pcms = vsnd->num_vsnd_pcms; + info->pcms = malloc(sizeof(*info->pcms) * info->num_vsnd_pcms); + + for (i = 0; i < info->num_vsnd_pcms; i++) + { + libxl_pcminfo_init(&info->pcms[i]); + + rc = libxl__device_stream_getinfo(gc, GCSPRINTF("%s/%d", path, i), + &vsnd->pcms[i], &info->pcms[i]); + if (rc) return rc; + } + + return 0; +} + +int libxl_device_vsnd_getinfo(libxl_ctx *ctx, uint32_t domid, + libxl_device_vsnd *vsnd, + libxl_vsndinfo *info) +{ + GC_INIT(ctx); + char *libxl_path, *dompath, *devpath; + const char *val; + int rc; + + libxl_vsndinfo_init(info); + dompath = libxl__xs_get_dompath(gc, domid); + info->devid = vsnd->devid; + + devpath = GCSPRINTF("%s/device/%s/%d", dompath, libxl__vsnd_devtype.entry, + info->devid); + libxl_path = GCSPRINTF("%s/device/%s/%d", + libxl__xs_libxl_path(gc, domid), + libxl__vsnd_devtype.entry, info->devid); + + info->backend = xs_read(ctx->xsh, XBT_NULL, + GCSPRINTF("%s/backend", libxl_path), NULL); + + rc = libxl__backendpath_parse_domid(gc, info->backend, &info->backend_id); + if (rc) goto out; + + val = xs_read(ctx->xsh, XBT_NULL, GCSPRINTF("%s/state", devpath), NULL); + + info->state = val ? strtoul(val, NULL, 10) : -1; + + info->frontend = xs_read(ctx->xsh, XBT_NULL, + GCSPRINTF("%s/frontend", libxl_path), NULL); + + info->frontend_id = domid; + + rc = libxl__device_pcm_getinfo(gc, devpath, vsnd, info); + if (rc) goto out; + + rc = 0; + +out: + GC_FREE; + return rc; +} + +int libxl_devid_to_device_vsnd(libxl_ctx *ctx, uint32_t domid, + int devid, libxl_device_vsnd *vsnd) +{ + GC_INIT(ctx); + + libxl_device_vsnd *vsnds = NULL; + int n, i; + int rc; + + libxl_device_vsnd_init(vsnd); + + vsnds = libxl__device_list(gc, &libxl__vsnd_devtype, domid, &n); + + if (!vsnds) { rc = ERROR_NOTFOUND; goto out; } + + for (i = 0; i < n; ++i) { + if (devid == vsnds[i].devid) { + libxl_device_vsnd_copy(ctx, vsnd, &vsnds[i]); + rc = 0; + goto out; + } + } + + rc = ERROR_NOTFOUND; + +out: + + if (vsnds) + libxl__device_list_free(&libxl__vsnd_devtype, vsnds, n); + + GC_FREE; + return rc; +} + LIBXL_DEFINE_DEVICE_ADD(vsnd) static LIBXL_DEFINE_DEVICES_ADD(vsnd) LIBXL_DEFINE_DEVICE_REMOVE(vsnd) static LIBXL_DEFINE_UPDATE_DEVID(vsnd, "vsnd") +LIBXL_DEFINE_DEVICE_LIST(vsnd) DEFINE_DEVICE_TYPE_STRUCT(vsnd, .update_config = (device_update_config_fn_t) libxl__update_config_vsnd, -- 2.7.4 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx https://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |