xref: /third_party/alsa-lib/src/ucm/parser.c (revision d5ac70f0)
1/*
2 *  This library is free software; you can redistribute it and/or
3 *  modify it under the terms of the GNU Lesser General Public
4 *  License as published by the Free Software Foundation; either
5 *  version 2 of the License, or (at your option) any later version.
6 *
7 *  This library is distributed in the hope that it will be useful,
8 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
9 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
10 *  Lesser General Public License for more details.
11 *
12 *  You should have received a copy of the GNU Lesser General Public
13 *  License along with this library; if not, write to the Free Software
14 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
15 *
16 *  Support for the verb/device/modifier core logic and API,
17 *  command line tool and file parser was kindly sponsored by
18 *  Texas Instruments Inc.
19 *  Support for multiple active modifiers and devices,
20 *  transition sequences, multiple client access and user defined use
21 *  cases was kindly sponsored by Wolfson Microelectronics PLC.
22 *
23 *  Copyright (C) 2008-2010 SlimLogic Ltd
24 *  Copyright (C) 2010 Wolfson Microelectronics PLC
25 *  Copyright (C) 2010 Texas Instruments Inc.
26 *  Copyright (C) 2010 Red Hat Inc.
27 *  Authors: Liam Girdwood <lrg@slimlogic.co.uk>
28 *	         Stefan Schmidt <stefan@slimlogic.co.uk>
29 *	         Justin Xu <justinx@slimlogic.co.uk>
30 *               Jaroslav Kysela <perex@perex.cz>
31 */
32
33#include "ucm_local.h"
34#include <sys/stat.h>
35#include <stdbool.h>
36#include <dirent.h>
37#include <limits.h>
38
39static int filename_filter(const struct dirent64 *dirent);
40
41static int parse_sequence(snd_use_case_mgr_t *uc_mgr,
42			  struct list_head *base,
43			  snd_config_t *cfg);
44
45/*
46 * compose the absolute ucm filename
47 */
48static void ucm_filename(char *fn, size_t fn_len, long version,
49			  const char *dir, const char *file)
50{
51	const char *env = getenv(version > 1 ? ALSA_CONFIG_UCM2_VAR : ALSA_CONFIG_UCM_VAR);
52
53	if (file[0] == '/')
54		file++;
55	if (env == NULL)
56		snprintf(fn, fn_len, "%s/%s/%s%s%s",
57			 snd_config_topdir(), version > 1 ? "ucm2" : "ucm",
58			 dir ?: "", dir ? "/" : "", file);
59	else
60		snprintf(fn, fn_len, "%s/%s%s%s",
61			 env, dir ?: "", dir ? "/" : "", file);
62}
63
64/*
65 *
66 */
67int uc_mgr_config_load_file(snd_use_case_mgr_t *uc_mgr,
68			     const char *file, snd_config_t **cfg)
69{
70	char filename[PATH_MAX];
71	int err;
72
73	ucm_filename(filename, sizeof(filename), uc_mgr->conf_format,
74		     file[0] == '/' ? NULL : uc_mgr->conf_dir_name,
75		     file);
76	err = uc_mgr_config_load(uc_mgr->conf_format, filename, cfg);
77	if (err < 0) {
78		uc_error("error: failed to open file %s: %d", filename, err);
79		return err;
80	}
81	return 0;
82}
83
84/*
85 * Replace mallocated string
86 */
87static char *replace_string(char **dst, const char *value)
88{
89	free(*dst);
90	*dst = value ? strdup(value) : NULL;
91	return *dst;
92}
93
94/*
95 * Parse string
96 */
97static int parse_string(snd_config_t *n, char **res)
98{
99	int err;
100
101	err = snd_config_get_string(n, (const char **)res);
102	if (err < 0)
103		return err;
104	*res = strdup(*res);
105	if (*res == NULL)
106		return -ENOMEM;
107	return 0;
108}
109
110/*
111 * Parse string and substitute
112 */
113static int parse_string_substitute(snd_use_case_mgr_t *uc_mgr,
114			    snd_config_t *n, char **res)
115{
116	const char *str;
117	char *s;
118	int err;
119
120	err = snd_config_get_string(n, &str);
121	if (err < 0)
122		return err;
123	err = uc_mgr_get_substituted_value(uc_mgr, &s, str);
124	if (err >= 0)
125		*res = s;
126	return err;
127}
128
129/*
130 * Parse string and substitute
131 */
132static int parse_string_substitute3(snd_use_case_mgr_t *uc_mgr,
133			     snd_config_t *n, char **res)
134{
135	if (uc_mgr->conf_format < 3)
136		return parse_string(n, res);
137	return parse_string_substitute(uc_mgr, n, res);
138}
139
140/*
141 * Parse integer with substitution
142 */
143static int parse_integer_substitute(snd_use_case_mgr_t *uc_mgr,
144			     snd_config_t *n, long *res)
145{
146	char *s1, *s2;
147	int err;
148
149	err = snd_config_get_ascii(n, &s1);
150	if (err < 0)
151		return err;
152	err = uc_mgr_get_substituted_value(uc_mgr, &s2, s1);
153	if (err >= 0)
154		err = safe_strtol(s2, res);
155	free(s2);
156	free(s1);
157	return err;
158}
159
160/*
161 * Parse integer with substitution
162 */
163static int parse_integer_substitute3(snd_use_case_mgr_t *uc_mgr,
164			      snd_config_t *n, long *res)
165{
166	char *s1, *s2;
167	int err;
168
169	err = snd_config_get_ascii(n, &s1);
170	if (err < 0)
171		return err;
172	if (uc_mgr->conf_format < 3)
173		s2 = s1;
174	else
175		err = uc_mgr_get_substituted_value(uc_mgr, &s2, s1);
176	if (err >= 0)
177		err = safe_strtol(s2, res);
178	if (s1 != s2)
179		free(s2);
180	free(s1);
181	return err;
182}
183
184/*
185 * Parse safe ID
186 */
187static int parse_is_name_safe(const char *name)
188{
189	if (strchr(name, '.')) {
190		uc_error("char '.' not allowed in '%s'", name);
191		return 0;
192	}
193	return 1;
194}
195
196static int get_string3(snd_use_case_mgr_t *uc_mgr, const char *s1, char **s)
197{
198	if (uc_mgr->conf_format < 3) {
199		*s = strdup(s1);
200		if (*s == NULL)
201			return -ENOMEM;
202		return 0;
203	}
204	return uc_mgr_get_substituted_value(uc_mgr, s, s1);
205}
206
207static int parse_get_safe_name(snd_use_case_mgr_t *uc_mgr, snd_config_t *n,
208			const char *alt, char **name)
209{
210	const char *id;
211	int err;
212
213	if (alt) {
214		id = alt;
215	} else {
216		err = snd_config_get_id(n, &id);
217		if (err < 0)
218			return err;
219	}
220	err = get_string3(uc_mgr, id, name);
221	if (err < 0)
222		return err;
223	if (!parse_is_name_safe(*name)) {
224		free(*name);
225		return -EINVAL;
226	}
227	return 0;
228}
229
230/*
231 * Handle 'Error' configuration node.
232 */
233static int error_node(snd_use_case_mgr_t *uc_mgr, snd_config_t *cfg)
234{
235	int err;
236	char *s;
237
238	err = parse_string_substitute3(uc_mgr, cfg, &s);
239	if (err < 0) {
240		uc_error("error: failed to get Error string");
241		return err;
242	}
243	if (!uc_mgr->suppress_nodev_errors)
244		uc_error("%s", s);
245	free(s);
246	return -ENXIO;
247}
248
249/*
250 *
251 */
252static int parse_syntax_field(snd_use_case_mgr_t *uc_mgr,
253			      snd_config_t *cfg, const char *filename)
254{
255	snd_config_t *n;
256	long l;
257	int err;
258
259	err = snd_config_search(cfg, "Syntax", &n);
260	if (err < 0) {
261		uc_error("Syntax field not found in %s", filename);
262		return -EINVAL;
263	}
264	err = snd_config_get_integer(n, &l);
265	if (err < 0) {
266		uc_error("Syntax field is invalid in %s", filename);
267		return err;
268	}
269	if (l < 2 || l > SYNTAX_VERSION_MAX) {
270		uc_error("Incompatible syntax %ld in %s", l, filename);
271		return -EINVAL;
272	}
273	/* delete this field to optimize strcmp() call in the parsing loop */
274	snd_config_delete(n);
275	uc_mgr->conf_format = l;
276	return l;
277}
278
279/*
280 * Evaluate variable regex definitions (in-place delete)
281 */
282static int evaluate_regex(snd_use_case_mgr_t *uc_mgr,
283			  snd_config_t *cfg)
284{
285	snd_config_iterator_t i, next;
286	snd_config_t *d, *n;
287	const char *id;
288	int err;
289
290	err = snd_config_search(cfg, "DefineRegex", &d);
291	if (err == -ENOENT)
292		return 1;
293	if (err < 0)
294		return err;
295
296	if (snd_config_get_type(d) != SND_CONFIG_TYPE_COMPOUND) {
297		uc_error("compound type expected for DefineRegex");
298		return -EINVAL;
299	}
300
301	if (uc_mgr->conf_format < 3) {
302		uc_error("DefineRegex is supported in v3+ syntax");
303		return -EINVAL;
304	}
305
306	snd_config_for_each(i, next, d) {
307		n = snd_config_iterator_entry(i);
308		err = snd_config_get_id(n, &id);
309		if (err < 0)
310			return err;
311		if (id[0] == '@') {
312			uc_error("error: value names starting with '@' are reserved for application variables");
313			return -EINVAL;
314		}
315		err = uc_mgr_define_regex(uc_mgr, id, n);
316		if (err < 0)
317			return err;
318	}
319
320	snd_config_delete(d);
321	return 0;
322}
323
324/*
325 * Evaluate variable definitions (in-place delete)
326 */
327static int evaluate_define(snd_use_case_mgr_t *uc_mgr,
328			   snd_config_t *cfg)
329{
330	snd_config_iterator_t i, next;
331	snd_config_t *d, *n;
332	const char *id;
333	char *var, *s;
334	int err;
335
336	err = snd_config_search(cfg, "Define", &d);
337	if (err == -ENOENT)
338		return evaluate_regex(uc_mgr, cfg);
339	if (err < 0)
340		return err;
341
342	if (snd_config_get_type(d) != SND_CONFIG_TYPE_COMPOUND) {
343		uc_error("compound type expected for Define");
344		return -EINVAL;
345	}
346
347	if (uc_mgr->conf_format < 3) {
348		uc_error("Define is supported in v3+ syntax");
349		return -EINVAL;
350	}
351
352	snd_config_for_each(i, next, d) {
353		n = snd_config_iterator_entry(i);
354		err = snd_config_get_id(n, &id);
355		if (err < 0)
356			return err;
357		err = snd_config_get_ascii(n, &var);
358		if (err < 0)
359			return err;
360		err = uc_mgr_get_substituted_value(uc_mgr, &s, var);
361		free(var);
362		if (err < 0)
363			return err;
364		if (id[0] == '@') {
365			free(s);
366			uc_error("error: value names starting with '@' are reserved for application variables");
367			return -EINVAL;
368		}
369		err = uc_mgr_set_variable(uc_mgr, id, s);
370		free(s);
371		if (err < 0)
372			return err;
373	}
374
375	snd_config_delete(d);
376
377	return evaluate_regex(uc_mgr, cfg);
378}
379
380/*
381 * Evaluate macro definitions (in-place delete)
382 */
383static int evaluate_define_macro(snd_use_case_mgr_t *uc_mgr,
384				 snd_config_t *cfg)
385{
386	snd_config_t *d;
387	int err;
388
389	err = snd_config_search(cfg, "DefineMacro", &d);
390	if (err == -ENOENT)
391		return 1;
392	if (err < 0)
393		return err;
394
395	if (snd_config_get_type(d) != SND_CONFIG_TYPE_COMPOUND) {
396		uc_error("compound type expected for DefineMacro");
397		return -EINVAL;
398	}
399
400	if (uc_mgr->conf_format < 6) {
401		uc_error("DefineMacro is supported in v6+ syntax");
402		return -EINVAL;
403	}
404
405	err = snd_config_merge(uc_mgr->macros, d, 0);
406	if (err < 0)
407		return err;
408	return 0;
409}
410
411static int evaluate_macro1(snd_use_case_mgr_t *uc_mgr,
412			   snd_config_t *dst,
413			   snd_config_t *args)
414{
415	snd_config_iterator_t i, next;
416	snd_config_t *m, *mc, *a, *n;
417	const char *mid, *id;
418	char name[128], *var;
419	const char *s;
420	int err;
421
422	err = snd_config_get_id(args, &mid);
423	if (err < 0)
424		return err;
425	err = snd_config_search(uc_mgr->macros, mid, &m);
426	if (err < 0) {
427		uc_error("Macro '%s' is not defined", mid);
428		return err;
429	}
430
431	a = args;
432	if (snd_config_get_type(args) == SND_CONFIG_TYPE_STRING) {
433		err = snd_config_get_string(args, &s);
434		if (err < 0)
435			return err;
436		err = snd_config_load_string(&a, s, 0);
437		if (err < 0)
438			return err;
439	} else if (snd_config_get_type(args) != SND_CONFIG_TYPE_COMPOUND) {
440		return -EINVAL;
441	}
442
443	/* set arguments */
444	snd_config_for_each(i, next, a) {
445		n = snd_config_iterator_entry(i);
446		err = snd_config_get_id(n, &id);
447		if (err < 0)
448			goto __err_path;
449		err = snd_config_get_ascii(n, &var);
450		if (err < 0)
451			goto __err_path;
452		snprintf(name, sizeof(name), "__%s", id);
453		err = uc_mgr_set_variable(uc_mgr, name, var);
454		free(var);
455		if (err < 0)
456			goto __err_path;
457	}
458
459	/* merge + substitute variables */
460	err = snd_config_copy(&mc, m);
461	if (err < 0)
462		goto __err_path;
463	err = uc_mgr_evaluate_inplace(uc_mgr, mc);
464	if (err < 0) {
465		snd_config_delete(mc);
466		goto __err_path;
467	}
468	err = uc_mgr_config_tree_merge(uc_mgr, dst, mc, NULL, NULL);
469	snd_config_delete(mc);
470
471	/* delete arguments */
472	snd_config_for_each(i, next, a) {
473		n = snd_config_iterator_entry(i);
474		err = snd_config_get_id(n, &id);
475		if (err < 0)
476			goto __err_path;
477		snprintf(name, sizeof(name), "__%s", id);
478		err = uc_mgr_delete_variable(uc_mgr, name);
479		if (err < 0)
480			goto __err_path;
481	}
482
483__err_path:
484	if (a != args)
485		snd_config_delete(a);
486	return err;
487}
488
489/*
490 * Evaluate macro definitions and instances (in-place delete)
491 */
492static int evaluate_macro(snd_use_case_mgr_t *uc_mgr,
493			  snd_config_t *cfg)
494{
495	snd_config_iterator_t i, i2, next, next2;
496	snd_config_t *d, *n, *n2;
497	int err, ret;
498
499	ret = evaluate_define_macro(uc_mgr, cfg);
500	if (ret < 0)
501		return ret;
502
503	err = snd_config_search(cfg, "Macro", &d);
504	if (err == -ENOENT)
505		return ret;
506	if (err < 0)
507		return err;
508
509	if (snd_config_get_type(d) != SND_CONFIG_TYPE_COMPOUND) {
510		uc_error("compound type expected for DefineMacro");
511		return -EINVAL;
512	}
513
514	if (uc_mgr->conf_format < 6) {
515		uc_error("Macro is supported in v6+ syntax");
516		return -EINVAL;
517	}
518
519	snd_config_for_each(i, next, d) {
520		n = snd_config_iterator_entry(i);
521		if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) {
522			const char *id;
523			if (snd_config_get_id(n, &id))
524				id = "";
525			uc_error("compound type expected for Macro.%s", id);
526			return -EINVAL;
527		}
528		snd_config_for_each(i2, next2, n) {
529			n2 = snd_config_iterator_entry(i2);
530			err = evaluate_macro1(uc_mgr, cfg, n2);
531			if (err < 0)
532				return err;
533		}
534	}
535
536	snd_config_delete(d);
537
538	return 0;
539}
540
541/*
542 * Evaluate include (in-place)
543 */
544static int evaluate_include(snd_use_case_mgr_t *uc_mgr,
545			    snd_config_t *cfg)
546{
547	snd_config_t *n;
548	int err;
549
550	err = snd_config_search(cfg, "Include", &n);
551	if (err == -ENOENT)
552		return 1;
553	if (err < 0)
554		return err;
555
556	err = uc_mgr_evaluate_include(uc_mgr, cfg, n);
557	snd_config_delete(n);
558	return err;
559}
560
561/*
562 * Evaluate condition (in-place)
563 */
564static int evaluate_condition(snd_use_case_mgr_t *uc_mgr, snd_config_t *cfg)
565{
566	snd_config_t *n;
567	int err;
568
569	err = snd_config_search(cfg, "If", &n);
570	if (err == -ENOENT)
571		return 1;
572	if (err < 0)
573		return err;
574
575	err = uc_mgr_evaluate_condition(uc_mgr, cfg, n);
576	snd_config_delete(n);
577	return err;
578}
579
580/*
581 * Evaluate variant (in-place)
582 */
583static int evaluate_variant(snd_use_case_mgr_t *uc_mgr, snd_config_t *cfg)
584{
585	snd_config_iterator_t i, next;
586	snd_config_t *n, *c;
587	const char *id;
588	int err;
589
590	err = snd_config_search(cfg, "Variant", &c);
591	if (err == -ENOENT)
592		return 1;
593	if (err < 0)
594		return err;
595
596	if (uc_mgr->conf_format < 6) {
597		uc_error("Variant is supported in v6+ syntax");
598		return -EINVAL;
599	}
600
601	if (uc_mgr->parse_master_section)
602		return 1;
603
604	if (uc_mgr->parse_variant == NULL)
605		goto __ret;
606
607	snd_config_for_each(i, next, c) {
608		n = snd_config_iterator_entry(i);
609
610		if (snd_config_get_id(n, &id) < 0)
611			return -EINVAL;
612
613		if (strcmp(id, uc_mgr->parse_variant))
614			continue;
615
616		err = uc_mgr_evaluate_inplace(uc_mgr, n);
617		if (err < 0)
618			return err;
619
620		err = uc_mgr_config_tree_merge(uc_mgr, cfg, n, NULL, NULL);
621		if (err < 0)
622			return err;
623		snd_config_delete(c);
624		return 0;
625	}
626
627__ret:
628	snd_config_delete(c);
629	return 1;
630}
631
632/*
633 * In-place evaluate
634 */
635int uc_mgr_evaluate_inplace(snd_use_case_mgr_t *uc_mgr,
636			    snd_config_t *cfg)
637{
638	long iterations = 10000;
639	int err1 = 0, err2 = 0, err3 = 0, err4 = 0, err5 = 0;
640
641	while (err1 == 0 || err2 == 0 || err3 == 0 || err4 == 0 || err5 == 0) {
642		if (iterations == 0) {
643			uc_error("Maximal inplace evaluation iterations number reached (recursive references?)");
644			return -EINVAL;
645		}
646		iterations--;
647		/* variables at first */
648		err1 = evaluate_define(uc_mgr, cfg);
649		if (err1 < 0)
650			return err1;
651		/* include at second */
652		err2 = evaluate_include(uc_mgr, cfg);
653		if (err2 < 0)
654			return err2;
655		/* include or macro may define another variables */
656		/* conditions may depend on them */
657		if (err2 == 0)
658			continue;
659		err3 = evaluate_variant(uc_mgr, cfg);
660		if (err3 < 0)
661			return err3;
662		if (err3 == 0)
663			continue;
664		uc_mgr->macro_hops++;
665		if (uc_mgr->macro_hops > 100) {
666			uc_error("Maximal macro hops reached!");
667			return -EINVAL;
668		}
669		err4 = evaluate_macro(uc_mgr, cfg);
670		uc_mgr->macro_hops--;
671		if (err4 < 0)
672			return err4;
673		if (err4 == 0)
674			continue;
675		err5 = evaluate_condition(uc_mgr, cfg);
676		if (err5 < 0)
677			return err5;
678	}
679	return 0;
680}
681
682/*
683 * Parse one item for alsa-lib config
684 */
685static int parse_libconfig1(snd_use_case_mgr_t *uc_mgr, snd_config_t *cfg)
686{
687	snd_config_iterator_t i, next;
688	snd_config_t *n, *config = NULL;
689	const char *id, *file = NULL;
690	bool substfile = false, substconfig = false;
691	int err;
692
693	if (snd_config_get_id(cfg, &id) < 0)
694		return -EINVAL;
695
696	if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) {
697		uc_error("compound type expected for %s", id);
698		return -EINVAL;
699	}
700
701	snd_config_for_each(i, next, cfg) {
702		n = snd_config_iterator_entry(i);
703
704		if (snd_config_get_id(n, &id) < 0)
705			return -EINVAL;
706
707		if (strcmp(id, "File") == 0 ||
708		    strcmp(id, "SubstiFile") == 0) {
709			substfile = id[0] == 'S';
710			err = snd_config_get_string(n, &file);
711			if (err < 0)
712				return err;
713			continue;
714		}
715
716		if (strcmp(id, "Config") == 0 ||
717		    strcmp(id, "SubstiConfig") == 0) {
718			substconfig = id[0] == 'S';
719			if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND)
720				return -EINVAL;
721			config = n;
722			continue;
723		}
724
725		uc_error("unknown field %s", id);
726		return -EINVAL;
727	}
728
729	if (file) {
730		if (substfile) {
731			snd_config_t *cfg;
732			err = uc_mgr_config_load(uc_mgr->conf_format, file, &cfg);
733			if (err < 0)
734				return err;
735			err = uc_mgr_substitute_tree(uc_mgr, cfg);
736			if (err < 0) {
737				snd_config_delete(cfg);
738				return err;
739			}
740			err = snd_config_merge(uc_mgr->local_config, cfg, 0);
741			if (err < 0) {
742				snd_config_delete(cfg);
743				return err;
744			}
745		} else {
746			char filename[PATH_MAX];
747
748			ucm_filename(filename, sizeof(filename), uc_mgr->conf_format,
749				     file[0] == '/' ? NULL : uc_mgr->conf_dir_name,
750				     file);
751			err = uc_mgr_config_load_into(uc_mgr->conf_format, filename, uc_mgr->local_config);
752			if (err < 0)
753				return err;
754		}
755	}
756
757	if (config) {
758		if (substconfig) {
759			err = uc_mgr_substitute_tree(uc_mgr, config);
760			if (err < 0)
761				return err;
762		}
763		err = snd_config_merge(uc_mgr->local_config, config, 0);
764		if (err < 0)
765			return err;
766	}
767
768	return 0;
769}
770
771/*
772 * Parse alsa-lib config
773 */
774static int parse_libconfig(snd_use_case_mgr_t *uc_mgr, snd_config_t *cfg)
775{
776	snd_config_iterator_t i, next;
777	snd_config_t *n;
778	const char *id;
779	int err;
780
781	if (snd_config_get_id(cfg, &id) < 0)
782		return -EINVAL;
783
784	if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) {
785		uc_error("compound type expected for %s", id);
786		return -EINVAL;
787	}
788
789	snd_config_for_each(i, next, cfg) {
790		n = snd_config_iterator_entry(i);
791
792		err = parse_libconfig1(uc_mgr, n);
793		if (err < 0)
794			return err;
795	}
796
797	return 0;
798}
799
800/*
801 * Parse transition
802 */
803static int parse_transition(snd_use_case_mgr_t *uc_mgr,
804			    struct list_head *tlist,
805			    snd_config_t *cfg)
806{
807	struct transition_sequence *tseq;
808	const char *id;
809	snd_config_iterator_t i, next;
810	snd_config_t *n;
811	int err;
812
813	if (snd_config_get_id(cfg, &id) < 0)
814		return -EINVAL;
815
816	if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) {
817		uc_error("compound type expected for %s", id);
818		return -EINVAL;
819	}
820
821	snd_config_for_each(i, next, cfg) {
822		n = snd_config_iterator_entry(i);
823
824		if (snd_config_get_id(n, &id) < 0)
825			return -EINVAL;
826
827		tseq = calloc(1, sizeof(*tseq));
828		if (tseq == NULL)
829			return -ENOMEM;
830		INIT_LIST_HEAD(&tseq->transition_list);
831
832		err = get_string3(uc_mgr, id, &tseq->name);
833		if (err < 0) {
834			free(tseq);
835			return err;
836		}
837
838		err = parse_sequence(uc_mgr, &tseq->transition_list, n);
839		if (err < 0) {
840			uc_mgr_free_transition_element(tseq);
841			return err;
842		}
843
844		list_add(&tseq->list, tlist);
845	}
846	return 0;
847}
848
849/*
850 * Parse compound
851 */
852static int parse_compound(snd_use_case_mgr_t *uc_mgr, snd_config_t *cfg,
853	  int (*fcn)(snd_use_case_mgr_t *, snd_config_t *, void *, void *),
854	  void *data1, void *data2)
855{
856	const char *id;
857	snd_config_iterator_t i, next;
858	snd_config_t *n;
859	int err;
860
861	if (snd_config_get_id(cfg, &id) < 0)
862		return -EINVAL;
863
864	if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) {
865		uc_error("compound type expected for %s", id);
866		return -EINVAL;
867	}
868	/* parse compound */
869	snd_config_for_each(i, next, cfg) {
870		n = snd_config_iterator_entry(i);
871
872		if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) {
873			uc_error("compound type expected for %s, is %d", id, snd_config_get_type(cfg));
874			return -EINVAL;
875		}
876
877		err = fcn(uc_mgr, n, data1, data2);
878		if (err < 0)
879			return err;
880	}
881
882	return 0;
883}
884
885static int strip_legacy_dev_index(char *name)
886{
887	char *dot = strchr(name, '.');
888	if (!dot)
889		return 0;
890	if (dot[1] != '0' || dot[2] != '\0') {
891		uc_error("device name %s contains a '.',"
892			 " and is not legacy foo.0 format", name);
893		return -EINVAL;
894	}
895	*dot = '\0';
896	return 0;
897}
898
899/*
900 * Parse device list
901 */
902static int parse_device_list(snd_use_case_mgr_t *uc_mgr ATTRIBUTE_UNUSED,
903			     struct dev_list *dev_list,
904			     enum dev_list_type type,
905			     snd_config_t *cfg)
906{
907	struct dev_list_node *sdev;
908	const char *id;
909	snd_config_iterator_t i, next;
910	snd_config_t *n;
911	int err;
912
913	if (dev_list->type != DEVLIST_NONE) {
914		uc_error("error: multiple supported or"
915			" conflicting device lists");
916		return -EEXIST;
917	}
918
919	if (snd_config_get_id(cfg, &id) < 0)
920		return -EINVAL;
921
922	if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) {
923		uc_error("compound type expected for %s", id);
924		return -EINVAL;
925	}
926
927	snd_config_for_each(i, next, cfg) {
928		n = snd_config_iterator_entry(i);
929
930		if (snd_config_get_id(n, &id) < 0)
931			return -EINVAL;
932
933		sdev = calloc(1, sizeof(struct dev_list_node));
934		if (sdev == NULL)
935			return -ENOMEM;
936		err = parse_string_substitute3(uc_mgr, n, &sdev->name);
937		if (err < 0) {
938			free(sdev);
939			return err;
940		}
941		err = strip_legacy_dev_index(sdev->name);
942		if (err < 0) {
943			free(sdev->name);
944			free(sdev);
945			return err;
946		}
947		list_add(&sdev->list, &dev_list->list);
948	}
949
950	dev_list->type = type;
951
952	return 0;
953}
954
955/* Find a component device by its name, and remove it from machine device
956 * list.
957 *
958 * Component devices are defined by machine components (usually off-soc
959 * codes or DSP embeded in SoC). Since alsaconf imports their configuration
960 * files automatically, we don't know which devices are component devices
961 * until they are referenced by a machine device sequence. So here when we
962 * find a referenced device, we move it from the machine device list to the
963 * component device list. Component devices will not be exposed to applications
964 * by the original API to list devices for backward compatibility. So sound
965 * servers can only see the machine devices.
966 */
967struct use_case_device *find_component_dev(snd_use_case_mgr_t *uc_mgr,
968	const char *name)
969{
970	struct list_head *pos, *posdev, *_posdev;
971	struct use_case_verb *verb;
972	struct use_case_device *dev;
973
974	list_for_each(pos, &uc_mgr->verb_list) {
975		verb = list_entry(pos, struct use_case_verb, list);
976
977		/* search in the component device list */
978		list_for_each(posdev, &verb->cmpt_device_list) {
979			dev = list_entry(posdev, struct use_case_device, list);
980			if (!strcmp(dev->name, name))
981				return dev;
982		}
983
984		/* search the machine device list */
985		list_for_each_safe(posdev, _posdev, &verb->device_list) {
986			dev = list_entry(posdev, struct use_case_device, list);
987			if (!strcmp(dev->name, name)) {
988				/* find the component device, move it from the
989				 * machine device list to the component device
990				 * list.
991				 */
992				list_del(&dev->list);
993				list_add_tail(&dev->list,
994					      &verb->cmpt_device_list);
995				return dev;
996			}
997		}
998	}
999
1000	return NULL;
1001}
1002
1003/* parse sequence of a component device
1004 *
1005 * This function will find the component device and mark if its enable or
1006 * disable sequence is needed by its parenet device.
1007 */
1008static int parse_component_seq(snd_use_case_mgr_t *uc_mgr,
1009			       snd_config_t *n, int enable,
1010			       struct component_sequence *cmpt_seq)
1011{
1012	char *val;
1013	int err;
1014
1015	err = parse_string_substitute3(uc_mgr, n, &val);
1016	if (err < 0)
1017		return err;
1018
1019	cmpt_seq->device = find_component_dev(uc_mgr, val);
1020	if (!cmpt_seq->device) {
1021		uc_error("error: Cannot find component device %s", val);
1022		free(val);
1023		return -EINVAL;
1024	}
1025	free(val);
1026
1027	/* Parent needs its enable or disable sequence */
1028	cmpt_seq->enable = enable;
1029
1030	return 0;
1031}
1032
1033/*
1034 * Parse sequences.
1035 *
1036 * Sequence controls elements  are in the following form:-
1037 *
1038 * cdev "hw:0"
1039 * cset "element_id_syntax value_syntax"
1040 * usleep time
1041 * exec "any unix command with arguments"
1042 * enadev "component device name"
1043 * disdev "component device name"
1044 *
1045 * e.g.
1046 *	cset "name='Master Playback Switch' 0,0"
1047 *      cset "iface=PCM,name='Disable HDMI',index=1 0"
1048 *	enadev "rt286:Headphones"
1049 *	disdev "rt286:Speaker"
1050 */
1051static int parse_sequence(snd_use_case_mgr_t *uc_mgr,
1052			  struct list_head *base,
1053			  snd_config_t *cfg)
1054{
1055	struct sequence_element *curr;
1056	snd_config_iterator_t i, next;
1057	snd_config_t *n;
1058	int err, idx = 0;
1059	const char *cmd = NULL;
1060
1061	if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) {
1062		uc_error("error: compound is expected for sequence definition");
1063		return -EINVAL;
1064	}
1065
1066	snd_config_for_each(i, next, cfg) {
1067		const char *id;
1068		idx ^= 1;
1069		n = snd_config_iterator_entry(i);
1070		err = snd_config_get_id(n, &id);
1071		if (err < 0)
1072			continue;
1073		if (idx == 1) {
1074			if (snd_config_get_type(n) != SND_CONFIG_TYPE_STRING) {
1075				uc_error("error: string type is expected for sequence command");
1076				return -EINVAL;
1077			}
1078			snd_config_get_string(n, &cmd);
1079			continue;
1080		}
1081
1082		/* alloc new sequence element */
1083		curr = calloc(1, sizeof(struct sequence_element));
1084		if (curr == NULL)
1085			return -ENOMEM;
1086		list_add_tail(&curr->list, base);
1087
1088		if (strcmp(cmd, "cdev") == 0) {
1089			curr->type = SEQUENCE_ELEMENT_TYPE_CDEV;
1090			err = parse_string_substitute3(uc_mgr, n, &curr->data.cdev);
1091			if (err < 0) {
1092				uc_error("error: cdev requires a string!");
1093				return err;
1094			}
1095			continue;
1096		}
1097
1098		if (strcmp(cmd, "cset") == 0) {
1099			curr->type = SEQUENCE_ELEMENT_TYPE_CSET;
1100cset:
1101			err = parse_string_substitute3(uc_mgr, n, &curr->data.cset);
1102			if (err < 0) {
1103				uc_error("error: %s requires a string!", cmd);
1104				return err;
1105			}
1106			continue;
1107		}
1108
1109		if (strcmp(cmd, "enadev") == 0 ||
1110		    strcmp(cmd, "disdev") == 0) {
1111			/* need to enable or disable a component device */
1112			curr->type = SEQUENCE_ELEMENT_TYPE_CMPT_SEQ;
1113			err = parse_component_seq(uc_mgr, n,
1114						strcmp(cmd, "enadev") == 0,
1115						&curr->data.cmpt_seq);
1116			if (err < 0) {
1117				uc_error("error: %s requires a valid device!", cmd);
1118				return err;
1119			}
1120			continue;
1121		}
1122
1123		if (strcmp(cmd, "enadev2") == 0) {
1124			curr->type = SEQUENCE_ELEMENT_TYPE_DEV_ENABLE_SEQ;
1125			goto device;
1126		}
1127
1128		if (strcmp(cmd, "disdev2") == 0) {
1129			curr->type = SEQUENCE_ELEMENT_TYPE_DEV_DISABLE_SEQ;
1130device:
1131			err = parse_string_substitute3(uc_mgr, n, &curr->data.device);
1132			if (err < 0) {
1133				uc_error("error: %s requires a valid device!", cmd);
1134				return err;
1135			}
1136			continue;
1137		}
1138
1139		if (strcmp(cmd, "disdevall") == 0) {
1140			curr->type = SEQUENCE_ELEMENT_TYPE_DEV_DISABLE_ALL;
1141			continue;
1142		}
1143
1144		if (strcmp(cmd, "cset-bin-file") == 0) {
1145			curr->type = SEQUENCE_ELEMENT_TYPE_CSET_BIN_FILE;
1146			goto cset;
1147		}
1148
1149		if (strcmp(cmd, "cset-tlv") == 0) {
1150			curr->type = SEQUENCE_ELEMENT_TYPE_CSET_TLV;
1151			goto cset;
1152		}
1153
1154		if (strcmp(cmd, "cset-new") == 0) {
1155			curr->type = SEQUENCE_ELEMENT_TYPE_CSET_NEW;
1156			goto cset;
1157		}
1158
1159		if (strcmp(cmd, "ctl-remove") == 0) {
1160			curr->type = SEQUENCE_ELEMENT_TYPE_CTL_REMOVE;
1161			goto cset;
1162		}
1163
1164		if (strcmp(cmd, "sysw") == 0) {
1165			curr->type = SEQUENCE_ELEMENT_TYPE_SYSSET;
1166			err = parse_string_substitute3(uc_mgr, n, &curr->data.sysw);
1167			if (err < 0) {
1168				uc_error("error: sysw requires a string!");
1169				return err;
1170			}
1171			continue;
1172		}
1173
1174		if (strcmp(cmd, "usleep") == 0) {
1175			curr->type = SEQUENCE_ELEMENT_TYPE_SLEEP;
1176			err = parse_integer_substitute3(uc_mgr, n, &curr->data.sleep);
1177			if (err < 0) {
1178				uc_error("error: usleep requires integer!");
1179				return err;
1180			}
1181			continue;
1182		}
1183
1184		if (strcmp(cmd, "msleep") == 0) {
1185			curr->type = SEQUENCE_ELEMENT_TYPE_SLEEP;
1186			err = parse_integer_substitute3(uc_mgr, n, &curr->data.sleep);
1187			if (err < 0) {
1188				uc_error("error: msleep requires integer!");
1189				return err;
1190			}
1191			curr->data.sleep *= 1000L;
1192			continue;
1193		}
1194
1195		if (strcmp(cmd, "exec") == 0) {
1196			curr->type = SEQUENCE_ELEMENT_TYPE_EXEC;
1197exec:
1198			err = parse_string_substitute3(uc_mgr, n, &curr->data.exec);
1199			if (err < 0) {
1200				uc_error("error: exec requires a string!");
1201				return err;
1202			}
1203			continue;
1204		}
1205
1206		if (strcmp(cmd, "shell") == 0) {
1207			curr->type = SEQUENCE_ELEMENT_TYPE_SHELL;
1208			goto exec;
1209		}
1210
1211		if (strcmp(cmd, "cfg-save") == 0) {
1212			curr->type = SEQUENCE_ELEMENT_TYPE_CFGSAVE;
1213			err = parse_string_substitute3(uc_mgr, n, &curr->data.cfgsave);
1214			if (err < 0) {
1215				uc_error("error: sysw requires a string!");
1216				return err;
1217			}
1218			continue;
1219		}
1220
1221		if (strcmp(cmd, "comment") == 0)
1222			goto skip;
1223
1224		uc_error("error: sequence command '%s' is ignored", cmd);
1225
1226skip:
1227		list_del(&curr->list);
1228		uc_mgr_free_sequence_element(curr);
1229	}
1230
1231	return 0;
1232}
1233
1234/*
1235 *
1236 */
1237int uc_mgr_add_value(struct list_head *base, const char *key, char *val)
1238{
1239	struct ucm_value *curr;
1240
1241	curr = calloc(1, sizeof(struct ucm_value));
1242	if (curr == NULL)
1243		return -ENOMEM;
1244	curr->name = strdup(key);
1245	if (curr->name == NULL) {
1246		free(curr);
1247		return -ENOMEM;
1248	}
1249	list_add_tail(&curr->list, base);
1250	curr->data = val;
1251	return 0;
1252}
1253
1254/*
1255 * Parse values.
1256 *
1257 * Parse values describing PCM, control/mixer settings and stream parameters.
1258 *
1259 * Value {
1260 *   TQ Voice
1261 *   CapturePCM "hw:1"
1262 *   PlaybackVolume "name='Master Playback Volume',index=2"
1263 *   PlaybackSwitch "name='Master Playback Switch',index=2"
1264 * }
1265 */
1266static int parse_value(snd_use_case_mgr_t *uc_mgr ATTRIBUTE_UNUSED,
1267			  struct list_head *base,
1268			  snd_config_t *cfg)
1269{
1270	snd_config_iterator_t i, next;
1271	snd_config_t *n;
1272	char *s;
1273	snd_config_type_t type;
1274	int err;
1275
1276	if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) {
1277		uc_error("error: compound is expected for value definition");
1278		return -EINVAL;
1279	}
1280
1281	/* in-place evaluation */
1282	err = uc_mgr_evaluate_inplace(uc_mgr, cfg);
1283	if (err < 0)
1284		return err;
1285
1286	snd_config_for_each(i, next, cfg) {
1287		const char *id;
1288		n = snd_config_iterator_entry(i);
1289		err = snd_config_get_id(n, &id);
1290		if (err < 0)
1291			continue;
1292
1293		type = snd_config_get_type(n);
1294		switch (type) {
1295		case SND_CONFIG_TYPE_INTEGER:
1296		case SND_CONFIG_TYPE_INTEGER64:
1297		case SND_CONFIG_TYPE_REAL:
1298			err = snd_config_get_ascii(n, &s);
1299			if (err < 0) {
1300				uc_error("error: unable to parse value for id '%s': %s!", id, snd_strerror(err));
1301				return err;
1302			}
1303			break;
1304		case SND_CONFIG_TYPE_STRING:
1305			err = parse_string_substitute(uc_mgr, n, &s);
1306			if (err < 0) {
1307				uc_error("error: unable to parse a string for id '%s'!", id);
1308				return err;
1309			}
1310			break;
1311		default:
1312			uc_error("error: invalid type %i in Value compound '%s'", type, id);
1313			return -EINVAL;
1314		}
1315		err = uc_mgr_add_value(base, id, s);
1316		if (err < 0) {
1317			free(s);
1318			return err;
1319		}
1320	}
1321
1322	return 0;
1323}
1324
1325/*
1326 * Parse Modifier Use cases
1327 *
1328 * # Each modifier is described in new section. N modifiers are allowed
1329 * SectionModifier."Capture Voice" {
1330 *
1331 *	Comment "Record voice call"
1332 *
1333 *	SupportedDevice [
1334 *		"x"
1335 *		"y"
1336 *	]
1337 *
1338 *	ConflictingDevice [
1339 *		"x"
1340 *		"y"
1341 *	]
1342 *
1343 *	EnableSequence [
1344 *		....
1345 *	]
1346 *
1347 *	DisableSequence [
1348 *		...
1349 *	]
1350 *
1351 *      TransitionSequence."ToModifierName" [
1352 *		...
1353 *	]
1354 *
1355 *	# Optional TQ and ALSA PCMs
1356 *	Value {
1357 *		TQ Voice
1358 *		CapturePCM "hw:1"
1359 *		PlaybackVolume "name='Master Playback Volume',index=2"
1360 *		PlaybackSwitch "name='Master Playback Switch',index=2"
1361 *	}
1362 * }
1363 *
1364 * SupportedDevice and ConflictingDevice cannot be specified together.
1365 * Both are optional.
1366 */
1367static int parse_modifier(snd_use_case_mgr_t *uc_mgr,
1368			  snd_config_t *cfg,
1369			  void *data1, void *data2)
1370{
1371	struct use_case_verb *verb = data1;
1372	struct use_case_modifier *modifier;
1373	char *name;
1374	snd_config_iterator_t i, next;
1375	snd_config_t *n;
1376	int err;
1377
1378	if (parse_get_safe_name(uc_mgr, cfg, data2, &name) < 0)
1379		return -EINVAL;
1380
1381	/* allocate modifier */
1382	modifier = calloc(1, sizeof(*modifier));
1383	if (modifier == NULL) {
1384		free(name);
1385		return -ENOMEM;
1386	}
1387	INIT_LIST_HEAD(&modifier->enable_list);
1388	INIT_LIST_HEAD(&modifier->disable_list);
1389	INIT_LIST_HEAD(&modifier->transition_list);
1390	INIT_LIST_HEAD(&modifier->dev_list.list);
1391	INIT_LIST_HEAD(&modifier->value_list);
1392	list_add_tail(&modifier->list, &verb->modifier_list);
1393	modifier->name = name;
1394
1395	/* in-place evaluation */
1396	err = uc_mgr_evaluate_inplace(uc_mgr, cfg);
1397	if (err < 0)
1398		return err;
1399
1400	snd_config_for_each(i, next, cfg) {
1401		const char *id;
1402		n = snd_config_iterator_entry(i);
1403		if (snd_config_get_id(n, &id) < 0)
1404			continue;
1405
1406		if (strcmp(id, "Comment") == 0) {
1407			err = parse_string_substitute3(uc_mgr, n, &modifier->comment);
1408			if (err < 0) {
1409				uc_error("error: failed to get modifier comment");
1410				return err;
1411			}
1412			continue;
1413		}
1414
1415		if (strcmp(id, "SupportedDevice") == 0) {
1416			err = parse_device_list(uc_mgr, &modifier->dev_list,
1417						DEVLIST_SUPPORTED, n);
1418			if (err < 0) {
1419				uc_error("error: failed to parse supported"
1420					" device list");
1421				return err;
1422			}
1423		}
1424
1425		if (strcmp(id, "ConflictingDevice") == 0) {
1426			err = parse_device_list(uc_mgr, &modifier->dev_list,
1427						DEVLIST_CONFLICTING, n);
1428			if (err < 0) {
1429				uc_error("error: failed to parse conflicting"
1430					" device list");
1431				return err;
1432			}
1433		}
1434
1435		if (strcmp(id, "EnableSequence") == 0) {
1436			err = parse_sequence(uc_mgr, &modifier->enable_list, n);
1437			if (err < 0) {
1438				uc_error("error: failed to parse modifier"
1439					" enable sequence");
1440				return err;
1441			}
1442			continue;
1443		}
1444
1445		if (strcmp(id, "DisableSequence") == 0) {
1446			err = parse_sequence(uc_mgr, &modifier->disable_list, n);
1447			if (err < 0) {
1448				uc_error("error: failed to parse modifier"
1449					" disable sequence");
1450				return err;
1451			}
1452			continue;
1453		}
1454
1455		if (strcmp(id, "TransitionSequence") == 0) {
1456			err = parse_transition(uc_mgr, &modifier->transition_list, n);
1457			if (err < 0) {
1458				uc_error("error: failed to parse transition"
1459					" modifier");
1460				return err;
1461			}
1462			continue;
1463		}
1464
1465		if (strcmp(id, "Value") == 0) {
1466			err = parse_value(uc_mgr, &modifier->value_list, n);
1467			if (err < 0) {
1468				uc_error("error: failed to parse Value");
1469				return err;
1470			}
1471			continue;
1472		}
1473	}
1474
1475	return 0;
1476}
1477
1478/*
1479 * Parse Device Use Cases
1480 *
1481 * # Each device is described in new section. N devices are allowed
1482 * SectionDevice."Headphones" {
1483 *	Comment "Headphones connected to 3.5mm jack"
1484 *
1485 *	SupportedDevice [
1486 *		"x"
1487 *		"y"
1488 *	]
1489 *
1490 *	ConflictingDevice [
1491 *		"x"
1492 *		"y"
1493 *	]
1494 *
1495 *	EnableSequence [
1496 *		....
1497 *	]
1498 *
1499 *	DisableSequence [
1500 *		...
1501 *	]
1502 *
1503 *      TransitionSequence."ToDevice" [
1504 *		...
1505 *	]
1506 *
1507 *	Value {
1508 *		PlaybackVolume "name='Master Playback Volume',index=2"
1509 *		PlaybackSwitch "name='Master Playback Switch',index=2"
1510 *	}
1511 * }
1512 */
1513static int parse_device(snd_use_case_mgr_t *uc_mgr,
1514			snd_config_t *cfg,
1515			void *data1, void *data2)
1516{
1517	struct use_case_verb *verb = data1;
1518	char *name;
1519	struct use_case_device *device;
1520	snd_config_iterator_t i, next;
1521	snd_config_t *n;
1522	int err;
1523
1524	if (parse_get_safe_name(uc_mgr, cfg, data2, &name) < 0)
1525		return -EINVAL;
1526
1527	device = calloc(1, sizeof(*device));
1528	if (device == NULL) {
1529		free(name);
1530		return -ENOMEM;
1531	}
1532	INIT_LIST_HEAD(&device->enable_list);
1533	INIT_LIST_HEAD(&device->disable_list);
1534	INIT_LIST_HEAD(&device->transition_list);
1535	INIT_LIST_HEAD(&device->dev_list.list);
1536	INIT_LIST_HEAD(&device->value_list);
1537	list_add_tail(&device->list, &verb->device_list);
1538	device->name = name;
1539
1540	/* in-place evaluation */
1541	err = uc_mgr_evaluate_inplace(uc_mgr, cfg);
1542	if (err < 0)
1543		return err;
1544
1545	snd_config_for_each(i, next, cfg) {
1546		const char *id;
1547		n = snd_config_iterator_entry(i);
1548		if (snd_config_get_id(n, &id) < 0)
1549			continue;
1550
1551		if (strcmp(id, "Comment") == 0) {
1552			err = parse_string_substitute3(uc_mgr, n, &device->comment);
1553			if (err < 0) {
1554				uc_error("error: failed to get device comment");
1555				return err;
1556			}
1557			continue;
1558		}
1559
1560		if (strcmp(id, "SupportedDevice") == 0) {
1561			err = parse_device_list(uc_mgr, &device->dev_list,
1562						DEVLIST_SUPPORTED, n);
1563			if (err < 0) {
1564				uc_error("error: failed to parse supported"
1565					" device list");
1566				return err;
1567			}
1568		}
1569
1570		if (strcmp(id, "ConflictingDevice") == 0) {
1571			err = parse_device_list(uc_mgr, &device->dev_list,
1572						DEVLIST_CONFLICTING, n);
1573			if (err < 0) {
1574				uc_error("error: failed to parse conflicting"
1575					" device list");
1576				return err;
1577			}
1578		}
1579
1580		if (strcmp(id, "EnableSequence") == 0) {
1581			uc_dbg("EnableSequence");
1582			err = parse_sequence(uc_mgr, &device->enable_list, n);
1583			if (err < 0) {
1584				uc_error("error: failed to parse device enable"
1585					 " sequence");
1586				return err;
1587			}
1588			continue;
1589		}
1590
1591		if (strcmp(id, "DisableSequence") == 0) {
1592			uc_dbg("DisableSequence");
1593			err = parse_sequence(uc_mgr, &device->disable_list, n);
1594			if (err < 0) {
1595				uc_error("error: failed to parse device disable"
1596					 " sequence");
1597				return err;
1598			}
1599			continue;
1600		}
1601
1602		if (strcmp(id, "TransitionSequence") == 0) {
1603			uc_dbg("TransitionSequence");
1604			err = parse_transition(uc_mgr, &device->transition_list, n);
1605			if (err < 0) {
1606				uc_error("error: failed to parse transition"
1607					" device");
1608				return err;
1609			}
1610			continue;
1611		}
1612
1613		if (strcmp(id, "Value") == 0) {
1614			err = parse_value(uc_mgr, &device->value_list, n);
1615			if (err < 0) {
1616				uc_error("error: failed to parse Value");
1617				return err;
1618			}
1619			continue;
1620		}
1621	}
1622	return 0;
1623}
1624
1625/*
1626 * Parse Device Rename/Delete Command
1627 *
1628 * # The devices might be renamed to allow the better conditional runtime
1629 * # evaluation. Bellow example renames Speaker1 device to Speaker and
1630 * # removes Speaker2 device.
1631 * RenameDevice."Speaker1" "Speaker"
1632 * RemoveDevice."Speaker2" "Speaker2"
1633 */
1634static int parse_dev_name_list(snd_use_case_mgr_t *uc_mgr,
1635			       snd_config_t *cfg,
1636			       struct list_head *list)
1637{
1638	snd_config_t *n;
1639	snd_config_iterator_t i, next;
1640	const char *id, *name1;
1641	char *name1s, *name2;
1642	struct ucm_dev_name *dev;
1643	snd_config_iterator_t pos;
1644	int err;
1645
1646	if (snd_config_get_id(cfg, &id) < 0)
1647		return -EINVAL;
1648
1649	if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) {
1650		uc_error("compound type expected for %s", id);
1651		return -EINVAL;
1652	}
1653
1654	snd_config_for_each(i, next, cfg) {
1655		n = snd_config_iterator_entry(i);
1656
1657		if (snd_config_get_id(n, &name1) < 0)
1658			return -EINVAL;
1659
1660		err = get_string3(uc_mgr, name1, &name1s);
1661		if (err < 0)
1662			return err;
1663
1664		err = parse_string_substitute3(uc_mgr, n, &name2);
1665		if (err < 0) {
1666			free(name1s);
1667			uc_error("error: failed to get target device name for '%s'", name1);
1668			return err;
1669		}
1670
1671		/* skip duplicates */
1672		list_for_each(pos, list) {
1673			dev = list_entry(pos, struct ucm_dev_name, list);
1674			if (strcmp(dev->name1, name1s) == 0) {
1675				free(name2);
1676				free(name1s);
1677				return 0;
1678			}
1679		}
1680
1681		free(name1s);
1682
1683		dev = calloc(1, sizeof(*dev));
1684		if (dev == NULL) {
1685			free(name2);
1686			return -ENOMEM;
1687		}
1688		dev->name1 = strdup(name1);
1689		if (dev->name1 == NULL) {
1690			free(dev);
1691			free(name2);
1692			return -ENOMEM;
1693		}
1694		dev->name2 = name2;
1695		list_add_tail(&dev->list, list);
1696	}
1697
1698	return 0;
1699}
1700
1701static int parse_compound_check_legacy(snd_use_case_mgr_t *uc_mgr,
1702	  snd_config_t *cfg,
1703	  int (*fcn)(snd_use_case_mgr_t *, snd_config_t *, void *, void *),
1704	  void *data1)
1705{
1706	const char *id, *idchild;
1707	int child_ctr = 0, legacy_format = 1;
1708	snd_config_iterator_t i, next;
1709	snd_config_t *child;
1710	int err;
1711
1712	err = snd_config_get_id(cfg, &id);
1713	if (err < 0)
1714		return err;
1715
1716	snd_config_for_each(i, next, cfg) {
1717		child_ctr++;
1718		if (child_ctr > 1) {
1719			break;
1720		}
1721
1722		child = snd_config_iterator_entry(i);
1723
1724		if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) {
1725			legacy_format = 0;
1726			break;
1727		}
1728
1729		if (snd_config_get_id(child, &idchild) < 0)
1730			return -EINVAL;
1731
1732		if (strcmp(idchild, "0")) {
1733			legacy_format = 0;
1734			break;
1735		}
1736	}
1737	if (child_ctr != 1) {
1738		legacy_format = 0;
1739	}
1740
1741	if (legacy_format)
1742		return parse_compound(uc_mgr, cfg, fcn, data1, (void *)id);
1743	else
1744		return fcn(uc_mgr, cfg, data1, NULL);
1745}
1746
1747static int parse_device_name(snd_use_case_mgr_t *uc_mgr,
1748			     snd_config_t *cfg,
1749			     void *data1,
1750			     void *data2 ATTRIBUTE_UNUSED)
1751{
1752	return parse_compound_check_legacy(uc_mgr, cfg, parse_device, data1);
1753}
1754
1755static int parse_modifier_name(snd_use_case_mgr_t *uc_mgr,
1756			     snd_config_t *cfg,
1757			     void *data1,
1758			     void *data2 ATTRIBUTE_UNUSED)
1759{
1760	return parse_compound_check_legacy(uc_mgr, cfg, parse_modifier, data1);
1761}
1762
1763static int verb_dev_list_add(struct use_case_verb *verb,
1764			     enum dev_list_type dst_type,
1765			     const char *dst,
1766			     const char *src)
1767{
1768	struct use_case_device *device;
1769	struct list_head *pos;
1770
1771	list_for_each(pos, &verb->device_list) {
1772		device = list_entry(pos, struct use_case_device, list);
1773		if (strcmp(device->name, dst) != 0)
1774			continue;
1775		if (device->dev_list.type != dst_type) {
1776			if (list_empty(&device->dev_list.list)) {
1777				device->dev_list.type = dst_type;
1778			} else {
1779				uc_error("error: incompatible device list type ('%s', '%s')",
1780					 device->name, src);
1781				return -EINVAL;
1782			}
1783		}
1784		return uc_mgr_put_to_dev_list(&device->dev_list, src);
1785	}
1786	uc_error("error: unable to find device '%s'", dst);
1787	return -ENOENT;
1788}
1789
1790static int verb_dev_list_check(struct use_case_verb *verb)
1791{
1792	struct list_head *pos, *pos2;
1793	struct use_case_device *device;
1794	struct dev_list_node *dlist;
1795	int err;
1796
1797	list_for_each(pos, &verb->device_list) {
1798		device = list_entry(pos, struct use_case_device, list);
1799		list_for_each(pos2, &device->dev_list.list) {
1800			dlist = list_entry(pos2, struct dev_list_node, list);
1801			err = verb_dev_list_add(verb, device->dev_list.type,
1802						dlist->name, device->name);
1803			if (err < 0)
1804				return err;
1805		}
1806	}
1807	return 0;
1808}
1809
1810static int verb_device_management(struct use_case_verb *verb)
1811{
1812	struct list_head *pos;
1813	struct ucm_dev_name *dev;
1814	int err;
1815
1816	/* rename devices */
1817	list_for_each(pos, &verb->rename_list) {
1818		dev = list_entry(pos, struct ucm_dev_name, list);
1819		err = uc_mgr_rename_device(verb, dev->name1, dev->name2);
1820		if (err < 0) {
1821			uc_error("error: cannot rename device '%s' to '%s'", dev->name1, dev->name2);
1822			return err;
1823		}
1824	}
1825
1826	/* remove devices */
1827	list_for_each(pos, &verb->remove_list) {
1828		dev = list_entry(pos, struct ucm_dev_name, list);
1829		err = uc_mgr_remove_device(verb, dev->name2);
1830		if (err < 0) {
1831			uc_error("error: cannot remove device '%s'", dev->name2);
1832			return err;
1833		}
1834	}
1835
1836	/* those lists are no longer used */
1837	uc_mgr_free_dev_name_list(&verb->rename_list);
1838	uc_mgr_free_dev_name_list(&verb->remove_list);
1839
1840	/* handle conflicting/supported lists */
1841	return verb_dev_list_check(verb);
1842}
1843
1844/*
1845 * Parse Verb Section
1846 *
1847 * # Example Use case verb section for Voice call blah
1848 * # By Joe Blogs <joe@blogs.com>
1849 *
1850 * SectionVerb {
1851 *	# enable and disable sequences are compulsory
1852 *	EnableSequence [
1853 *		cset "name='Master Playback Switch',index=2 0,0"
1854 *		cset "name='Master Playback Volume',index=2 25,25"
1855 *		msleep 50
1856 *		cset "name='Master Playback Switch',index=2 1,1"
1857 *		cset "name='Master Playback Volume',index=2 50,50"
1858 *	]
1859 *
1860 *	DisableSequence [
1861 *		cset "name='Master Playback Switch',index=2 0,0"
1862 *		cset "name='Master Playback Volume',index=2 25,25"
1863 *		msleep 50
1864 *		cset "name='Master Playback Switch',index=2 1,1"
1865 *		cset "name='Master Playback Volume',index=2 50,50"
1866 *	]
1867 *
1868 *      # Optional transition verb
1869 *      TransitionSequence."ToCaseName" [
1870 *		msleep 1
1871 *      ]
1872 *
1873 *	# Optional TQ and ALSA PCMs
1874 *	Value {
1875 *		TQ HiFi
1876 *		CapturePCM "hw:0"
1877 *		PlaybackPCM "hw:0"
1878 *	}
1879 * }
1880 */
1881static int parse_verb(snd_use_case_mgr_t *uc_mgr,
1882		      struct use_case_verb *verb,
1883		      snd_config_t *cfg)
1884{
1885	snd_config_iterator_t i, next;
1886	snd_config_t *n;
1887	int err;
1888
1889	/* in-place evaluation */
1890	err = uc_mgr_evaluate_inplace(uc_mgr, cfg);
1891	if (err < 0)
1892		return err;
1893
1894	/* parse verb section */
1895	snd_config_for_each(i, next, cfg) {
1896		const char *id;
1897		n = snd_config_iterator_entry(i);
1898		if (snd_config_get_id(n, &id) < 0)
1899			continue;
1900
1901		if (strcmp(id, "EnableSequence") == 0) {
1902			uc_dbg("Parse EnableSequence");
1903			err = parse_sequence(uc_mgr, &verb->enable_list, n);
1904			if (err < 0) {
1905				uc_error("error: failed to parse verb enable sequence");
1906				return err;
1907			}
1908			continue;
1909		}
1910
1911		if (strcmp(id, "DisableSequence") == 0) {
1912			uc_dbg("Parse DisableSequence");
1913			err = parse_sequence(uc_mgr, &verb->disable_list, n);
1914			if (err < 0) {
1915				uc_error("error: failed to parse verb disable sequence");
1916				return err;
1917			}
1918			continue;
1919		}
1920
1921		if (strcmp(id, "TransitionSequence") == 0) {
1922			uc_dbg("Parse TransitionSequence");
1923			err = parse_transition(uc_mgr, &verb->transition_list, n);
1924			if (err < 0) {
1925				uc_error("error: failed to parse transition sequence");
1926				return err;
1927			}
1928			continue;
1929		}
1930
1931		if (strcmp(id, "Value") == 0) {
1932			uc_dbg("Parse Value");
1933			err = parse_value(uc_mgr, &verb->value_list, n);
1934			if (err < 0)
1935				return err;
1936			continue;
1937		}
1938	}
1939
1940	return 0;
1941}
1942
1943/*
1944 * Parse a Use case verb file.
1945 *
1946 * This file contains the following :-
1947 *  o Verb enable and disable sequences.
1948 *  o Supported Device enable and disable sequences for verb.
1949 *  o Supported Modifier enable and disable sequences for verb
1950 *  o Optional QoS for the verb and modifiers.
1951 *  o Optional PCM device ID for verb and modifiers
1952 *  o Alias kcontrols IDs for master and volumes and mutes.
1953 */
1954static int parse_verb_file(snd_use_case_mgr_t *uc_mgr,
1955			   const char *use_case_name,
1956			   const char *comment,
1957			   const char *file)
1958{
1959	snd_config_iterator_t i, next;
1960	snd_config_t *n;
1961	struct use_case_verb *verb;
1962	snd_config_t *cfg;
1963	int err;
1964
1965	/* allocate verb */
1966	verb = calloc(1, sizeof(struct use_case_verb));
1967	if (verb == NULL)
1968		return -ENOMEM;
1969	INIT_LIST_HEAD(&verb->enable_list);
1970	INIT_LIST_HEAD(&verb->disable_list);
1971	INIT_LIST_HEAD(&verb->transition_list);
1972	INIT_LIST_HEAD(&verb->device_list);
1973	INIT_LIST_HEAD(&verb->cmpt_device_list);
1974	INIT_LIST_HEAD(&verb->modifier_list);
1975	INIT_LIST_HEAD(&verb->value_list);
1976	INIT_LIST_HEAD(&verb->rename_list);
1977	INIT_LIST_HEAD(&verb->remove_list);
1978	list_add_tail(&verb->list, &uc_mgr->verb_list);
1979	if (use_case_name == NULL)
1980		return -EINVAL;
1981	verb->name = strdup(use_case_name);
1982	if (verb->name == NULL)
1983		return -ENOMEM;
1984
1985	if (comment != NULL) {
1986		verb->comment = strdup(comment);
1987		if (verb->comment == NULL)
1988			return -ENOMEM;
1989	}
1990
1991	/* open Verb file for reading */
1992	err = uc_mgr_config_load_file(uc_mgr, file, &cfg);
1993	if (err < 0)
1994		return err;
1995
1996	/* in-place evaluation */
1997	err = uc_mgr_evaluate_inplace(uc_mgr, cfg);
1998	if (err < 0)
1999		goto _err;
2000
2001	/* parse master config sections */
2002	snd_config_for_each(i, next, cfg) {
2003		const char *id;
2004		n = snd_config_iterator_entry(i);
2005		if (snd_config_get_id(n, &id) < 0)
2006			continue;
2007
2008		/* find verb section and parse it */
2009		if (strcmp(id, "SectionVerb") == 0) {
2010			err = parse_verb(uc_mgr, verb, n);
2011			if (err < 0) {
2012				uc_error("error: %s failed to parse verb",
2013						file);
2014				goto _err;
2015			}
2016			continue;
2017		}
2018
2019		/* find device sections and parse them */
2020		if (strcmp(id, "SectionDevice") == 0) {
2021			err = parse_compound(uc_mgr, n,
2022						parse_device_name, verb, NULL);
2023			if (err < 0) {
2024				uc_error("error: %s failed to parse device",
2025						file);
2026				goto _err;
2027			}
2028			continue;
2029		}
2030
2031		/* find modifier sections and parse them */
2032		if (strcmp(id, "SectionModifier") == 0) {
2033			err = parse_compound(uc_mgr, n,
2034					     parse_modifier_name, verb, NULL);
2035			if (err < 0) {
2036				uc_error("error: %s failed to parse modifier",
2037						file);
2038				goto _err;
2039			}
2040			continue;
2041		}
2042
2043		/* device renames */
2044		if (strcmp(id, "RenameDevice") == 0) {
2045			err = parse_dev_name_list(uc_mgr, n, &verb->rename_list);
2046			if (err < 0) {
2047				uc_error("error: %s failed to parse device rename",
2048						file);
2049				goto _err;
2050			}
2051			continue;
2052		}
2053
2054		/* device remove */
2055		if (strcmp(id, "RemoveDevice") == 0) {
2056			err = parse_dev_name_list(uc_mgr, n, &verb->remove_list);
2057			if (err < 0) {
2058				uc_error("error: %s failed to parse device remove",
2059						file);
2060				goto _err;
2061			}
2062			continue;
2063		}
2064
2065		/* alsa-lib configuration */
2066		if (uc_mgr->conf_format > 3 && strcmp(id, "LibraryConfig") == 0) {
2067			err = parse_libconfig(uc_mgr, n);
2068			if (err < 0) {
2069				uc_error("error: failed to parse LibConfig");
2070				goto _err;
2071			}
2072			continue;
2073		}
2074	}
2075
2076	snd_config_delete(cfg);
2077
2078	/* use case verb must have at least 1 device */
2079	if (list_empty(&verb->device_list)) {
2080		uc_error("error: no use case device defined", file);
2081		return -EINVAL;
2082	}
2083
2084	/* do device rename and delete */
2085	err = verb_device_management(verb);
2086	if (err < 0) {
2087		uc_error("error: device management error in verb '%s'", verb->name);
2088		return err;
2089	}
2090
2091	return 0;
2092
2093       _err:
2094	snd_config_delete(cfg);
2095	return err;
2096}
2097
2098/*
2099 * Parse variant information
2100 */
2101static int parse_variant(snd_use_case_mgr_t *uc_mgr, snd_config_t *cfg,
2102			 char **_vfile, char **_vcomment)
2103{
2104	snd_config_iterator_t i, next;
2105	snd_config_t *n;
2106	char *file = NULL, *comment = NULL;
2107	int err;
2108
2109	/* parse master config sections */
2110	snd_config_for_each(i, next, cfg) {
2111		const char *id;
2112		n = snd_config_iterator_entry(i);
2113		if (snd_config_get_id(n, &id) < 0)
2114			continue;
2115
2116		/* get use case verb file name */
2117		if (strcmp(id, "File") == 0) {
2118			if (_vfile) {
2119				err = parse_string_substitute3(uc_mgr, n, &file);
2120				if (err < 0) {
2121					uc_error("failed to get File");
2122					goto __error;
2123				}
2124			}
2125			continue;
2126		}
2127
2128		/* get optional use case comment */
2129		if (strncmp(id, "Comment", 7) == 0) {
2130			if (_vcomment) {
2131				err = parse_string_substitute3(uc_mgr, n, &comment);
2132				if (err < 0) {
2133					uc_error("error: failed to get Comment");
2134					goto __error;
2135				}
2136			}
2137			continue;
2138		}
2139
2140		uc_error("unknown field '%s' in Variant section", id);
2141		err = -EINVAL;
2142		goto __error;
2143	}
2144
2145	if (_vfile)
2146		*_vfile = file;
2147	if (_vcomment)
2148		*_vcomment = comment;
2149	return 0;
2150
2151__error:
2152	free(file);
2153	free(comment);
2154	return err;
2155}
2156
2157/*
2158 * Parse master section for "Use Case" and "File" tags.
2159 */
2160static int parse_master_section(snd_use_case_mgr_t *uc_mgr, snd_config_t *cfg,
2161				void *data1 ATTRIBUTE_UNUSED,
2162				void *data2 ATTRIBUTE_UNUSED)
2163{
2164	snd_config_iterator_t i, next;
2165	snd_config_t *n, *variant = NULL;
2166	char *use_case_name, *file = NULL, *comment = NULL;
2167	bool variant_ok = false;
2168	int err;
2169
2170	if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) {
2171		uc_error("compound type expected for use case section");
2172		return -EINVAL;
2173	}
2174
2175	err = parse_get_safe_name(uc_mgr, cfg, NULL, &use_case_name);
2176	if (err < 0) {
2177		uc_error("unable to get name for use case section");
2178		return err;
2179	}
2180
2181	/* in-place evaluation */
2182	uc_mgr->parse_master_section = 1;
2183	err = uc_mgr_evaluate_inplace(uc_mgr, cfg);
2184	uc_mgr->parse_master_section = 0;
2185	if (err < 0)
2186		goto __error;
2187
2188	/* parse master config sections */
2189	snd_config_for_each(i, next, cfg) {
2190		const char *id;
2191		n = snd_config_iterator_entry(i);
2192		if (snd_config_get_id(n, &id) < 0)
2193			continue;
2194
2195		/* get use case verb file name */
2196		if (strcmp(id, "File") == 0) {
2197			err = parse_string_substitute3(uc_mgr, n, &file);
2198			if (err < 0) {
2199				uc_error("failed to get File");
2200				goto __error;
2201			}
2202			continue;
2203		}
2204
2205		/* get optional use case comment */
2206		if (strncmp(id, "Comment", 7) == 0) {
2207			err = parse_string_substitute3(uc_mgr, n, &comment);
2208			if (err < 0) {
2209				uc_error("error: failed to get Comment");
2210				goto __error;
2211			}
2212			continue;
2213		}
2214
2215		if (uc_mgr->conf_format >= 6 && strcmp(id, "Variant") == 0) {
2216			snd_config_iterator_t i2, next2;
2217			variant = n;
2218			snd_config_for_each(i2, next2, n) {
2219				const char *id2;
2220				snd_config_t *n2;
2221				n2 = snd_config_iterator_entry(i2);
2222				if (snd_config_get_id(n2, &id2) < 0)
2223					continue;
2224				err = uc_mgr_evaluate_inplace(uc_mgr, n2);
2225				if (err < 0)
2226					goto __error;
2227				if (strcmp(use_case_name, id2) == 0)
2228					variant_ok = true;
2229			}
2230			continue;
2231		}
2232
2233		uc_error("unknown field '%s' in SectionUseCase", id);
2234	}
2235
2236	if (variant && !variant_ok) {
2237		uc_error("error: undefined variant '%s'", use_case_name);
2238		err = -EINVAL;
2239		goto __error;
2240	}
2241
2242	if (!variant) {
2243		uc_dbg("use_case_name %s file '%s'", use_case_name, file);
2244
2245		/* do we have both use case name and file ? */
2246		if (!file) {
2247			uc_error("error: use case missing file");
2248			err = -EINVAL;
2249			goto __error;
2250		}
2251
2252		/* parse verb file */
2253		err = parse_verb_file(uc_mgr, use_case_name, comment, file);
2254	} else {
2255		/* parse variants */
2256		snd_config_for_each(i, next, variant) {
2257			char *vfile, *vcomment;
2258			const char *id;
2259			n = snd_config_iterator_entry(i);
2260			if (snd_config_get_id(n, &id) < 0)
2261				continue;
2262			if (!parse_is_name_safe(id)) {
2263				err = -EINVAL;
2264				goto __error;
2265			}
2266			err = parse_variant(uc_mgr, n, &vfile, &vcomment);
2267			if (err < 0)
2268				break;
2269			uc_mgr->parse_variant = id;
2270			err = parse_verb_file(uc_mgr, id,
2271						vcomment ? vcomment : comment,
2272						vfile ? vfile : file);
2273			uc_mgr->parse_variant = NULL;
2274			free(vfile);
2275			free(vcomment);
2276		}
2277	}
2278
2279__error:
2280	free(use_case_name);
2281	free(file);
2282	free(comment);
2283	return err;
2284}
2285
2286/*
2287 * parse controls which should be run only at initial boot (forcefully)
2288 */
2289static int parse_controls_fixedboot(snd_use_case_mgr_t *uc_mgr, snd_config_t *cfg)
2290{
2291	int err;
2292
2293	if (!list_empty(&uc_mgr->fixedboot_list)) {
2294		uc_error("FixedBoot list is not empty");
2295		return -EINVAL;
2296	}
2297	err = parse_sequence(uc_mgr, &uc_mgr->fixedboot_list, cfg);
2298	if (err < 0) {
2299		uc_error("Unable to parse FixedBootSequence");
2300		return err;
2301	}
2302
2303	return 0;
2304}
2305
2306/*
2307 * parse controls which should be run only at initial boot
2308 */
2309static int parse_controls_boot(snd_use_case_mgr_t *uc_mgr, snd_config_t *cfg)
2310{
2311	int err;
2312
2313	if (!list_empty(&uc_mgr->boot_list)) {
2314		uc_error("Boot list is not empty");
2315		return -EINVAL;
2316	}
2317	err = parse_sequence(uc_mgr, &uc_mgr->boot_list, cfg);
2318	if (err < 0) {
2319		uc_error("Unable to parse BootSequence");
2320		return err;
2321	}
2322
2323	return 0;
2324}
2325
2326/*
2327 * parse controls
2328 */
2329static int parse_controls(snd_use_case_mgr_t *uc_mgr, snd_config_t *cfg)
2330{
2331	int err;
2332
2333	if (!list_empty(&uc_mgr->default_list)) {
2334		uc_error("Default list is not empty");
2335		return -EINVAL;
2336	}
2337	err = parse_sequence(uc_mgr, &uc_mgr->default_list, cfg);
2338	if (err < 0) {
2339		uc_error("Unable to parse SectionDefaults");
2340		return err;
2341	}
2342
2343	return 0;
2344}
2345
2346/*
2347 * Each sound card has a master sound card file that lists all the supported
2348 * use case verbs for that sound card. i.e.
2349 *
2350 * #Example master file for blah sound card
2351 * #By Joe Blogs <joe@bloggs.org>
2352 *
2353 * Comment "Nice Abstracted Soundcard"
2354 *
2355 * # The file is divided into Use case sections. One section per use case verb.
2356 *
2357 * SectionUseCase."Voice Call" {
2358 *	File "voice_call_blah"
2359 *	Comment "Make a voice phone call."
2360 * }
2361 *
2362 * SectionUseCase."HiFi" {
2363 *	File "hifi_blah"
2364 *	Comment "Play and record HiFi quality Music."
2365 * }
2366 *
2367 * # Define Value defaults
2368 *
2369 * ValueDefaults {
2370 *	PlaybackCTL "hw:CARD=0"
2371 *	CaptureCTL "hw:CARD=0"
2372 * }
2373 *
2374 * # The initial boot (run once) configuration.
2375 *
2376 * BootSequence [
2377 *      cset "name='Master Playback Switch',index=2 1,1"
2378 *	cset "name='Master Playback Volume',index=2 25,25"
2379 * ]
2380 *
2381 * # This file also stores the default sound card state.
2382 *
2383 * SectionDefaults [
2384 *	cset "name='Master Mono Playback',index=1 0"
2385 *	cset "name='Master Mono Playback Volume',index=1 0"
2386 *	cset "name='PCM Switch',index=2 1,1"
2387 *      exec "some binary here"
2388 *      msleep 50
2389 *	........
2390 * ]
2391 *
2392 * # End of example file.
2393 */
2394static int parse_master_file(snd_use_case_mgr_t *uc_mgr, snd_config_t *cfg)
2395{
2396	snd_config_iterator_t i, next;
2397	snd_config_t *n;
2398	const char *id;
2399	int err;
2400
2401	if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) {
2402		uc_error("compound type expected for master file");
2403		return -EINVAL;
2404	}
2405
2406	if (uc_mgr->conf_format >= 2) {
2407		err = parse_syntax_field(uc_mgr, cfg, uc_mgr->conf_file_name);
2408		if (err < 0)
2409			return err;
2410	}
2411
2412	/* in-place evaluation */
2413	err = uc_mgr_evaluate_inplace(uc_mgr, cfg);
2414	if (err < 0)
2415		return err;
2416
2417	/* parse master config sections */
2418	snd_config_for_each(i, next, cfg) {
2419
2420		n = snd_config_iterator_entry(i);
2421		if (snd_config_get_id(n, &id) < 0)
2422			continue;
2423
2424		if (strcmp(id, "Comment") == 0) {
2425			err = parse_string_substitute3(uc_mgr, n, &uc_mgr->comment);
2426			if (err < 0) {
2427				uc_error("error: failed to get master comment");
2428				return err;
2429			}
2430			continue;
2431		}
2432
2433		/* find use case section and parse it */
2434		if (strcmp(id, "SectionUseCase") == 0) {
2435			err = parse_compound(uc_mgr, n,
2436					     parse_master_section,
2437					     NULL, NULL);
2438			if (err < 0)
2439				return err;
2440			continue;
2441		}
2442
2443		/* find default control values section (force boot sequence only) */
2444		if (strcmp(id, "FixedBootSequence") == 0) {
2445			err = parse_controls_fixedboot(uc_mgr, n);
2446			if (err < 0)
2447				return err;
2448			continue;
2449		}
2450
2451		/* find default control values section (first boot only) */
2452		if (strcmp(id, "BootSequence") == 0) {
2453			err = parse_controls_boot(uc_mgr, n);
2454			if (err < 0)
2455				return err;
2456			continue;
2457		}
2458
2459		/* find default control values section and parse it */
2460		if (strcmp(id, "SectionDefaults") == 0) {
2461			err = parse_controls(uc_mgr, n);
2462			if (err < 0)
2463				return err;
2464			continue;
2465		}
2466
2467		/* get the default values */
2468		if (strcmp(id, "ValueDefaults") == 0) {
2469			err = parse_value(uc_mgr, &uc_mgr->value_list, n);
2470			if (err < 0) {
2471				uc_error("error: failed to parse ValueDefaults");
2472				return err;
2473			}
2474			continue;
2475		}
2476
2477		/* alsa-lib configuration */
2478		if (uc_mgr->conf_format > 3 && strcmp(id, "LibraryConfig") == 0) {
2479			err = parse_libconfig(uc_mgr, n);
2480			if (err < 0) {
2481				uc_error("error: failed to parse LibraryConfig");
2482				return err;
2483			}
2484			continue;
2485		}
2486
2487		/* error */
2488		if (strcmp(id, "Error") == 0)
2489			return error_node(uc_mgr, n);
2490
2491		/* skip further Syntax value updates (Include) */
2492		if (strcmp(id, "Syntax") == 0)
2493			continue;
2494
2495		uc_error("unknown master file field %s", id);
2496	}
2497	return 0;
2498}
2499
2500/* get the card info */
2501static int get_card_info(snd_use_case_mgr_t *mgr,
2502			 const char *ctl_name,
2503			 snd_ctl_card_info_t **info)
2504{
2505	struct ctl_list *ctl_list;
2506	int err;
2507
2508	err = uc_mgr_open_ctl(mgr, &ctl_list, ctl_name, 0);
2509	if (err < 0)
2510		return err;
2511
2512	if (info)
2513		*info = ctl_list->ctl_info;
2514	return err;
2515}
2516
2517/* find the card in the local machine */
2518static int get_by_card_name(snd_use_case_mgr_t *mgr, const char *card_name)
2519{
2520	int card, err;
2521	snd_ctl_card_info_t *info;
2522	const char *_driver, *_name, *_long_name;
2523
2524	snd_ctl_card_info_alloca(&info);
2525
2526	card = -1;
2527	if (snd_card_next(&card) < 0 || card < 0) {
2528		uc_error("no soundcards found...");
2529		return -1;
2530	}
2531
2532	while (card >= 0) {
2533		char name[32];
2534
2535		/* clear the list, keep the only one CTL device */
2536		uc_mgr_free_ctl_list(mgr);
2537
2538		sprintf(name, "hw:%d", card);
2539		err = get_card_info(mgr, name, &info);
2540
2541		if (err == 0) {
2542			_driver = snd_ctl_card_info_get_driver(info);
2543			_name = snd_ctl_card_info_get_name(info);
2544			_long_name = snd_ctl_card_info_get_longname(info);
2545			if (!strcmp(card_name, _driver) ||
2546			    !strcmp(card_name, _name) ||
2547			    !strcmp(card_name, _long_name))
2548				return 0;
2549		}
2550
2551		if (snd_card_next(&card) < 0) {
2552			uc_error("snd_card_next");
2553			break;
2554		}
2555	}
2556
2557	uc_mgr_free_ctl_list(mgr);
2558
2559	return -1;
2560}
2561
2562/* set the driver name and long name by the card ctl name */
2563static inline int get_by_card(snd_use_case_mgr_t *mgr, const char *ctl_name)
2564{
2565	return get_card_info(mgr, ctl_name, NULL);
2566}
2567
2568static int parse_toplevel_path(snd_use_case_mgr_t *uc_mgr,
2569			       char *filename,
2570			       snd_config_t *cfg)
2571{
2572	snd_config_iterator_t i, next, i2, next2;
2573	snd_config_t *n, *n2;
2574	const char *id;
2575	char *dir = NULL, *file = NULL, fn[PATH_MAX];
2576	struct stat64 st;
2577	long version;
2578	int err;
2579
2580	if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) {
2581		uc_error("compound type expected for UseCasePath node");
2582		return -EINVAL;
2583	}
2584
2585	/* parse use case path config sections */
2586	snd_config_for_each(i, next, cfg) {
2587		n = snd_config_iterator_entry(i);
2588
2589		if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) {
2590			uc_error("compound type expected for UseCasePath.something node");
2591			return -EINVAL;
2592		}
2593
2594			if (snd_config_get_id(n, &id) < 0)
2595				continue;
2596
2597		version = 2;
2598
2599		/* parse use case path config sections */
2600		snd_config_for_each(i2, next2, n) {
2601
2602			n2 = snd_config_iterator_entry(i2);
2603			if (snd_config_get_id(n2, &id) < 0)
2604				continue;
2605
2606			if (strcmp(id, "Version") == 0) {
2607				err = parse_integer_substitute(uc_mgr, n2, &version);
2608				if (err < 0) {
2609					uc_error("unable to parse UcmDirectory");
2610					goto __error;
2611				}
2612				if (version < 1 || version > 2) {
2613					uc_error("Version must be 1 or 2");
2614					err = -EINVAL;
2615					goto __error;
2616				}
2617				continue;
2618			}
2619
2620			if (strcmp(id, "Directory") == 0) {
2621				err = parse_string_substitute(uc_mgr, n2, &dir);
2622				if (err < 0) {
2623					uc_error("unable to parse Directory");
2624					goto __error;
2625				}
2626				continue;
2627			}
2628
2629			if (strcmp(id, "File") == 0) {
2630				err = parse_string_substitute(uc_mgr, n2, &file);
2631				if (err < 0) {
2632					uc_error("unable to parse File");
2633					goto __error;
2634				}
2635				continue;
2636			}
2637
2638			uc_error("unknown UseCasePath field %s", id);
2639		}
2640
2641		if (dir == NULL) {
2642			uc_error("Directory is not defined in %s!", filename);
2643			goto __next;
2644		}
2645		if (file == NULL) {
2646			uc_error("File is not defined in %s!", filename);
2647			goto __next;
2648		}
2649
2650		ucm_filename(fn, sizeof(fn), version, dir, file);
2651		if (access(fn, R_OK) == 0 && lstat64(fn, &st) == 0) {
2652			if (S_ISLNK(st.st_mode)) {
2653				ssize_t r;
2654				char *link, *dir2, *p;
2655
2656				link = malloc(PATH_MAX);
2657				if (link == NULL)
2658					goto __enomem;
2659				r = readlink(fn, link, PATH_MAX - 1);
2660				if (r <= 0) {
2661					free(link);
2662					goto __next;
2663				}
2664				link[r] = '\0';
2665				p = strrchr(link, '/');
2666				if (p) {
2667					*p = '\0';
2668					dir2 = malloc(PATH_MAX);
2669					if (dir2 == NULL) {
2670						free(link);
2671						goto __enomem;
2672					}
2673					strncpy(dir2, dir, PATH_MAX - 1);
2674					strncat(dir2, "/", PATH_MAX - 1);
2675					strncat(dir2, link, PATH_MAX - 1);
2676					fn[PATH_MAX - 1] = '\0';
2677					free(dir);
2678					dir = dir2;
2679				}
2680				free(link);
2681			}
2682			if (replace_string(&uc_mgr->conf_dir_name, dir) == NULL)
2683				goto __enomem;
2684			if (replace_string(&uc_mgr->conf_file_name, file) == NULL)
2685				goto __enomem;
2686			strncpy(filename, fn, PATH_MAX);
2687			filename[PATH_MAX - 1] = '\0';
2688			uc_mgr->conf_format = version;
2689			goto __ok;
2690		}
2691
2692__next:
2693		free(file);
2694		if (dir != fn)
2695			free(dir);
2696		dir = NULL;
2697		file = NULL;
2698	}
2699
2700	err = -ENOENT;
2701	goto __error;
2702
2703__enomem:
2704	err = -ENOMEM;
2705	goto __error;
2706
2707__ok:
2708	err = 0;
2709__error:
2710	free(file);
2711	if (dir != fn)
2712		free(dir);
2713	return err;
2714}
2715
2716static int parse_toplevel_config(snd_use_case_mgr_t *uc_mgr,
2717				 char *filename,
2718				 snd_config_t *cfg)
2719{
2720	snd_config_iterator_t i, next;
2721	snd_config_t *n;
2722	const char *id;
2723	int err;
2724
2725	if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) {
2726		uc_error("compound type expected for toplevel file");
2727		return -EINVAL;
2728	}
2729
2730	err = parse_syntax_field(uc_mgr, cfg, filename);
2731	if (err < 0)
2732		return err;
2733
2734	/* in-place evaluation */
2735	err = uc_mgr_evaluate_inplace(uc_mgr, cfg);
2736	if (err < 0)
2737		return err;
2738
2739	/* parse toplevel config sections */
2740	snd_config_for_each(i, next, cfg) {
2741
2742		n = snd_config_iterator_entry(i);
2743		if (snd_config_get_id(n, &id) < 0)
2744			continue;
2745
2746		if (strcmp(id, "UseCasePath") == 0) {
2747			err = parse_toplevel_path(uc_mgr, filename, n);
2748			if (err == 0)
2749				return err;
2750			continue;
2751		}
2752
2753		/* alsa-lib configuration */
2754		if (uc_mgr->conf_format > 3 && strcmp(id, "LibraryConfig") == 0) {
2755			err = parse_libconfig(uc_mgr, n);
2756			if (err < 0) {
2757				uc_error("error: failed to parse LibConfig");
2758				return err;
2759			}
2760			continue;
2761		}
2762
2763		/* skip further Syntax value updates (Include) */
2764		if (strcmp(id, "Syntax") == 0)
2765			continue;
2766
2767		uc_error("unknown toplevel field %s", id);
2768	}
2769
2770	return -ENOENT;
2771}
2772
2773static int load_toplevel_config(snd_use_case_mgr_t *uc_mgr,
2774				snd_config_t **cfg)
2775{
2776	char filename[PATH_MAX];
2777	snd_config_t *tcfg;
2778	int err;
2779
2780	ucm_filename(filename, sizeof(filename), 2, NULL, "ucm.conf");
2781
2782	if (access(filename, R_OK) != 0) {
2783		uc_error("Unable to find the top-level configuration file '%s'.", filename);
2784		return -ENOENT;
2785	}
2786
2787	err = uc_mgr_config_load(2, filename, &tcfg);
2788	if (err < 0)
2789		goto __error;
2790
2791	/* filename is shared for function input and output! */
2792	err = parse_toplevel_config(uc_mgr, filename, tcfg);
2793	snd_config_delete(tcfg);
2794	if (err < 0)
2795		goto __error;
2796
2797	err = uc_mgr_config_load(uc_mgr->conf_format, filename, cfg);
2798	if (err < 0) {
2799		uc_error("error: could not parse configuration for card %s",
2800				uc_mgr->card_name);
2801		goto __error;
2802	}
2803
2804	return 0;
2805
2806__error:
2807	return err;
2808}
2809
2810/* load master use case file for sound card based on rules in ucm2/ucm.conf
2811 */
2812int uc_mgr_import_master_config(snd_use_case_mgr_t *uc_mgr)
2813{
2814	snd_config_t *cfg;
2815	const char *name;
2816	int err;
2817
2818	err = snd_config_top(&uc_mgr->local_config);
2819	if (err < 0)
2820		return err;
2821
2822	err = snd_config_top(&uc_mgr->macros);
2823	if (err < 0)
2824		return err;
2825
2826	name = uc_mgr->card_name;
2827	if (strncmp(name, "hw:", 3) == 0) {
2828		err = get_by_card(uc_mgr, name);
2829		if (err < 0) {
2830			uc_error("card '%s' is not valid", name);
2831			goto __error;
2832		}
2833	} else if (strncmp(name, "strict:", 7)) {
2834		/* do not handle the error here */
2835		/* we can refer the virtual UCM config */
2836		get_by_card_name(uc_mgr, name);
2837	}
2838
2839	err = load_toplevel_config(uc_mgr, &cfg);
2840	if (err < 0)
2841		goto __error;
2842
2843	err = parse_master_file(uc_mgr, cfg);
2844	if (uc_mgr->macros) {
2845		snd_config_delete(uc_mgr->macros);
2846		uc_mgr->macros = NULL;
2847	}
2848	snd_config_delete(cfg);
2849	if (err < 0) {
2850		uc_mgr_free_ctl_list(uc_mgr);
2851		uc_mgr_free_verb(uc_mgr);
2852	}
2853
2854	return err;
2855
2856__error:
2857	uc_mgr_free_ctl_list(uc_mgr);
2858	replace_string(&uc_mgr->conf_dir_name, NULL);
2859	return err;
2860}
2861
2862static int filename_filter(const struct dirent64 *dirent)
2863{
2864	if (dirent == NULL)
2865		return 0;
2866	if (dirent->d_type == DT_DIR) {
2867		if (dirent->d_name[0] == '.') {
2868			if (dirent->d_name[1] == '\0')
2869				return 0;
2870			if (dirent->d_name[1] == '.' &&
2871			    dirent->d_name[2] == '\0')
2872				return 0;
2873		}
2874		return 1;
2875	}
2876	return 0;
2877}
2878
2879/* scan all cards and comments
2880 *
2881 * Cards are defined by machines. Each card/machine installs its UCM
2882 * configuration files in a subdirectory with the same name as the sound
2883 * card under /usr/share/alsa/ucm2. This function will scan all the card
2884 * directories and skip the component directories defined in the array
2885 * component_dir.
2886 */
2887int uc_mgr_scan_master_configs(const char **_list[])
2888{
2889	char filename[PATH_MAX], dfl[PATH_MAX], fn[FILENAME_MAX];
2890	char *env = getenv(ALSA_CONFIG_UCM2_VAR);
2891	snd_use_case_mgr_t *uc_mgr;
2892	const char **list, *d_name;
2893	char *s;
2894	snd_config_t *cfg, *c;
2895	int i, j, cnt, err, cards;
2896	long l;
2897	ssize_t ss;
2898	struct dirent64 **namelist;
2899
2900	i = -1;
2901	cards = 0;
2902	while (1) {
2903		err = snd_card_next(&i);
2904		if (err < 0)
2905			return err;
2906		if (i < 0)
2907			break;
2908		cards++;
2909	}
2910	cards += 4;	/* plug-and-play */
2911
2912	if (env)
2913		snprintf(filename, sizeof(filename), "%s/conf.virt.d", env);
2914	else
2915		snprintf(filename, sizeof(filename), "%s/ucm2/conf.virt.d",
2916			 snd_config_topdir());
2917
2918#if defined(_GNU_SOURCE) && !defined(__NetBSD__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__DragonFly__) && !defined(__sun) && !defined(__ANDROID__)
2919#define SORTFUNC	versionsort64
2920#else
2921#define SORTFUNC	alphasort64
2922#endif
2923	err = scandir64(filename, &namelist, filename_filter, SORTFUNC);
2924	if (err < 0) {
2925		err = -errno;
2926		uc_error("error: could not scan directory %s: %s",
2927				filename, strerror(-err));
2928		return err;
2929	}
2930	cnt = err;
2931
2932	dfl[0] = '\0';
2933	if (strlen(filename) + 8 < sizeof(filename)) {
2934		strcat(filename, "/default");
2935		ss = readlink(filename, dfl, sizeof(dfl)-1);
2936		if (ss >= 0) {
2937			dfl[ss] = '\0';
2938			dfl[sizeof(dfl)-1] = '\0';
2939			if (dfl[0] && dfl[strlen(dfl)-1] == '/')
2940				dfl[strlen(dfl)-1] = '\0';
2941		} else {
2942			dfl[0] = '\0';
2943		}
2944	}
2945
2946	j = 0;
2947	list = calloc(1, (cards + cnt) * 2 * sizeof(char *));
2948	if (list == NULL) {
2949		err = -ENOMEM;
2950		goto __err;
2951	}
2952
2953	i = -1;
2954	while (j / 2 < cards) {
2955		err = snd_card_next(&i);
2956		if (err < 0)
2957			goto __err;
2958		if (i < 0)
2959			break;
2960		snprintf(fn, sizeof(fn), "-hw:%d", i);
2961		err = snd_use_case_mgr_open(&uc_mgr, fn);
2962		if (err == -ENOENT || err == -ENXIO)
2963			continue;
2964		if (err < 0) {
2965			uc_error("Unable to open '%s': %s", fn, snd_strerror(err));
2966			goto __err;
2967		}
2968		err = snd_use_case_get(uc_mgr, "comment", (const char **)&s);
2969		if (err < 0) {
2970			err = snd_card_get_longname(i, &s);
2971			if (err < 0)
2972				goto __err;
2973		}
2974		snd_use_case_mgr_close(uc_mgr);
2975		list[j] = strdup(fn + 1);
2976		if (list[j] == NULL) {
2977			free(s);
2978			err = -ENOMEM;
2979			goto __err;
2980		}
2981		list[j + 1] = s;
2982		j += 2;
2983	}
2984
2985	for (i = 0; i < cnt; i++) {
2986
2987		d_name = namelist[i]->d_name;
2988
2989		snprintf(fn, sizeof(fn), "%s.conf", d_name);
2990		ucm_filename(filename, sizeof(filename), 2, d_name, fn);
2991#ifdef HAVE_EACCESS
2992		if (eaccess(filename, R_OK))
2993#else
2994		if (access(filename, R_OK))
2995#endif
2996			continue;
2997
2998		err = uc_mgr_config_load(2, filename, &cfg);
2999		if (err < 0)
3000			goto __err;
3001		err = snd_config_search(cfg, "Syntax", &c);
3002		if (err < 0) {
3003			uc_error("Syntax field not found in %s", d_name);
3004			snd_config_delete(cfg);
3005			continue;
3006		}
3007		err = snd_config_get_integer(c, &l);
3008		if (err < 0) {
3009			uc_error("Syntax field is invalid in %s", d_name);
3010			snd_config_delete(cfg);
3011			goto __err;
3012		}
3013		if (l < 2 || l > SYNTAX_VERSION_MAX) {
3014			uc_error("Incompatible syntax %d in %s", l, d_name);
3015			snd_config_delete(cfg);
3016			goto __err;
3017		}
3018		err = snd_config_search(cfg, "Comment", &c);
3019		if (err >= 0) {
3020			err = parse_string(c, (char **)&list[j+1]);
3021			if (err < 0) {
3022				snd_config_delete(cfg);
3023				goto __err;
3024			}
3025		}
3026		snd_config_delete(cfg);
3027		list[j] = strdup(d_name);
3028		if (list[j] == NULL) {
3029			err = -ENOMEM;
3030			goto __err;
3031		}
3032		if (strcmp(dfl, list[j]) == 0) {
3033			/* default to top */
3034			const char *save1 = list[j];
3035			const char *save2 = list[j + 1];
3036			memmove(list + 2, list, j * sizeof(char *));
3037			list[0] = save1;
3038			list[1] = save2;
3039		}
3040		j += 2;
3041	}
3042	err = 0;
3043
3044      __err:
3045	for (i = 0; i < cnt; i++)
3046		free(namelist[i]);
3047	free(namelist);
3048	if (err < 0) {
3049		for (i = 0; i < j; i++) {
3050			free((void *)list[i * 2]);
3051			free((void *)list[i * 2 + 1]);
3052		}
3053		free(list);
3054		return err;
3055	}
3056
3057	*_list = list;
3058	return j;
3059}
3060