@@ -138,7 +138,7 @@ LIBXL_OBJS = flexarray.o libxl.o libxl_create.o libxl_dm.o libxl_pci.o \
libxl_dom_suspend.o libxl_dom_save.o libxl_usb.o \
libxl_vtpm.o libxl_nic.o libxl_disk.o libxl_console.o \
libxl_cpupool.o libxl_mem.o libxl_sched.o libxl_tmem.o \
- libxl_9pfs.o libxl_domain.o libxl_vdispl.o \
+ libxl_9pfs.o libxl_domain.o libxl_vdispl.o libxl_vsnd.o \
$(LIBXL_OBJS-y)
LIBXL_OBJS += libxl_genid.o
LIBXL_OBJS += _libxl_types.o libxl_flask.o _libxl_types_internal.o
@@ -1913,6 +1913,20 @@ int libxl_device_vdispl_getinfo(libxl_ctx *ctx, uint32_t domid,
libxl_vdisplinfo *vdisplinfo)
LIBXL_EXTERNAL_CALLERS_ONLY;
+/* Virtual sounds */
+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;
+
/* Keyboard */
int libxl_device_vkb_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vkb *vkb,
const libxl_asyncop_how *ao_how)
@@ -1449,6 +1449,7 @@ const struct libxl_device_type *device_type_tbl[] = {
&libxl__pcidev_devtype,
&libxl__dtdev_devtype,
&libxl__vdispl_devtype,
+ &libxl__vsnd_devtype,
NULL
};
@@ -3575,6 +3575,7 @@ extern const struct libxl_device_type libxl__usbdev_devtype;
extern const struct libxl_device_type libxl__pcidev_devtype;
extern const struct libxl_device_type libxl__vdispl_devtype;
extern const struct libxl_device_type libxl__p9_devtype;
+extern const struct libxl_device_type libxl__vsnd_devtype;
extern const struct libxl_device_type *device_type_tbl[];
@@ -793,6 +793,69 @@ libxl_device_vdispl = Struct("device_vdispl", [
("connectors", Array(libxl_connector_param, "num_connectors"))
])
+libxl_vsnd_pcm_format = Enumeration("vsnd_pcm_format", [
+ (1, "S8"),
+ (2, "U8"),
+ (3, "S16_LE"),
+ (4, "S16_BE"),
+ (5, "U16_LE"),
+ (6, "U16_BE"),
+ (7, "S24_LE"),
+ (8, "S24_BE"),
+ (9, "U24_LE"),
+ (10, "U24_BE"),
+ (11, "S32_LE"),
+ (12, "S32_BE"),
+ (13, "U32_LE"),
+ (14, "U32_BE"),
+ (15, "F32_LE"),
+ (16, "F32_BE"),
+ (17, "F64_LE"),
+ (18, "F64_BE"),
+ (19, "IEC958_SUBFRAME_LE"),
+ (20, "IEC958_SUBFRAME_BE"),
+ (21, "MU_LAW"),
+ (22, "A_LAW"),
+ (23, "IMA_ADPCM"),
+ (24, "MPEG"),
+ (25, "GSM")
+ ])
+
+libxl_vsnd_params = Struct("vsnd_params", [
+ ("sample_rates", Array(uint32, "num_sample_rates")),
+ ("sample_formats", Array(libxl_vsnd_pcm_format, "num_sample_formats")),
+ ("channels_min", uint32),
+ ("channels_max", uint32),
+ ("buffer_size", uint32)
+ ])
+
+libxl_vsnd_stream_type = Enumeration("vsnd_stream_type", [
+ (1, "P"),
+ (2, "C")
+ ])
+
+libxl_vsnd_stream = Struct("vsnd_stream", [
+ ("id", string),
+ ("type", libxl_vsnd_stream_type),
+ ("params", libxl_vsnd_params)
+ ])
+
+libxl_vsnd_pcm = Struct("vsnd_pcm", [
+ ("name", string),
+ ("params", libxl_vsnd_params),
+ ("streams", Array(libxl_vsnd_stream, "num_vsnd_streams"))
+ ])
+
+libxl_device_vsnd = Struct("device_vsnd", [
+ ("backend_domid", libxl_domid),
+ ("backend_domname", string),
+ ("devid", libxl_devid),
+ ("short_name", string),
+ ("long_name", string),
+ ("params", libxl_vsnd_params),
+ ("pcms", Array(libxl_vsnd_pcm, "num_vsnd_pcms"))
+ ])
+
libxl_domain_config = Struct("domain_config", [
("c_info", libxl_domain_create_info),
("b_info", libxl_domain_build_info),
@@ -807,6 +870,7 @@ libxl_domain_config = Struct("domain_config", [
("vtpms", Array(libxl_device_vtpm, "num_vtpms")),
("p9s", Array(libxl_device_p9, "num_p9s")),
("vdispls", Array(libxl_device_vdispl, "num_vdispls")),
+ ("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")),
@@ -27,6 +27,7 @@ libxl__device_kind = Enumeration("device_kind", [
(10, "QUSB"),
(11, "9PFS"),
(12, "VDISPL"),
+ (13, "VSND")
])
libxl__console_backend = Enumeration("console_backend", [
new file mode 100644
@@ -0,0 +1,330 @@
+/*
+ * Copyright (C) 2016 EPAM Systems Inc.
+ *
+ * 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_internal.h"
+#include <xen/io/sndif.h>
+
+static int libxl__device_vsnd_setdefault(libxl__gc *gc, uint32_t domid,
+ libxl_device_vsnd *vsnd,
+ bool hotplug)
+{
+ return libxl__resolve_domid(gc, vsnd->backend_domname,
+ &vsnd->backend_domid);
+}
+
+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__vsnd_from_xenstore(libxl__gc *gc, const char *libxl_path,
+ libxl_devid devid,
+ libxl_device_vsnd *vsnd)
+{
+ const char *be_path;
+ int rc;
+
+ vsnd->devid = devid;
+ rc = libxl__xs_read_mandatory(gc, XBT_NULL,
+ GCSPRINTF("%s/backend", libxl_path),
+ &be_path);
+ if (rc) goto out;
+
+ rc = libxl__backendpath_parse_domid(gc, be_path, &vsnd->backend_domid);
+ if (rc) goto out;
+
+ rc = 0;
+
+out:
+
+ return rc;
+}
+
+static void libxl__update_config_vsnd(libxl__gc *gc,
+ libxl_device_vsnd *dst,
+ libxl_device_vsnd *src)
+{
+ dst->devid = src->devid;
+}
+
+static int libxl_device_vsnd_compare(libxl_device_vsnd *d1,
+ libxl_device_vsnd *d2)
+{
+ return COMPARE_DEVID(d1, d2);
+}
+
+static void libxl__device_vsnd_add(libxl__egc *egc, uint32_t domid,
+ libxl_device_vsnd *vsnd,
+ libxl__ao_device *aodev)
+{
+ libxl__device_add_async(egc, domid, &libxl__vsnd_devtype, vsnd, aodev);
+}
+
+static unsigned int libxl__rates_to_str_vsnd(char *str, uint32_t *sample_rates,
+ int num_sample_rates)
+{
+ unsigned int len;
+ int i;
+
+ len = 0;
+
+ if (num_sample_rates == 0) goto out;
+
+ for (i = 0; i < num_sample_rates - 1; i++) {
+ if (str) {
+ len += sprintf(&str[len], "%u,", sample_rates[i]);
+ } else {
+ len += snprintf(NULL, 0, "%u,", sample_rates[i]);
+ }
+ }
+
+ if (str) {
+ len += sprintf(&str[len], "%u", sample_rates[i]);
+ } else {
+ len += snprintf(NULL, 0, "%u", sample_rates[i]);
+ }
+
+out:
+
+ return len;
+}
+
+static unsigned int libxl__formats_to_str_vsnd(char *str,
+ libxl_vsnd_pcm_format *sample_formats,
+ int num_sample_formats)
+{
+ unsigned int len;
+ int i;
+
+ len = 0;
+
+ if (num_sample_formats == 0) goto out;
+
+ for (i = 0; i < num_sample_formats - 1; i++) {
+ if (str) {
+ len += sprintf(&str[len], "%s,",
+ libxl_vsnd_pcm_format_to_string(sample_formats[i]));
+ } else {
+ len += snprintf(NULL, 0, "%s,",
+ libxl_vsnd_pcm_format_to_string(sample_formats[i]));
+ }
+ }
+
+ if (str) {
+ len += sprintf(&str[len], "%s",
+ libxl_vsnd_pcm_format_to_string(sample_formats[i]));
+ } else {
+ len += snprintf(NULL, 0, "%s",
+ libxl_vsnd_pcm_format_to_string(sample_formats[i]));
+ }
+
+out:
+
+ return len;
+}
+
+static int libxl__set_params_vsnd(libxl__gc *gc, char *path,
+ libxl_vsnd_params *params, flexarray_t *front)
+{
+ char *buffer;
+ int len;
+ int rc;
+
+ if (params->sample_rates) {
+ /* calculate required string size */
+ len = libxl__rates_to_str_vsnd(NULL, params->sample_rates,
+ params->num_sample_rates);
+
+ if (len) {
+ buffer = libxl__malloc(gc, len + 1);
+
+ libxl__rates_to_str_vsnd(buffer, params->sample_rates,
+ params->num_sample_rates);
+ rc = flexarray_append_pair(front,
+ GCSPRINTF("%s"XENSND_FIELD_SAMPLE_RATES,
+ path), buffer);
+ if (rc) goto out;
+ }
+ }
+
+ if (params->sample_formats) {
+ /* calculate required string size */
+ len = libxl__formats_to_str_vsnd(NULL, params->sample_formats,
+ params->num_sample_formats);
+
+ if (len) {
+ buffer = libxl__malloc(gc, len + 1);
+
+ libxl__formats_to_str_vsnd(buffer, params->sample_formats,
+ params->num_sample_formats);
+ rc = flexarray_append_pair(front,
+ GCSPRINTF("%s"XENSND_FIELD_SAMPLE_FORMATS,
+ path), buffer);
+ if (rc) goto out;
+ }
+ }
+
+ if (params->channels_min) {
+ rc = flexarray_append_pair(front,
+ GCSPRINTF("%s"XENSND_FIELD_CHANNELS_MIN, path),
+ GCSPRINTF("%u", params->channels_min));
+ if (rc) goto out;
+ }
+
+ if (params->channels_max) {
+ rc = flexarray_append_pair(front,
+ GCSPRINTF("%s"XENSND_FIELD_CHANNELS_MAX, path),
+ GCSPRINTF("%u", params->channels_max));
+ if (rc) goto out;
+ }
+
+ if (params->buffer_size) {
+ rc = flexarray_append_pair(front,
+ GCSPRINTF("%s"XENSND_FIELD_BUFFER_SIZE, path),
+ GCSPRINTF("%u", params->buffer_size));
+ if (rc) goto out;
+ }
+
+ rc = 0;
+
+out:
+
+ return rc;
+}
+
+static int libxl__set_streams_vsnd(libxl__gc *gc, char *path,
+ libxl_vsnd_stream *streams,
+ int num_streams, flexarray_t *front)
+{
+ int i;
+ int rc;
+
+ for (i = 0; i < num_streams; i++) {
+ rc = flexarray_append_pair(front,
+ GCSPRINTF("%s%d/"XENSND_FIELD_STREAM_UNIQUE_ID, path, i),
+ streams[i].id);
+ if (rc) goto out;
+
+ const char *type = libxl_vsnd_stream_type_to_string(streams[i].type);
+
+ if (type) {
+ rc = flexarray_append_pair(front,
+ GCSPRINTF("%s%d/"XENSND_FIELD_TYPE, path, i),
+ (char *)type);
+ if (rc) goto out;
+ }
+
+ rc = libxl__set_params_vsnd(gc, GCSPRINTF("%s%d/", path, i),
+ &streams[i].params, front);
+ if (rc) goto out;
+ }
+
+ rc = 0;
+
+out:
+
+ return rc;
+}
+
+static int libxl__set_pcms_vsnd(libxl__gc *gc, libxl_vsnd_pcm *pcms,
+ int num_pcms, flexarray_t *front)
+{
+ int i;
+ int rc;
+
+ for (i = 0; i < num_pcms; i++) {
+ if (pcms[i].name) {
+ rc = flexarray_append_pair(front,
+ GCSPRINTF("%d/"XENSND_FIELD_DEVICE_NAME, i),
+ pcms[i].name);
+ if (rc) goto out;
+ }
+
+ char *path = GCSPRINTF("%d/", i);
+
+ rc = libxl__set_params_vsnd(gc, path, &pcms[i].params, front);
+ if (rc) goto out;
+
+ rc = libxl__set_streams_vsnd(gc, path, pcms[i].streams,
+ pcms[i].num_vsnd_streams, front);
+ if (rc) goto out;
+ }
+
+ rc = 0;
+
+out:
+
+ return rc;
+}
+
+static int libxl__set_xenstore_vsnd(libxl__gc *gc, uint32_t domid,
+ libxl_device_vsnd *vsnd,
+ flexarray_t *back, flexarray_t *front,
+ flexarray_t *ro_front)
+{
+ int rc;
+
+ if (vsnd->long_name) {
+ rc = flexarray_append_pair(front, XENSND_FIELD_VCARD_LONG_NAME,
+ vsnd->long_name);
+ if (rc) goto out;
+ }
+
+ if (vsnd->short_name) {
+ rc = flexarray_append_pair(front, XENSND_FIELD_VCARD_SHORT_NAME,
+ vsnd->short_name);
+ if (rc) goto out;
+ }
+
+ rc = libxl__set_params_vsnd(gc, "", &vsnd->params, front);
+ if (rc) goto out;
+
+ rc = libxl__set_pcms_vsnd(gc, vsnd->pcms, vsnd->num_vsnd_pcms, front);
+ if (rc) goto out;
+
+ rc = 0;
+
+out:
+
+ 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")
+
+DEFINE_DEVICE_TYPE_STRUCT(vsnd,
+ .update_config = (device_update_config_fn_t) libxl__update_config_vsnd,
+ .from_xenstore = (device_from_xenstore_fn_t) libxl__vsnd_from_xenstore,
+ .set_xenstore_config = (device_set_xenstore_config_fn_t)
+ libxl__set_xenstore_vsnd
+);
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */