mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
xl: add PV sound condif parser
Add config parser for virtual sound devices Signed-off-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com> Acked-by: Wei Liu <wei.liu2@citrix.com>
This commit is contained in:
1 parent
b24fb566eb
commit
8d89d52c5a
2 files changed
+247
No files matched your search
@@ -19,6 +19,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <xen/hvm/e820.h>
|
||||
#include <xen/hvm/params.h>
|
||||
#include <xen/io/sndif.h>
|
||||
|
||||
#include <libxl.h>
|
||||
#include <libxl_utils.h>
|
||||
@@ -851,6 +852,249 @@ out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int parse_vsnd_params(libxl_vsnd_params *params, char *token)
|
||||
{
|
||||
char *oparg;
|
||||
int i;
|
||||
|
||||
if (MATCH_OPTION(XENSND_FIELD_SAMPLE_RATES, token, oparg)) {
|
||||
libxl_string_list rates = NULL;
|
||||
|
||||
split_string_into_string_list(oparg, ";", &rates);
|
||||
|
||||
params->num_sample_rates = libxl_string_list_length(&rates);
|
||||
params->sample_rates = calloc(params->num_sample_rates,
|
||||
sizeof(*params->sample_rates));
|
||||
|
||||
for (i = 0; i < params->num_sample_rates; i++) {
|
||||
params->sample_rates[i] = strtoul(rates[i], NULL, 0);
|
||||
}
|
||||
|
||||
libxl_string_list_dispose(&rates);
|
||||
} else if (MATCH_OPTION(XENSND_FIELD_SAMPLE_FORMATS, token, oparg)) {
|
||||
libxl_string_list formats = NULL;
|
||||
|
||||
split_string_into_string_list(oparg, ";", &formats);
|
||||
|
||||
params->num_sample_formats = libxl_string_list_length(&formats);
|
||||
params->sample_formats = calloc(params->num_sample_formats,
|
||||
sizeof(*params->sample_formats));
|
||||
|
||||
for (i = 0; i < params->num_sample_formats; i++) {
|
||||
libxl_vsnd_pcm_format format;
|
||||
|
||||
if (libxl_vsnd_pcm_format_from_string(formats[i], &format)) {
|
||||
fprintf(stderr, "Invalid pcm format: %s\n", formats[i]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
params->sample_formats[i] = format;
|
||||
}
|
||||
|
||||
libxl_string_list_dispose(&formats);
|
||||
} else if (MATCH_OPTION(XENSND_FIELD_CHANNELS_MIN, token, oparg)) {
|
||||
params->channels_min = strtoul(oparg, NULL, 0);
|
||||
} else if (MATCH_OPTION(XENSND_FIELD_CHANNELS_MAX, token, oparg)) {
|
||||
params->channels_max = strtoul(oparg, NULL, 0);
|
||||
} else if (MATCH_OPTION(XENSND_FIELD_BUFFER_SIZE, token, oparg)) {
|
||||
params->buffer_size = strtoul(oparg, NULL, 0);
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_vsnd_pcm_stream(libxl_device_vsnd *vsnd, char *param)
|
||||
{
|
||||
if (vsnd->num_vsnd_pcms == 0) {
|
||||
fprintf(stderr, "No vsnd pcm device\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
libxl_vsnd_pcm *pcm = &vsnd->pcms[vsnd->num_vsnd_pcms - 1];
|
||||
|
||||
if (pcm->num_vsnd_streams == 0) {
|
||||
fprintf(stderr, "No vsnd stream\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
libxl_vsnd_stream *stream = &pcm->streams[pcm->num_vsnd_streams - 1];
|
||||
|
||||
if (parse_vsnd_params(&stream->params, param)) {
|
||||
char *oparg;
|
||||
|
||||
if (MATCH_OPTION(XENSND_FIELD_STREAM_UNIQUE_ID, param, oparg)) {
|
||||
stream->unique_id = strdup(oparg);
|
||||
} else if (MATCH_OPTION(XENSND_FIELD_TYPE, param, oparg)) {
|
||||
if (libxl_vsnd_stream_type_from_string(oparg, &stream->type)) {
|
||||
fprintf(stderr, "Invalid stream type: %s\n", oparg);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Invalid parameter: %s\n", param);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_vsnd_pcm_param(libxl_device_vsnd *vsnd, char *param)
|
||||
{
|
||||
if (vsnd->num_vsnd_pcms == 0) {
|
||||
fprintf(stderr, "No pcm device\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
libxl_vsnd_pcm *pcm = &vsnd->pcms[vsnd->num_vsnd_pcms - 1];
|
||||
|
||||
if (parse_vsnd_params(&pcm->params, param)) {
|
||||
char *oparg;
|
||||
|
||||
if (MATCH_OPTION(XENSND_FIELD_DEVICE_NAME, param, oparg)) {
|
||||
pcm->name = strdup(oparg);
|
||||
} else {
|
||||
fprintf(stderr, "Invalid parameter: %s\n", param);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_vsnd_card_param(libxl_device_vsnd *vsnd, char *param)
|
||||
{
|
||||
if (parse_vsnd_params(&vsnd->params, param)) {
|
||||
char *oparg;
|
||||
|
||||
if (MATCH_OPTION("backend", param, oparg)) {
|
||||
vsnd->backend_domname = strdup(oparg);
|
||||
} else if (MATCH_OPTION(XENSND_FIELD_VCARD_SHORT_NAME, param, oparg)) {
|
||||
vsnd->short_name = strdup(oparg);
|
||||
} else if (MATCH_OPTION(XENSND_FIELD_VCARD_LONG_NAME, param, oparg)) {
|
||||
vsnd->long_name = strdup(oparg);
|
||||
} else {
|
||||
fprintf(stderr, "Invalid parameter: %s\n", param);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_vsnd_create_item(libxl_device_vsnd *vsnd, const char *key)
|
||||
{
|
||||
if (strcasecmp(key, "card") == 0) {
|
||||
|
||||
} else if (strcasecmp(key, "pcm") == 0) {
|
||||
ARRAY_EXTEND_INIT_NODEVID(vsnd->pcms, vsnd->num_vsnd_pcms,
|
||||
libxl_vsnd_pcm_init);
|
||||
} else if (strcasecmp(key, "stream") == 0) {
|
||||
if (vsnd->num_vsnd_pcms == 0) {
|
||||
ARRAY_EXTEND_INIT_NODEVID(vsnd->pcms, vsnd->num_vsnd_pcms,
|
||||
libxl_vsnd_pcm_init);
|
||||
}
|
||||
|
||||
libxl_vsnd_pcm *pcm = &vsnd->pcms[vsnd->num_vsnd_pcms - 1];
|
||||
|
||||
ARRAY_EXTEND_INIT_NODEVID(pcm->streams, pcm->num_vsnd_streams,
|
||||
libxl_vsnd_stream_init);
|
||||
} else {
|
||||
fprintf(stderr, "Invalid key: %s\n", key);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parse_vsnd_item(libxl_device_vsnd *vsnd, const char *spec)
|
||||
{
|
||||
char *buf = strdup(spec);
|
||||
char *token = strtok(buf, ",");
|
||||
char *key = NULL;
|
||||
int ret;
|
||||
|
||||
while (token) {
|
||||
while (*token == ' ') token++;
|
||||
|
||||
if (!key) {
|
||||
key = token;
|
||||
ret = parse_vsnd_create_item(vsnd, key);
|
||||
if (ret) goto out;
|
||||
} else {
|
||||
if (strcasecmp(key, "card") == 0) {
|
||||
ret = parse_vsnd_card_param(vsnd, token);
|
||||
if (ret) goto out;
|
||||
} else if (strcasecmp(key, "pcm") == 0) {
|
||||
ret = parse_vsnd_pcm_param(vsnd, token);
|
||||
if (ret) goto out;
|
||||
} else if (strcasecmp(key, "stream") == 0) {
|
||||
ret = parse_vsnd_pcm_stream(vsnd, token);
|
||||
if (ret) goto out;
|
||||
}
|
||||
}
|
||||
token = strtok (NULL, ",");
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
free(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void parse_vsnd_card_config(const XLU_Config *config,
|
||||
XLU_ConfigValue *card_value,
|
||||
libxl_domain_config *d_config)
|
||||
{
|
||||
int ret;
|
||||
XLU_ConfigList *card_list;
|
||||
libxl_device_vsnd *vsnd;
|
||||
const char *card_item;
|
||||
int item = 0;
|
||||
|
||||
ret = xlu_cfg_value_get_list(config, card_value, &card_list, 0);
|
||||
|
||||
if (ret) {
|
||||
fprintf(stderr, "Failed to get vsnd card list: %s\n", strerror(ret));
|
||||
goto out;
|
||||
}
|
||||
|
||||
vsnd = ARRAY_EXTEND_INIT(d_config->vsnds,
|
||||
d_config->num_vsnds,
|
||||
libxl_device_vsnd_init);
|
||||
|
||||
while ((card_item = xlu_cfg_get_listitem(card_list, item++)) != NULL) {
|
||||
ret = parse_vsnd_item(vsnd, card_item);
|
||||
if (ret) goto out;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
|
||||
if (ret) exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static void parse_vsnd_config(const XLU_Config *config,
|
||||
libxl_domain_config *d_config)
|
||||
{
|
||||
XLU_ConfigList *vsnds;
|
||||
|
||||
if (!xlu_cfg_get_list(config, "vsnd", &vsnds, 0, 0)) {
|
||||
XLU_ConfigValue *card_value;
|
||||
|
||||
d_config->num_vsnds = 0;
|
||||
d_config->vsnds = NULL;
|
||||
|
||||
while ((card_value = xlu_cfg_get_listitem2(vsnds, d_config->num_vsnds))
|
||||
!= NULL) {
|
||||
parse_vsnd_card_config(config, card_value, d_config);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void parse_config_data(const char *config_source,
|
||||
const char *config_data,
|
||||
int config_len,
|
||||
@@ -1726,6 +1970,8 @@ void parse_config_data(const char *config_source,
|
||||
}
|
||||
}
|
||||
|
||||
parse_vsnd_config(config, d_config);
|
||||
|
||||
if (!xlu_cfg_get_list (config, "channel", &channels, 0, 0)) {
|
||||
d_config->num_channels = 0;
|
||||
d_config->channels = NULL;
|
||||
|
||||
@@ -34,6 +34,7 @@ int parse_usbdev_config(libxl_device_usbdev *usbdev, char *token);
|
||||
int parse_cpurange(const char *cpu, libxl_bitmap *cpumap);
|
||||
int parse_nic_config(libxl_device_nic *nic, XLU_Config **config, char *token);
|
||||
int parse_vdispl_config(libxl_device_vdispl *vdispl, char *token);
|
||||
int parse_vsnd_item(libxl_device_vsnd *vsnd, const char *spec);
|
||||
|
||||
int match_option_size(const char *prefix, size_t len,
|
||||
char *arg, char **argopt);
|
||||
|
||||