struct list_head *base,
snd_config_t *cfg);
+/*
+ * compose configuration file
+ */
+static void configuration_filename2(char *fn, size_t fn_len, int format,
+ const char *dir, const char *file,
+ const char *suffix)
+{
+ snprintf(fn, fn_len, "%s/ucm%s/%s/%s%s",
+ snd_config_topdir(), format >= 2 ? "2" : "",
+ dir, file, suffix);
+ fn[fn_len-1] = '\0';
+}
+
+static void configuration_filename(snd_use_case_mgr_t *uc_mgr,
+ char *fn, size_t fn_len,
+ const char *file, const char *suffix)
+{
+ const char *env, *dir;
+
+ if (uc_mgr->conf_format > 0) {
+ /* known format */
+ env = getenv(uc_mgr->conf_format >= 2 ? ALSA_CONFIG_UCM2_VAR :
+ ALSA_CONFIG_UCM_VAR);
+ } else {
+ /* auto-detect */
+ env = getenv(ALSA_CONFIG_UCM2_VAR);
+ if (env == NULL) {
+ env = getenv(ALSA_CONFIG_UCM_VAR);
+ } else {
+ uc_mgr->conf_format = 2;
+ }
+ }
+ if (env) {
+ snprintf(fn, fn_len, "%s/%s/%s%s",
+ env, uc_mgr->conf_file_name, file, suffix);
+ fn[fn_len-1] = '\0';
+ return;
+ }
+
+ dir = uc_mgr->conf_file_name;
+ if (uc_mgr->conf_format > 0) {
+__format:
+ configuration_filename2(fn, fn_len, uc_mgr->conf_format,
+ dir, file, suffix);
+ return;
+ }
+
+ configuration_filename2(fn, fn_len, 2, dir, file, suffix);
+ if (access(fn, R_OK) == 0)
+ return;
+
+ configuration_filename2(fn, fn_len, 0, dir, file, suffix);
+ if (access(fn, R_OK)) {
+ /* make sure that the error message refers to the new path */
+ uc_mgr->conf_format = 2;
+ goto __format;
+ }
+}
+
/*
* Parse string
*/
struct use_case_verb *verb;
snd_config_t *cfg;
char filename[MAX_FILE];
- char *env = getenv(ALSA_CONFIG_UCM_VAR);
int err;
/* allocate verb */
}
/* open Verb file for reading */
- if (env)
- snprintf(filename, sizeof(filename), "%s/%s/%s",
- env, uc_mgr->conf_file_name, file);
- else
- snprintf(filename, sizeof(filename), "%s/ucm/%s/%s",
- snd_config_topdir(), uc_mgr->conf_file_name, file);
- filename[sizeof(filename)-1] = '\0';
-
- err = uc_mgr_config_load(filename, &cfg);
+ configuration_filename(uc_mgr, filename, sizeof(filename), file, "");
+ err = uc_mgr_config_load(uc_mgr->conf_format, filename, &cfg);
if (err < 0) {
uc_error("error: failed to open verb file %s : %d",
filename, -errno);
snd_config_iterator_t i, next;
snd_config_t *n;
const char *id;
+ long l;
int err;
if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) {
return -EINVAL;
}
+ if (uc_mgr->conf_format >= 2) {
+ err = snd_config_search(cfg, "Syntax", &n);
+ if (err < 0) {
+ uc_error("Syntax field not found in %s", uc_mgr->conf_file_name);
+ return -EINVAL;
+ }
+ err = snd_config_get_integer(n, &l);
+ if (err < 0) {
+ uc_error("Syntax field is invalid in %s", uc_mgr->conf_file_name);
+ return err;
+ }
+ if (l < 2 || l > SYNTAX_VERSION_MAX) {
+ uc_error("Incompatible syntax %d in %s", l, uc_mgr->conf_file_name);
+ return -EINVAL;
+ }
+ }
+
/* parse master config sections */
snd_config_for_each(i, next, cfg) {
if (snd_config_get_id(n, &id) < 0)
continue;
+ if (uc_mgr->conf_format >= 2 && strcmp(id, "Syntax") == 0)
+ continue;
+
if (strcmp(id, "Comment") == 0) {
err = parse_string(n, &uc_mgr->comment);
if (err < 0) {
return -1;
}
-static int load_master_config(const char *card_name, snd_config_t **cfg)
+static int load_master_config(snd_use_case_mgr_t *uc_mgr,
+ const char *card_name, snd_config_t **cfg)
{
char filename[MAX_FILE];
- char *env = getenv(ALSA_CONFIG_UCM_VAR);
int err;
if (strnlen(card_name, MAX_CARD_LONG_NAME) == MAX_CARD_LONG_NAME) {
return -EINVAL;
}
- if (env)
- snprintf(filename, sizeof(filename)-1,
- "%s/%s/%s.conf", env, card_name, card_name);
- else
- snprintf(filename, sizeof(filename)-1,
- "%s/ucm/%s/%s.conf", snd_config_topdir(),
- card_name, card_name);
- filename[MAX_FILE-1] = '\0';
-
- err = uc_mgr_config_load(filename, cfg);
+ configuration_filename(uc_mgr, filename, sizeof(filename),
+ card_name, ".conf");
+ err = uc_mgr_config_load(uc_mgr->conf_format, filename, cfg);
if (err < 0) {
uc_error("error: could not parse configuration for card %s",
card_name);
err = get_card_long_name(uc_mgr);
if (err == 0) /* load file that maches the card long name */
- err = load_master_config(uc_mgr->card_long_name, &cfg);
+ err = load_master_config(uc_mgr, uc_mgr->card_long_name, &cfg);
if (err == 0) {
/* got device-specific file that matches the card long name */
* either short name or long name (users may open a card by
* its name or long name).
*/
- err = load_master_config(uc_mgr->card_name, &cfg);
+ err = load_master_config(uc_mgr, uc_mgr->card_name, &cfg);
if (err < 0)
return err;
strncpy(uc_mgr->conf_file_name, uc_mgr->card_name, MAX_CARD_LONG_NAME);
*
* Cards are defined by machines. Each card/machine installs its UCM
* configuration files in a subdirectory with the same name as the sound
- * card under /usr/share/alsa/ucm. This function will scan all the card
+ * card under /usr/share/alsa/ucm2. This function will scan all the card
* directories and skip the component directories defined in the array
* component_dir.
*/
int uc_mgr_scan_master_configs(const char **_list[])
{
char filename[MAX_FILE], dfl[MAX_FILE];
- char *env = getenv(ALSA_CONFIG_UCM_VAR);
- const char **list;
+ char *env = getenv(ALSA_CONFIG_UCM2_VAR);
+ const char **list, *d_name;
snd_config_t *cfg, *c;
int i, j, cnt, err;
+ long l;
ssize_t ss;
struct dirent **namelist;
if (env)
snprintf(filename, sizeof(filename)-1, "%s", env);
else
- snprintf(filename, sizeof(filename)-1, "%s/ucm",
+ snprintf(filename, sizeof(filename)-1, "%s/ucm2",
snd_config_topdir());
- filename[MAX_FILE-1] = '\0';
+ filename[sizeof(filename)-1] = '\0';
#if defined(_GNU_SOURCE) && !defined(__NetBSD__) && !defined(__FreeBSD__) && !defined(__sun) && !defined(ANDROID)
#define SORTFUNC versionsort
for (i = j = 0; i < cnt; i++) {
+ d_name = namelist[i]->d_name;
+
/* Skip the directories for component devices */
- if (is_component_directory(namelist[i]->d_name))
+ if (is_component_directory(d_name))
continue;
- err = load_master_config(namelist[i]->d_name, &cfg);
+
+ configuration_filename2(filename, sizeof(filename), 2,
+ d_name, d_name, ".conf");
+ err = uc_mgr_config_load(2, filename, &cfg);
if (err < 0)
goto __err;
+ err = snd_config_search(cfg, "Syntax", &c);
+ if (err < 0) {
+ uc_error("Syntax field not found in %s", d_name);
+ continue;
+ }
+ err = snd_config_get_integer(c, &l);
+ if (err < 0) {
+ uc_error("Syntax field is invalid in %s", d_name);
+ goto __err;
+ }
+ if (l < 2 || l > SYNTAX_VERSION_MAX) {
+ uc_error("Incompatible syntax %d in %s", l, d_name);
+ goto __err;
+ }
err = snd_config_search(cfg, "Comment", &c);
if (err >= 0) {
err = parse_string(c, (char **)&list[j+1]);
}
}
snd_config_delete(cfg);
- list[j] = strdup(namelist[i]->d_name);
+ list[j] = strdup(d_name);
if (list[j] == NULL) {
err = -ENOMEM;
goto __err;