OSDN Git Service

ucm: fix bad frees in get_list0 and get_list20
[android-x86/external-alsa-lib.git] / src / ucm / main.c
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 <ctype.h>
35 #include <stdarg.h>
36 #include <pthread.h>
37 #include <sys/stat.h>
38 #include <limits.h>
39
40 /*
41  * misc
42  */
43
44 static int get_value(snd_use_case_mgr_t *uc_mgr,
45                         const char *identifier,
46                         char **value,
47                         const char *mod_dev_name,
48                         const char *verb_name,
49                         int exact);
50 static int get_value1(snd_use_case_mgr_t *uc_mgr, char **value,
51                       struct list_head *value_list, const char *identifier);
52 static int get_value3(snd_use_case_mgr_t *uc_mgr,
53                       char **value,
54                       const char *identifier,
55                       struct list_head *value_list1,
56                       struct list_head *value_list2,
57                       struct list_head *value_list3);
58
59 static int execute_component_seq(snd_use_case_mgr_t *uc_mgr,
60                                  struct component_sequence *cmpt_seq,
61                                  struct list_head *value_list1,
62                                  struct list_head *value_list2,
63                                  struct list_head *value_list3,
64                                  char *cdev);
65
66 static int check_identifier(const char *identifier, const char *prefix)
67 {
68         int len;
69
70         len = strlen(prefix);
71         if (strncmp(identifier, prefix, len) != 0)
72                 return 0;
73
74         if (identifier[len] == 0 || identifier[len] == '/')
75                 return 1;
76
77         return 0;
78 }
79
80 static int list_count(struct list_head *list)
81 {
82         struct list_head *pos;
83         int count = 0;
84         
85         list_for_each(pos, list) {
86                 count += 1;
87         }
88         return count;
89 }
90
91 static int alloc_str_list(struct list_head *list, int mult, char **result[])
92 {
93         char **res;
94         int cnt;
95         
96         cnt = list_count(list) * mult;
97         if (cnt == 0) {
98                 *result = NULL;
99                 return cnt;
100         }
101         res = calloc(mult, cnt * sizeof(char *));
102         if (res == NULL)
103                 return -ENOMEM;
104         *result = res;
105         return cnt;
106 }
107
108 /**
109  * \brief Create an identifier
110  * \param fmt Format (sprintf like)
111  * \param ... Optional arguments for sprintf like format
112  * \return Allocated string identifier or NULL on error
113  */
114 char *snd_use_case_identifier(const char *fmt, ...)
115 {
116         char *str, *res;
117         int size = strlen(fmt) + 512;
118         va_list args;
119
120         str = malloc(size);
121         if (str == NULL)
122                 return NULL;
123         va_start(args, fmt);
124         vsnprintf(str, size, fmt, args);
125         va_end(args);
126         str[size-1] = '\0';
127         res = realloc(str, strlen(str) + 1);
128         if (res)
129                 return res;
130         return str;
131 }
132
133 /**
134  * \brief Free a string list
135  * \param list The string list to free
136  * \param items Count of strings
137  * \return Zero if success, otherwise a negative error code
138  */
139 int snd_use_case_free_list(const char *list[], int items)
140 {
141         int i;
142         if (list == NULL)
143                 return 0;
144         for (i = 0; i < items; i++)
145                 free((void *)list[i]);
146         free(list);
147         return 0;
148 }
149
150 static int read_tlv_file(unsigned int **res,
151                          const char *filepath)
152 {
153         int err = 0;
154         int fd;
155         struct stat st;
156         size_t sz;
157         ssize_t sz_read;
158         struct snd_ctl_tlv *tlv;
159
160         fd = open(filepath, O_RDONLY);
161         if (fd < 0) {
162                 err = -errno;
163                 return err;
164         }
165         if (fstat(fd, &st) == -1) {
166                 err = -errno;
167                 goto __fail;
168         }
169         sz = st.st_size;
170         if (sz > 16 * 1024 * 1024 || sz < 8 || sz % 4) {
171                 uc_error("File size should be less than 16 MB "
172                          "and multiple of 4");
173                 err = -EINVAL;
174                 goto __fail;
175         }
176         *res = malloc(sz);
177         if (res == NULL) {
178                 err = -ENOMEM;
179                 goto __fail;
180         }
181         sz_read = read(fd, *res, sz);
182         if (sz_read < 0 || (size_t)sz_read != sz) {
183                 err = -EIO;
184                 free(*res);
185                 *res = NULL;
186         }
187         /* Check if the tlv file specifies valid size. */
188         tlv = (struct snd_ctl_tlv *)(*res);
189         if (tlv->length + 2 * sizeof(unsigned int) != sz) {
190                 uc_error("Invalid tlv size: %d", tlv->length);
191                 err = -EINVAL;
192                 free(*res);
193                 *res = NULL;
194         }
195
196 __fail:
197         close(fd);
198         return err;
199 }
200
201 static int binary_file_parse(snd_ctl_elem_value_t *dst,
202                               snd_ctl_elem_info_t *info,
203                               const char *filepath)
204 {
205         int err = 0;
206         int fd;
207         struct stat st;
208         size_t sz;
209         ssize_t sz_read;
210         char *res;
211         snd_ctl_elem_type_t type;
212         unsigned int idx, count;
213
214         type = snd_ctl_elem_info_get_type(info);
215         if (type != SND_CTL_ELEM_TYPE_BYTES) {
216                 uc_error("only support byte type!");
217                 err = -EINVAL;
218                 return err;
219         }
220         fd = open(filepath, O_RDONLY);
221         if (fd < 0) {
222                 err = -errno;
223                 return err;
224         }
225         if (stat(filepath, &st) == -1) {
226                 err = -errno;
227                 goto __fail;
228         }
229         sz = st.st_size;
230         count = snd_ctl_elem_info_get_count(info);
231         if (sz != count || sz > sizeof(dst->value.bytes)) {
232                 uc_error("invalid parameter size %d!", sz);
233                 err = -EINVAL;
234                 goto __fail;
235         }
236         res = malloc(sz);
237         if (res == NULL) {
238                 err = -ENOMEM;
239                 goto __fail;
240         }
241         sz_read = read(fd, res, sz);
242         if (sz_read < 0 || (size_t)sz_read != sz) {
243                 err = -errno;
244                 goto __fail_read;
245         }
246         for (idx = 0; idx < sz; idx++)
247                 snd_ctl_elem_value_set_byte(dst, idx, *(res + idx));
248       __fail_read:
249         free(res);
250       __fail:
251         close(fd);
252         return err;
253 }
254
255 extern int __snd_ctl_ascii_elem_id_parse(snd_ctl_elem_id_t *dst,
256                                          const char *str,
257                                          const char **ret_ptr);
258
259 static int execute_cset(snd_ctl_t *ctl, const char *cset, unsigned int type)
260 {
261         const char *pos;
262         int err;
263         snd_ctl_elem_id_t *id;
264         snd_ctl_elem_value_t *value;
265         snd_ctl_elem_info_t *info;
266         unsigned int *res = NULL;
267
268         snd_ctl_elem_id_malloc(&id);
269         snd_ctl_elem_value_malloc(&value);
270         snd_ctl_elem_info_malloc(&info);
271
272         err = __snd_ctl_ascii_elem_id_parse(id, cset, &pos);
273         if (err < 0)
274                 goto __fail;
275         while (*pos && isspace(*pos))
276                 pos++;
277         if (!*pos) {
278                 uc_error("undefined value for cset >%s<", cset);
279                 err = -EINVAL;
280                 goto __fail;
281         }
282         snd_ctl_elem_info_set_id(info, id);
283         err = snd_ctl_elem_info(ctl, info);
284         if (err < 0)
285                 goto __fail;
286         if (type == SEQUENCE_ELEMENT_TYPE_CSET_TLV) {
287                 if (!snd_ctl_elem_info_is_tlv_writable(info)) {
288                         err = -EINVAL;
289                         goto __fail;
290                 }
291                 err = read_tlv_file(&res, pos);
292                 if (err < 0)
293                         goto __fail;
294                 err = snd_ctl_elem_tlv_write(ctl, id, res);
295                 if (err < 0)
296                         goto __fail;
297         } else {
298                 snd_ctl_elem_value_set_id(value, id);
299                 err = snd_ctl_elem_read(ctl, value);
300                 if (err < 0)
301                         goto __fail;
302                 if (type == SEQUENCE_ELEMENT_TYPE_CSET_BIN_FILE)
303                         err = binary_file_parse(value, info, pos);
304                 else
305                         err = snd_ctl_ascii_value_parse(ctl, value, info, pos);
306                 if (err < 0)
307                         goto __fail;
308                 err = snd_ctl_elem_write(ctl, value);
309                 if (err < 0)
310                         goto __fail;
311         }
312         err = 0;
313       __fail:
314         if (id != NULL)
315                 free(id);
316         if (value != NULL)
317                 free(value);
318         if (info != NULL)
319                 free(info);
320         if (res != NULL)
321                 free(res);
322
323         return err;
324 }
325
326 /**
327  * \brief Execute the sequence
328  * \param uc_mgr Use case manager
329  * \param seq Sequence
330  * \return zero on success, otherwise a negative error code
331  */
332 static int execute_sequence(snd_use_case_mgr_t *uc_mgr,
333                             struct list_head *seq,
334                             struct list_head *value_list1,
335                             struct list_head *value_list2,
336                             struct list_head *value_list3)
337 {
338         struct list_head *pos;
339         struct sequence_element *s;
340         char *cdev = NULL;
341         snd_ctl_t *ctl = NULL;
342         struct ctl_list *ctl_list;
343         int err = 0;
344
345         list_for_each(pos, seq) {
346                 s = list_entry(pos, struct sequence_element, list);
347                 switch (s->type) {
348                 case SEQUENCE_ELEMENT_TYPE_CDEV:
349                         cdev = strdup(s->data.cdev);
350                         if (cdev == NULL)
351                                 goto __fail_nomem;
352                         break;
353                 case SEQUENCE_ELEMENT_TYPE_CSET:
354                 case SEQUENCE_ELEMENT_TYPE_CSET_BIN_FILE:
355                 case SEQUENCE_ELEMENT_TYPE_CSET_TLV:
356                         if (cdev == NULL && uc_mgr->in_component_domain) {
357                                 /* For sequence of a component device, use
358                                  * its parent's cdev stored by ucm manager.
359                                  */
360                                 if (uc_mgr->cdev == NULL) {
361                                         uc_error("cdev is not defined!");
362                                         return err;
363                                 }
364
365                                 cdev = strndup(uc_mgr->cdev, PATH_MAX);
366                                 if (!cdev)
367                                         return -ENOMEM;
368                         } else if (cdev == NULL) {
369                                 char *playback_ctl = NULL;
370                                 char *capture_ctl = NULL;
371
372                                 err = get_value3(uc_mgr, &playback_ctl, "PlaybackCTL",
373                                                  value_list1,
374                                                  value_list2,
375                                                  value_list3);
376                                 if (err < 0 && err != -ENOENT) {
377                                         uc_error("cdev is not defined!");
378                                         return err;
379                                 }
380                                 err = get_value3(uc_mgr, &capture_ctl, "CaptureCTL",
381                                                  value_list1,
382                                                  value_list2,
383                                                  value_list3);
384                                 if (err < 0 && err != -ENOENT) {
385                                         free(playback_ctl);
386                                         uc_error("cdev is not defined!");
387                                         return err;
388                                 }
389                                 if (playback_ctl == NULL &&
390                                     capture_ctl == NULL) {
391                                         uc_error("cdev is not defined!");
392                                         return -EINVAL;
393                                 }
394                                 if (playback_ctl != NULL &&
395                                     capture_ctl != NULL &&
396                                     strcmp(playback_ctl, capture_ctl) != 0) {
397                                         free(playback_ctl);
398                                         free(capture_ctl);
399                                         uc_error("cdev is not equal for playback and capture!");
400                                         return -EINVAL;
401                                 }
402                                 if (playback_ctl != NULL) {
403                                         cdev = playback_ctl;
404                                         free(capture_ctl);
405                                 } else {
406                                         cdev = capture_ctl;
407                                 }
408                         }
409                         if (ctl == NULL) {
410                                 err = uc_mgr_open_ctl(uc_mgr, &ctl_list, cdev, 1);
411                                 if (err < 0) {
412                                         uc_error("unable to open ctl device '%s'", cdev);
413                                         goto __fail;
414                                 }
415                                 ctl = ctl_list->ctl;
416                         }
417                         err = execute_cset(ctl, s->data.cset, s->type);
418                         if (err < 0) {
419                                 uc_error("unable to execute cset '%s'", s->data.cset);
420                                 goto __fail;
421                         }
422                         break;
423                 case SEQUENCE_ELEMENT_TYPE_SLEEP:
424                         usleep(s->data.sleep);
425                         break;
426                 case SEQUENCE_ELEMENT_TYPE_EXEC:
427                         err = system(s->data.exec);
428                         if (err < 0)
429                                 goto __fail;
430                         break;
431                 case SEQUENCE_ELEMENT_TYPE_CMPT_SEQ:
432                         /* Execute enable or disable sequence of a component
433                          * device. Pass the cdev defined by the machine device.
434                          */
435                         err = execute_component_seq(uc_mgr,
436                                                     &s->data.cmpt_seq,
437                                                     value_list1,
438                                                     value_list2,
439                                                     value_list3,
440                                                     cdev);
441                         if (err < 0)
442                                 goto __fail;
443                         break;
444                 default:
445                         uc_error("unknown sequence command %i", s->type);
446                         break;
447                 }
448         }
449         free(cdev);
450         return 0;
451       __fail_nomem:
452         err = -ENOMEM;
453       __fail:
454         free(cdev);
455         return err;
456
457 }
458
459 /* Execute enable or disable sequence of a component device.
460  *
461  * For a component device (a codec or embedded DSP), its sequence doesn't
462  * specify the sound card device 'cdev', because a component can be reused
463  * by different sound cards (machines). So when executing its sequence, a
464  * parameter 'cdev' is used to pass cdev defined by the sequence of its
465  * parent, the machine device. UCM manger will store the cdev when entering
466  * the component domain.
467  */
468 static int execute_component_seq(snd_use_case_mgr_t *uc_mgr,
469                                  struct component_sequence *cmpt_seq,
470                                  struct list_head *value_list1 ATTRIBUTE_UNUSED,
471                                  struct list_head *value_list2 ATTRIBUTE_UNUSED,
472                                  struct list_head *value_list3 ATTRIBUTE_UNUSED,
473                                  char *cdev)
474 {
475         struct use_case_device *device = cmpt_seq->device;
476         struct list_head *seq;
477         int err;
478
479         /* enter component domain and store cdev for the component */
480         uc_mgr->in_component_domain = 1;
481         uc_mgr->cdev = cdev;
482
483         /* choose enable or disable sequence of the component device */
484         if (cmpt_seq->enable)
485                 seq = &device->enable_list;
486         else
487                 seq = &device->disable_list;
488
489         /* excecute the sequence of the component dev */
490         err = execute_sequence(uc_mgr, seq,
491                                &device->value_list,
492                                &uc_mgr->active_verb->value_list,
493                                &uc_mgr->value_list);
494
495         /* exit component domain and clear cdev */
496         uc_mgr->in_component_domain = 0;
497         uc_mgr->cdev = NULL;
498
499         return err;
500 }
501
502 static int add_auto_value(snd_use_case_mgr_t *uc_mgr, const char *key, char *value)
503 {
504         char *s;
505         int err;
506
507         err = get_value1(uc_mgr, &value, &uc_mgr->value_list, key);
508         if (err == -ENOENT) {
509                 s = strdup(value);
510                 if (s == NULL)
511                         return -ENOMEM;
512                 return uc_mgr_add_value(&uc_mgr->value_list, key, s);
513         } else if (err < 0) {
514                 return err;
515         }
516         free(value);
517         return 0;
518 }
519
520 static int add_auto_values(snd_use_case_mgr_t *uc_mgr)
521 {
522         struct ctl_list *ctl_list;
523         const char *id;
524         char buf[40];
525         int err;
526
527         ctl_list = uc_mgr_get_master_ctl(uc_mgr);
528         if (ctl_list) {
529                 id = snd_ctl_card_info_get_id(ctl_list->ctl_info);
530                 snprintf(buf, sizeof(buf), "hw:%s", id);
531                 err = add_auto_value(uc_mgr, "PlaybackCTL", buf);
532                 if (err < 0)
533                         return err;
534                 err = add_auto_value(uc_mgr, "CaptureCTL", buf);
535                 if (err < 0)
536                         return err;
537         }
538         return 0;
539 }
540
541 /**
542  * \brief execute default commands
543  * \param uc_mgr Use case manager
544  * \return zero on success, otherwise a negative error code
545  */
546 static int set_defaults(snd_use_case_mgr_t *uc_mgr)
547 {
548         int err;
549
550         if (uc_mgr->default_list_executed)
551                 return 0;
552         err = execute_sequence(uc_mgr, &uc_mgr->default_list,
553                                &uc_mgr->value_list, NULL, NULL);
554         if (err < 0) {
555                 uc_error("Unable to execute default sequence");
556                 return err;
557         }
558         uc_mgr->default_list_executed = 1;
559         return 0;
560 }
561
562 /**
563  * \brief Import master config and execute the default sequence
564  * \param uc_mgr Use case manager
565  * \return zero on success, otherwise a negative error code
566  */
567 static int import_master_config(snd_use_case_mgr_t *uc_mgr)
568 {
569         int err;
570         
571         err = uc_mgr_import_master_config(uc_mgr);
572         if (err < 0)
573                 return err;
574         return add_auto_values(uc_mgr);
575 }
576
577 /**
578  * \brief Check, if the UCM configuration is empty
579  * \param uc_mgr Use case Manager
580  * \return zero on success, otherwise a negative error code
581  */
582 static int check_empty_configuration(snd_use_case_mgr_t *uc_mgr)
583 {
584         int err;
585         char *value;
586
587         err = get_value(uc_mgr, "Linked", &value, NULL, NULL, 1);
588         if (err >= 0) {
589                 err = strcasecmp(value, "true") == 0 ||
590                       strcmp(value, "1") == 0;
591                 free(value);
592                 if (err)
593                         return 0;
594         }
595         if (!list_empty(&uc_mgr->verb_list))
596                 return 0;
597         if (!list_empty(&uc_mgr->boot_list))
598                 return 0;
599         return -ENXIO;
600 }
601
602 /**
603  * \brief Universal find - string in a list
604  * \param list List of structures
605  * \param offset Offset of list structure
606  * \param soffset Offset of string structure
607  * \param match String to match
608  * \return structure on success, otherwise a NULL (not found)
609  */
610 static void *find0(struct list_head *list,
611                    unsigned long offset,
612                    unsigned long soffset,
613                    const char *match)
614 {
615         struct list_head *pos;
616         char *ptr, *str;
617
618         list_for_each(pos, list) {
619                 ptr = list_entry_offset(pos, char, offset);
620                 str = *((char **)(ptr + soffset));
621                 if (strcmp(str, match) == 0)
622                         return ptr;
623         }
624         return NULL;
625 }
626
627 #define find(list, type, member, value, match) \
628         find0(list, (unsigned long)(&((type *)0)->member), \
629                     (unsigned long)(&((type *)0)->value), match)
630
631 /**
632  * \brief Universal string list
633  * \param list List of structures
634  * \param result Result list
635  * \param offset Offset of list structure
636  * \param s1offset Offset of string structure
637  * \return count of items on success, otherwise a negative error code
638  */
639 static int get_list0(struct list_head *list,
640                      const char **result[],
641                      unsigned long offset,
642                      unsigned long s1offset)
643 {
644         char **res;
645         int cnt;
646         struct list_head *pos;
647         char *ptr, *str1;
648
649         cnt = alloc_str_list(list, 1, &res);
650         if (cnt <= 0) {
651                 *result = NULL;
652                 return cnt;
653         }
654         *result = (const char **)res;
655         list_for_each(pos, list) {
656                 ptr = list_entry_offset(pos, char, offset);
657                 str1 = *((char **)(ptr + s1offset));
658                 if (str1 != NULL) {
659                         *res = strdup(str1);
660                         if (*res == NULL)
661                                 goto __fail;
662                 } else {
663                         *res = NULL;
664                 }
665                 res++;
666         }
667         return cnt;
668       __fail:
669         snd_use_case_free_list(*result, cnt);
670         return -ENOMEM;
671 }
672
673 #define get_list(list, result, type, member, s1) \
674         get_list0(list, result, \
675                     (unsigned long)(&((type *)0)->member), \
676                     (unsigned long)(&((type *)0)->s1))
677
678 /**
679  * \brief Universal string list - pair of strings
680  * \param list List of structures
681  * \param result Result list
682  * \param offset Offset of list structure
683  * \param s1offset Offset of string structure
684  * \param s1offset Offset of string structure
685  * \return count of items on success, otherwise a negative error code
686  */
687 static int get_list20(struct list_head *list,
688                       const char **result[],
689                       unsigned long offset,
690                       unsigned long s1offset,
691                       unsigned long s2offset)
692 {
693         char **res;
694         int cnt;
695         struct list_head *pos;
696         char *ptr, *str1, *str2;
697
698         cnt = alloc_str_list(list, 2, &res);
699         if (cnt <= 0) {
700                 *result = NULL;
701                 return cnt;
702         }
703         *result = (const char **)res;
704         list_for_each(pos, list) {
705                 ptr = list_entry_offset(pos, char, offset);
706                 str1 = *((char **)(ptr + s1offset));
707                 if (str1 != NULL) {
708                         *res = strdup(str1);
709                         if (*res == NULL)
710                                 goto __fail;
711                 } else {
712                         *res = NULL;
713                 }
714                 res++;
715                 str2 = *((char **)(ptr + s2offset));
716                 if (str2 != NULL) {
717                         *res = strdup(str2);
718                         if (*res == NULL)
719                                 goto __fail;
720                 } else {
721                         *res = NULL;
722                 }
723                 res++;
724         }
725         return cnt;
726       __fail:
727         snd_use_case_free_list(*result, cnt);
728         return -ENOMEM;
729 }
730
731 #define get_list2(list, result, type, member, s1, s2) \
732         get_list20(list, result, \
733                     (unsigned long)(&((type *)0)->member), \
734                     (unsigned long)(&((type *)0)->s1), \
735                     (unsigned long)(&((type *)0)->s2))
736
737 /**
738  * \brief Find verb
739  * \param uc_mgr Use case manager
740  * \param verb_name verb to find
741  * \return structure on success, otherwise a NULL (not found)
742  */
743 static inline struct use_case_verb *find_verb(snd_use_case_mgr_t *uc_mgr,
744                                               const char *verb_name)
745 {
746         return find(&uc_mgr->verb_list,
747                     struct use_case_verb, list, name,
748                     verb_name);
749 }
750
751 static int is_devlist_supported(snd_use_case_mgr_t *uc_mgr, 
752         struct dev_list *dev_list)
753 {
754         struct dev_list_node *device;
755         struct use_case_device *adev;
756         struct list_head *pos, *pos1;
757         int found_ret;
758
759         switch (dev_list->type) {
760         case DEVLIST_NONE:
761         default:
762                 return 1;
763         case DEVLIST_SUPPORTED:
764                 found_ret = 1;
765                 break;
766         case DEVLIST_CONFLICTING:
767                 found_ret = 0;
768                 break;
769         }
770
771         list_for_each(pos, &dev_list->list) {
772                 device = list_entry(pos, struct dev_list_node, list);
773
774                 list_for_each(pos1, &uc_mgr->active_devices) {
775                         adev = list_entry(pos1, struct use_case_device,
776                                             active_list);
777                         if (!strcmp(device->name, adev->name))
778                                 return found_ret;
779                 }
780         }
781         return 1 - found_ret;
782 }
783
784 static inline int is_modifier_supported(snd_use_case_mgr_t *uc_mgr, 
785         struct use_case_modifier *modifier)
786 {
787         return is_devlist_supported(uc_mgr, &modifier->dev_list);
788 }
789
790 static inline int is_device_supported(snd_use_case_mgr_t *uc_mgr, 
791         struct use_case_device *device)
792 {
793         return is_devlist_supported(uc_mgr, &device->dev_list);
794 }
795
796 /**
797  * \brief Find device
798  * \param verb Use case verb
799  * \param device_name device to find
800  * \return structure on success, otherwise a NULL (not found)
801  */
802 static inline struct use_case_device *
803         find_device(snd_use_case_mgr_t *uc_mgr, struct use_case_verb *verb,
804                     const char *device_name, int check_supported)
805 {
806         struct use_case_device *device;
807         struct list_head *pos;
808
809         list_for_each(pos, &verb->device_list) {
810                 device = list_entry(pos, struct use_case_device, list);
811
812                 if (strcmp(device_name, device->name))
813                         continue;
814
815                 if (check_supported &&
816                     !is_device_supported(uc_mgr, device))
817                         continue;
818
819                 return device;
820         }
821         return NULL;
822 }
823
824 /**
825  * \brief Find modifier
826  * \param verb Use case verb
827  * \param modifier_name modifier to find
828  * \return structure on success, otherwise a NULL (not found)
829  */
830 static struct use_case_modifier *
831         find_modifier(snd_use_case_mgr_t *uc_mgr, struct use_case_verb *verb,
832                       const char *modifier_name, int check_supported)
833 {
834         struct use_case_modifier *modifier;
835         struct list_head *pos;
836
837         list_for_each(pos, &verb->modifier_list) {
838                 modifier = list_entry(pos, struct use_case_modifier, list);
839
840                 if (strcmp(modifier->name, modifier_name))
841                         continue;
842
843                 if (check_supported &&
844                     !is_modifier_supported(uc_mgr, modifier))
845                         continue;
846
847                 return modifier;
848         }
849         return NULL;
850 }
851
852 long device_status(snd_use_case_mgr_t *uc_mgr,
853                    const char *device_name)
854 {
855         struct use_case_device *dev;
856         struct list_head *pos;
857
858         list_for_each(pos, &uc_mgr->active_devices) {
859                 dev = list_entry(pos, struct use_case_device, active_list);
860                 if (strcmp(dev->name, device_name) == 0)
861                         return 1;
862         }
863         return 0;
864 }
865
866 long modifier_status(snd_use_case_mgr_t *uc_mgr,
867                      const char *modifier_name)
868 {
869         struct use_case_modifier *mod;
870         struct list_head *pos;
871
872         list_for_each(pos, &uc_mgr->active_modifiers) {
873                 mod = list_entry(pos, struct use_case_modifier, active_list);
874                 if (strcmp(mod->name, modifier_name) == 0)
875                         return 1;
876         }
877         return 0;
878 }
879
880 /**
881  * \brief Set verb
882  * \param uc_mgr Use case manager
883  * \param verb verb to set
884  * \param enable nonzero = enable, zero = disable
885  * \return zero on success, otherwise a negative error code
886  */
887 static int set_verb(snd_use_case_mgr_t *uc_mgr,
888                     struct use_case_verb *verb,
889                     int enable)
890 {
891         struct list_head *seq;
892         int err;
893
894         if (enable) {
895                 err = set_defaults(uc_mgr);
896                 if (err < 0)
897                         return err;
898                 seq = &verb->enable_list;
899         } else {
900                 seq = &verb->disable_list;
901         }
902         err = execute_sequence(uc_mgr, seq,
903                                &verb->value_list,
904                                &uc_mgr->value_list,
905                                NULL);
906         if (enable && err >= 0)
907                 uc_mgr->active_verb = verb;
908         return err;
909 }
910
911 /**
912  * \brief Set modifier
913  * \param uc_mgr Use case manager
914  * \param modifier modifier to set
915  * \param enable nonzero = enable, zero = disable
916  * \return zero on success, otherwise a negative error code
917  */
918 static int set_modifier(snd_use_case_mgr_t *uc_mgr,
919                         struct use_case_modifier *modifier,
920                         int enable)
921 {
922         struct list_head *seq;
923         int err;
924
925         if (modifier_status(uc_mgr, modifier->name) == enable)
926                 return 0;
927
928         if (enable) {
929                 seq = &modifier->enable_list;
930         } else {
931                 seq = &modifier->disable_list;
932         }
933         err = execute_sequence(uc_mgr, seq,
934                                &modifier->value_list,
935                                &uc_mgr->active_verb->value_list,
936                                &uc_mgr->value_list);
937         if (enable && err >= 0) {
938                 list_add_tail(&modifier->active_list, &uc_mgr->active_modifiers);
939         } else if (!enable) {
940                 list_del(&modifier->active_list);
941         }
942         return err;
943 }
944
945 /**
946  * \brief Set device
947  * \param uc_mgr Use case manager
948  * \param device device to set
949  * \param enable nonzero = enable, zero = disable
950  * \return zero on success, otherwise a negative error code
951  */
952 static int set_device(snd_use_case_mgr_t *uc_mgr,
953                       struct use_case_device *device,
954                       int enable)
955 {
956         struct list_head *seq;
957         int err;
958
959         if (device_status(uc_mgr, device->name) == enable)
960                 return 0;
961
962         if (enable) {
963                 seq = &device->enable_list;
964         } else {
965                 seq = &device->disable_list;
966         }
967         err = execute_sequence(uc_mgr, seq,
968                                &device->value_list,
969                                &uc_mgr->active_verb->value_list,
970                                &uc_mgr->value_list);
971         if (enable && err >= 0) {
972                 list_add_tail(&device->active_list, &uc_mgr->active_devices);
973         } else if (!enable) {
974                 list_del(&device->active_list);
975         }
976         return err;
977 }
978
979 /**
980  * \brief Init sound card use case manager.
981  * \param uc_mgr Returned use case manager pointer
982  * \param card_name name of card to open
983  * \return zero on success, otherwise a negative error code
984  */
985 int snd_use_case_mgr_open(snd_use_case_mgr_t **uc_mgr,
986                           const char *card_name)
987 {
988         snd_use_case_mgr_t *mgr;
989         int err;
990
991         /* create a new UCM */
992         mgr = calloc(1, sizeof(snd_use_case_mgr_t));
993         if (mgr == NULL)
994                 return -ENOMEM;
995         INIT_LIST_HEAD(&mgr->verb_list);
996         INIT_LIST_HEAD(&mgr->boot_list);
997         INIT_LIST_HEAD(&mgr->default_list);
998         INIT_LIST_HEAD(&mgr->value_list);
999         INIT_LIST_HEAD(&mgr->active_modifiers);
1000         INIT_LIST_HEAD(&mgr->active_devices);
1001         INIT_LIST_HEAD(&mgr->ctl_list);
1002         INIT_LIST_HEAD(&mgr->variable_list);
1003         pthread_mutex_init(&mgr->mutex, NULL);
1004
1005         mgr->card_name = strdup(card_name);
1006         if (mgr->card_name == NULL) {
1007                 free(mgr);
1008                 return -ENOMEM;
1009         }
1010
1011         /* get info on use_cases and verify against card */
1012         err = import_master_config(mgr);
1013         if (err < 0) {
1014                 uc_error("error: failed to import %s use case configuration %d",
1015                          card_name, err);
1016                 goto _err;
1017         }
1018
1019         err = check_empty_configuration(mgr);
1020         if (err < 0) {
1021                 uc_error("error: failed to import %s (empty configuration)", card_name);
1022                 goto _err;
1023         }
1024
1025         *uc_mgr = mgr;
1026         return 0;
1027
1028 _err:
1029         uc_mgr_free(mgr);
1030         return err;
1031 }
1032
1033 /**
1034  * \brief Reload and reparse all use case files.
1035  * \param uc_mgr Use case manager
1036  * \return zero on success, otherwise a negative error code
1037  */
1038 int snd_use_case_mgr_reload(snd_use_case_mgr_t *uc_mgr)
1039 {
1040         int err;
1041
1042         pthread_mutex_lock(&uc_mgr->mutex);
1043
1044         uc_mgr_free_verb(uc_mgr);
1045
1046         uc_mgr->default_list_executed = 0;
1047
1048         /* reload all use cases */
1049         err = import_master_config(uc_mgr);
1050         if (err < 0) {
1051                 uc_error("error: failed to reload use cases");
1052                 pthread_mutex_unlock(&uc_mgr->mutex);
1053                 return -EINVAL;
1054         }
1055
1056         pthread_mutex_unlock(&uc_mgr->mutex);
1057         return err;
1058 }
1059
1060 /**
1061  * \brief Close use case manager.
1062  * \param uc_mgr Use case manager
1063  * \return zero on success, otherwise a negative error code
1064  */
1065 int snd_use_case_mgr_close(snd_use_case_mgr_t *uc_mgr)
1066 {
1067         uc_mgr_free(uc_mgr);
1068
1069         return 0;
1070 }
1071
1072 /*
1073  * Tear down current use case verb, device and modifier.
1074  */
1075 static int dismantle_use_case(snd_use_case_mgr_t *uc_mgr)
1076 {
1077         struct list_head *pos, *npos;
1078         struct use_case_modifier *modifier;
1079         struct use_case_device *device;
1080         int err;
1081
1082         list_for_each_safe(pos, npos, &uc_mgr->active_modifiers) {
1083                 modifier = list_entry(pos, struct use_case_modifier,
1084                                       active_list);
1085                 err = set_modifier(uc_mgr, modifier, 0);
1086                 if (err < 0)
1087                         uc_error("Unable to disable modifier %s", modifier->name);
1088         }
1089         INIT_LIST_HEAD(&uc_mgr->active_modifiers);
1090
1091         list_for_each_safe(pos, npos, &uc_mgr->active_devices) {
1092                 device = list_entry(pos, struct use_case_device,
1093                                     active_list);
1094                 err = set_device(uc_mgr, device, 0);
1095                 if (err < 0)
1096                         uc_error("Unable to disable device %s", device->name);
1097         }
1098         INIT_LIST_HEAD(&uc_mgr->active_devices);
1099
1100         err = set_verb(uc_mgr, uc_mgr->active_verb, 0);
1101         if (err < 0) {
1102                 uc_error("Unable to disable verb %s", uc_mgr->active_verb->name);
1103                 return err;
1104         }
1105         uc_mgr->active_verb = NULL;
1106
1107         err = execute_sequence(uc_mgr, &uc_mgr->default_list,
1108                                &uc_mgr->value_list, NULL, NULL);
1109         
1110         return err;
1111 }
1112
1113 /**
1114  * \brief Reset sound card controls to default values.
1115  * \param uc_mgr Use case manager
1116  * \return zero on success, otherwise a negative error code
1117  */
1118 int snd_use_case_mgr_reset(snd_use_case_mgr_t *uc_mgr)
1119 {
1120         int err;
1121
1122         pthread_mutex_lock(&uc_mgr->mutex);
1123         err = execute_sequence(uc_mgr, &uc_mgr->default_list,
1124                                &uc_mgr->value_list, NULL, NULL);
1125         INIT_LIST_HEAD(&uc_mgr->active_modifiers);
1126         INIT_LIST_HEAD(&uc_mgr->active_devices);
1127         uc_mgr->active_verb = NULL;
1128         pthread_mutex_unlock(&uc_mgr->mutex);
1129         return err;
1130 }
1131
1132 /**
1133  * \brief Get list of verbs in pair verbname+comment
1134  * \param list Returned list
1135  * \return Number of list entries if success, otherwise a negative error code
1136  */
1137 static int get_verb_list(snd_use_case_mgr_t *uc_mgr, const char **list[])
1138 {
1139         return get_list2(&uc_mgr->verb_list, list,
1140                          struct use_case_verb, list,
1141                          name, comment);
1142 }
1143
1144 /**
1145  * \brief Get list of devices in pair devicename+comment
1146  * \param list Returned list
1147  * \param verbname For verb (NULL = current)
1148  * \return Number of list entries if success, otherwise a negative error code
1149  */
1150 static int get_device_list(snd_use_case_mgr_t *uc_mgr, const char **list[],
1151                            char *verbname)
1152 {
1153         struct use_case_verb *verb;
1154         
1155         if (verbname) {
1156                 verb = find_verb(uc_mgr, verbname);
1157         } else {
1158                 verb = uc_mgr->active_verb;
1159         }
1160         if (verb == NULL)
1161                 return -ENOENT;
1162         return get_list2(&verb->device_list, list,
1163                          struct use_case_device, list,
1164                          name, comment);
1165 }
1166
1167 /**
1168  * \brief Get list of modifiers in pair devicename+comment
1169  * \param list Returned list
1170  * \param verbname For verb (NULL = current)
1171  * \return Number of list entries if success, otherwise a negative error code
1172  */
1173 static int get_modifier_list(snd_use_case_mgr_t *uc_mgr, const char **list[],
1174                              char *verbname)
1175 {
1176         struct use_case_verb *verb;
1177         
1178         if (verbname) {
1179                 verb = find_verb(uc_mgr, verbname);
1180         } else {
1181                 verb = uc_mgr->active_verb;
1182         }
1183         if (verb == NULL)
1184                 return -ENOENT;
1185         return get_list2(&verb->modifier_list, list,
1186                          struct use_case_modifier, list,
1187                          name, comment);
1188 }
1189
1190 /**
1191  * \brief Get list of supported/conflicting devices
1192  * \param list Returned list
1193  * \param name Name of modifier or verb to query
1194  * \param type Type of device list entries to return
1195  * \return Number of list entries if success, otherwise a negative error code
1196  */
1197 static int get_supcon_device_list(snd_use_case_mgr_t *uc_mgr,
1198                                   const char **list[], char *name,
1199                                   enum dev_list_type type)
1200 {
1201         char *str;
1202         struct use_case_verb *verb;
1203         struct use_case_modifier *modifier;
1204         struct use_case_device *device;
1205
1206         if (!name)
1207                 return -ENOENT;
1208
1209         str = strchr(name, '/');
1210         if (str) {
1211                 *str = '\0';
1212                 verb = find_verb(uc_mgr, str + 1);
1213         }
1214         else {
1215                 verb = uc_mgr->active_verb;
1216         }
1217         if (!verb)
1218                 return -ENOENT;
1219
1220         modifier = find_modifier(uc_mgr, verb, name, 0);
1221         if (modifier) {
1222                 if (modifier->dev_list.type != type) {
1223                         *list = NULL;
1224                         return 0;
1225                 }
1226                 return get_list(&modifier->dev_list.list, list,
1227                                 struct dev_list_node, list,
1228                                 name);
1229         }
1230
1231         device = find_device(uc_mgr, verb, name, 0);
1232         if (device) {
1233                 if (device->dev_list.type != type) {
1234                         *list = NULL;
1235                         return 0;
1236                 }
1237                 return get_list(&device->dev_list.list, list,
1238                                 struct dev_list_node, list,
1239                                 name);
1240         }
1241
1242         return -ENOENT;
1243 }
1244
1245 /**
1246  * \brief Get list of supported devices
1247  * \param list Returned list
1248  * \param name Name of verb or modifier to query
1249  * \return Number of list entries if success, otherwise a negative error code
1250  */
1251 static int get_supported_device_list(snd_use_case_mgr_t *uc_mgr,
1252                                      const char **list[], char *name)
1253 {
1254         return get_supcon_device_list(uc_mgr, list, name, DEVLIST_SUPPORTED);
1255 }
1256
1257 /**
1258  * \brief Get list of conflicting devices
1259  * \param list Returned list
1260  * \param name Name of verb or modifier to query
1261  * \return Number of list entries if success, otherwise a negative error code
1262  */
1263 static int get_conflicting_device_list(snd_use_case_mgr_t *uc_mgr,
1264                                        const char **list[], char *name)
1265 {
1266         return get_supcon_device_list(uc_mgr, list, name, DEVLIST_CONFLICTING);
1267 }
1268
1269 #ifndef DOC_HIDDEN
1270 struct myvalue {
1271         struct list_head list;
1272         const char *text;
1273 };
1274 #endif
1275
1276 /**
1277  * \brief Convert myvalue list string list
1278  * \param list myvalue list
1279  * \param res string list
1280  * \retval Number of list entries if success, otherwise a negativer error code
1281  */
1282 static int myvalue_to_str_list(struct list_head *list, char ***res)
1283 {
1284         struct list_head *pos;
1285         struct myvalue *value;
1286         char **p;
1287         int cnt;
1288
1289         cnt = alloc_str_list(list, 1, res);
1290         if (cnt < 0)
1291                 return cnt;
1292         p = *res;
1293         list_for_each(pos, list) {
1294                 value = list_entry(pos, struct myvalue, list);
1295                 *p = strdup(value->text);
1296                 if (*p == NULL) {
1297                         snd_use_case_free_list((const char **)p, cnt);
1298                         return -ENOMEM;
1299                 }
1300                 p++;
1301         }
1302         return cnt;
1303 }
1304
1305 /**
1306  * \brief Free myvalue list
1307  * \param list myvalue list
1308  */
1309 static void myvalue_list_free(struct list_head *list)
1310 {
1311         struct list_head *pos, *npos;
1312         struct myvalue *value;
1313
1314         list_for_each_safe(pos, npos, list) {
1315                 value = list_entry(pos, struct myvalue, list);
1316                 list_del(&value->list);
1317                 free(value);
1318         }
1319 }
1320
1321 /**
1322  * \brief Merge one value to the myvalue list
1323  * \param list The list with values
1324  * \param value The value to be merged (without duplicates)
1325  * \return 1 if dup, 0 if success, otherwise a negative error code
1326  */
1327 static int merge_value(struct list_head *list, const char *text)
1328 {
1329         struct list_head *pos;
1330         struct myvalue *value;
1331
1332         list_for_each(pos, list) {
1333                 value = list_entry(pos, struct myvalue, list);
1334                 if (strcmp(value->text, text) == 0)
1335                         return 1;
1336         }
1337         value = malloc(sizeof(*value));
1338         if (value == NULL)
1339                 return -ENOMEM;
1340         value->text = text;
1341         list_add_tail(&value->list, list);
1342         return 0;
1343 }
1344
1345 /**
1346  * \brief Find all values for given identifier
1347  * \param list Returned list
1348  * \param source Source list with ucm_value structures
1349  * \return Zero if success, otherwise a negative error code
1350  */
1351 static int add_identifiers(struct list_head *list,
1352                            struct list_head *source)
1353 {
1354         struct ucm_value *v;
1355         struct list_head *pos;
1356         int err;
1357
1358         list_for_each(pos, source) {
1359                 v = list_entry(pos, struct ucm_value, list);
1360                 err = merge_value(list, v->name);
1361                 if (err < 0)
1362                         return err;
1363         }
1364         return 0;
1365 }
1366
1367 /**
1368  * \brief Find all values for given identifier
1369  * \param list Returned list
1370  * \param identifier Identifier
1371  * \param source Source list with ucm_value structures
1372  */
1373 static int add_values(struct list_head *list,
1374                       const char *identifier,
1375                       struct list_head *source)
1376 {
1377         struct ucm_value *v;
1378         struct list_head *pos;
1379         int err;
1380         
1381         list_for_each(pos, source) {
1382                 v = list_entry(pos, struct ucm_value, list);
1383                 if (check_identifier(identifier, v->name)) {
1384                         err = merge_value(list, v->data);
1385                         if (err < 0)
1386                                 return err;
1387                 }
1388         }
1389         return 0;
1390 }
1391
1392 /**
1393  * \brief compare two identifiers
1394  */
1395 static int identifier_cmp(const void *_a, const void *_b)
1396 {
1397         const char * const *a = _a;
1398         const char * const *b = _b;
1399         return strcmp(*a, *b);
1400 }
1401
1402 /**
1403  * \brief Get list of available identifiers
1404  * \param list Returned list
1405  * \param name Name of verb or modifier to query
1406  * \return Number of list entries if success, otherwise a negative error code
1407  */
1408 static int get_identifiers_list(snd_use_case_mgr_t *uc_mgr,
1409                                 const char **list[], char *name)
1410 {
1411         struct use_case_verb *verb;
1412         struct use_case_modifier *modifier;
1413         struct use_case_device *device;
1414         struct list_head mylist;
1415         struct list_head *value_list;
1416         char *str, **res;
1417         int err;
1418
1419         if (!name)
1420                 return -ENOENT;
1421
1422         str = strchr(name, '/');
1423         if (str) {
1424                 *str = '\0';
1425                 verb = find_verb(uc_mgr, str + 1);
1426         }
1427         else {
1428                 verb = uc_mgr->active_verb;
1429         }
1430         if (!verb)
1431                 return -ENOENT;
1432
1433         value_list = NULL;
1434         modifier = find_modifier(uc_mgr, verb, name, 0);
1435         if (modifier) {
1436                 value_list = &modifier->value_list;
1437         } else {
1438                 device = find_device(uc_mgr, verb, name, 0);
1439                 if (device)
1440                         value_list = &device->value_list;
1441         }
1442         if (value_list == NULL)
1443                 return -ENOENT;
1444
1445         INIT_LIST_HEAD(&mylist);
1446         err = add_identifiers(&mylist, &uc_mgr->value_list);
1447         if (err < 0)
1448                 goto __fail;
1449         err = add_identifiers(&mylist, &verb->value_list);
1450         if (err < 0)
1451                 goto __fail;
1452         err = add_identifiers(&mylist, value_list);
1453         if (err < 0)
1454                 goto __fail;
1455         err = myvalue_to_str_list(&mylist, &res);
1456         if (err > 0)
1457                 *list = (const char **)res;
1458         else if (err == 0)
1459                 *list = NULL;
1460 __fail:
1461         myvalue_list_free(&mylist);
1462         if (err <= 0)
1463                 return err;
1464         qsort(*list, err, sizeof(char *), identifier_cmp);
1465         return err;
1466 }
1467
1468 /**
1469  * \brief Get list of values
1470  * \param list Returned list
1471  * \param verbname For verb (NULL = current)
1472  * \return Number of list entries if success, otherwise a negative error code
1473  */
1474 static int get_value_list(snd_use_case_mgr_t *uc_mgr,
1475                           const char *identifier,
1476                           const char **list[],
1477                           char *verbname)
1478 {
1479         struct list_head mylist, *pos;
1480         struct use_case_verb *verb;
1481         struct use_case_device *dev;
1482         struct use_case_modifier *mod;
1483         char **res;
1484         int err;
1485         
1486         if (verbname) {
1487                 verb = find_verb(uc_mgr, verbname);
1488         } else {
1489                 verb = uc_mgr->active_verb;
1490         }
1491         if (verb == NULL)
1492                 return -ENOENT;
1493         INIT_LIST_HEAD(&mylist);
1494         err = add_values(&mylist, identifier, &uc_mgr->value_list);
1495         if (err < 0)
1496                 goto __fail;
1497         err = add_values(&mylist, identifier, &verb->value_list);
1498         if (err < 0)
1499                 goto __fail;
1500         list_for_each(pos, &verb->device_list) {
1501                 dev = list_entry(pos, struct use_case_device, list);
1502                 err = add_values(&mylist, identifier, &dev->value_list);
1503                 if (err < 0)
1504                         goto __fail;
1505         }
1506         list_for_each(pos, &verb->modifier_list) {
1507                 mod = list_entry(pos, struct use_case_modifier, list);
1508                 err = add_values(&mylist, identifier, &mod->value_list);
1509                 if (err < 0)
1510                         goto __fail;
1511         }
1512         err = myvalue_to_str_list(&mylist, &res);
1513         if (err > 0)
1514                 *list = (const char **)res;
1515         else if (err == 0)
1516                 *list = NULL;
1517       __fail:
1518         myvalue_list_free(&mylist);
1519         return err;
1520 }
1521
1522 /**
1523  * \brief Get list of enabled devices
1524  * \param list Returned list
1525  * \param verbname For verb (NULL = current)
1526  * \return Number of list entries if success, otherwise a negative error code
1527  */
1528 static int get_enabled_device_list(snd_use_case_mgr_t *uc_mgr,
1529                                    const char **list[])
1530 {
1531         if (uc_mgr->active_verb == NULL)
1532                 return -EINVAL;
1533         return get_list(&uc_mgr->active_devices, list,
1534                         struct use_case_device, active_list,
1535                         name);
1536 }
1537
1538 /**
1539  * \brief Get list of enabled modifiers
1540  * \param list Returned list
1541  * \param verbname For verb (NULL = current)
1542  * \return Number of list entries if success, otherwise a negative error code
1543  */
1544 static int get_enabled_modifier_list(snd_use_case_mgr_t *uc_mgr,
1545                                      const char **list[])
1546 {
1547         if (uc_mgr->active_verb == NULL)
1548                 return -EINVAL;
1549         return get_list(&uc_mgr->active_modifiers, list,
1550                         struct use_case_modifier, active_list,
1551                         name);
1552 }
1553
1554 /**
1555  * \brief Obtain a list of entries
1556  * \param uc_mgr Use case manager (may be NULL - card list)
1557  * \param identifier (may be NULL - card list)
1558  * \param list Returned allocated list
1559  * \return Number of list entries if success, otherwise a negative error code
1560  */
1561 int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr,
1562                           const char *identifier,
1563                           const char **list[])
1564 {
1565         char *str, *str1;
1566         int err;
1567
1568         if (uc_mgr == NULL || identifier == NULL)
1569                 return uc_mgr_scan_master_configs(list);
1570         pthread_mutex_lock(&uc_mgr->mutex);
1571         if (strcmp(identifier, "_verbs") == 0)
1572                 err = get_verb_list(uc_mgr, list);
1573         else if (strcmp(identifier, "_enadevs") == 0)
1574                 err = get_enabled_device_list(uc_mgr, list);
1575         else if (strcmp(identifier, "_enamods") == 0)
1576                 err = get_enabled_modifier_list(uc_mgr, list);
1577         else {
1578                 str1 = strchr(identifier, '/');
1579                 if (str1) {
1580                         str = strdup(str1 + 1);
1581                         if (str == NULL) {
1582                                 err = -ENOMEM;
1583                                 goto __end;
1584                         }
1585                 } else {
1586                         str = NULL;
1587                 }
1588                 if (check_identifier(identifier, "_devices"))
1589                         err = get_device_list(uc_mgr, list, str);
1590                 else if (check_identifier(identifier, "_modifiers"))
1591                         err = get_modifier_list(uc_mgr, list, str);
1592                 else if (check_identifier(identifier, "_identifiers"))
1593                         err = get_identifiers_list(uc_mgr, list, str);
1594                 else if (check_identifier(identifier, "_supporteddevs"))
1595                         err = get_supported_device_list(uc_mgr, list, str);
1596                 else if (check_identifier(identifier, "_conflictingdevs"))
1597                         err = get_conflicting_device_list(uc_mgr, list, str);
1598                 else if (identifier[0] == '_')
1599                         err = -ENOENT;
1600                 else
1601                         err = get_value_list(uc_mgr, identifier, list, str);
1602                 if (str)
1603                         free(str);
1604         }
1605       __end:
1606         pthread_mutex_unlock(&uc_mgr->mutex);
1607         return err;
1608 }
1609
1610 static int get_value1(snd_use_case_mgr_t *uc_mgr, char **value,
1611                       struct list_head *value_list, const char *identifier)
1612 {
1613         struct ucm_value *val;
1614         struct list_head *pos;
1615         
1616         if (!value_list)
1617                 return -ENOENT;
1618
1619         list_for_each(pos, value_list) {
1620                 val = list_entry(pos, struct ucm_value, list);
1621                 if (check_identifier(identifier, val->name)) {
1622                         if (uc_mgr->conf_format < 2) {
1623                                 *value = strdup(val->data);
1624                                 if (*value == NULL)
1625                                         return -ENOMEM;
1626                                 return 0;
1627                         }
1628                         return uc_mgr_get_substituted_value(uc_mgr, value, val->data);
1629                 }
1630         }
1631         return -ENOENT;
1632 }
1633
1634 static int get_value3(snd_use_case_mgr_t *uc_mgr,
1635                       char **value,
1636                       const char *identifier,
1637                       struct list_head *value_list1,
1638                       struct list_head *value_list2,
1639                       struct list_head *value_list3)
1640 {
1641         int err;
1642
1643         err = get_value1(uc_mgr, value, value_list1, identifier);
1644         if (err >= 0 || err != -ENOENT)
1645                 return err;
1646         err = get_value1(uc_mgr, value, value_list2, identifier);
1647         if (err >= 0 || err != -ENOENT)
1648                 return err;
1649         err = get_value1(uc_mgr, value, value_list3, identifier);
1650         if (err >= 0 || err != -ENOENT)
1651                 return err;
1652         return -ENOENT;
1653 }
1654
1655 /**
1656  * \brief Get value
1657  * \param uc_mgr Use case manager
1658  * \param identifier Value identifier (string)
1659  * \param value Returned value string
1660  * \param item Modifier or Device name (string)
1661  * \return Zero on success (value is filled), otherwise a negative error code
1662  */
1663 static int get_value(snd_use_case_mgr_t *uc_mgr,
1664                         const char *identifier,
1665                         char **value,
1666                         const char *mod_dev_name,
1667                         const char *verb_name,
1668                         int exact)
1669 {
1670         struct use_case_verb *verb;
1671         struct use_case_modifier *mod;
1672         struct use_case_device *dev;
1673         int err;
1674
1675         if (mod_dev_name || verb_name || !exact) {
1676                 if (verb_name && strlen(verb_name)) {
1677                         verb = find_verb(uc_mgr, verb_name);
1678                 } else {
1679                         verb = uc_mgr->active_verb;
1680                 }
1681                 if (verb) {
1682                         if (mod_dev_name) {
1683                                 mod = find_modifier(uc_mgr, verb,
1684                                                     mod_dev_name, 0);
1685                                 if (mod) {
1686                                         err = get_value1(uc_mgr, value,
1687                                                          &mod->value_list,
1688                                                          identifier);
1689                                         if (err >= 0 || err != -ENOENT)
1690                                                 return err;
1691                                 }
1692
1693                                 dev = find_device(uc_mgr, verb,
1694                                                   mod_dev_name, 0);
1695                                 if (dev) {
1696                                         err = get_value1(uc_mgr, value,
1697                                                          &dev->value_list,
1698                                                          identifier);
1699                                         if (err >= 0 || err != -ENOENT)
1700                                                 return err;
1701                                 }
1702
1703                                 if (exact)
1704                                         return -ENOENT;
1705                         }
1706
1707                         err = get_value1(uc_mgr, value, &verb->value_list, identifier);
1708                         if (err >= 0 || err != -ENOENT)
1709                                 return err;
1710                 }
1711
1712                 if (exact)
1713                         return -ENOENT;
1714         }
1715
1716         err = get_value1(uc_mgr, value, &uc_mgr->value_list, identifier);
1717         if (err >= 0 || err != -ENOENT)
1718                 return err;
1719
1720         return -ENOENT;
1721 }
1722
1723 /**
1724  * \brief Get current - string
1725  * \param uc_mgr Use case manager
1726  * \param identifier 
1727  * \param value Value pointer
1728  * \return Zero if success, otherwise a negative error code
1729  *
1730  * Note: String is dynamically allocated, use free() to
1731  * deallocate this string.
1732  */      
1733 int snd_use_case_get(snd_use_case_mgr_t *uc_mgr,
1734                      const char *identifier,
1735                      const char **value)
1736 {
1737         const char *slash1, *slash2, *mod_dev_after;
1738         const char *ident, *mod_dev, *verb;
1739         int exact = 0;
1740         int err;
1741
1742         pthread_mutex_lock(&uc_mgr->mutex);
1743         if (identifier == NULL) {
1744                 *value = strdup(uc_mgr->card_name);
1745                 if (*value == NULL) {
1746                         err = -ENOMEM;
1747                         goto __end;
1748                 }
1749                 err = 0;
1750         } else if (strcmp(identifier, "_verb") == 0) {
1751                 if (uc_mgr->active_verb == NULL) {
1752                         err = -ENOENT;
1753                         goto __end;
1754                 }
1755                 *value = strdup(uc_mgr->active_verb->name);
1756                 if (*value == NULL) {
1757                         err = -ENOMEM;
1758                         goto __end;
1759                 }
1760                 err = 0;
1761         } else if (strcmp(identifier, "_file") == 0) {
1762                 /* get the conf file name of the opened card */
1763                 if ((uc_mgr->card_name == NULL) ||
1764                     (uc_mgr->conf_file_name == NULL) ||
1765                     (uc_mgr->conf_file_name[0] == '\0')) {
1766                         err = -ENOENT;
1767                         goto __end;
1768                 }
1769                 *value = strdup(uc_mgr->conf_file_name);
1770                 if (*value == NULL) {
1771                         err = -ENOMEM;
1772                         goto __end;
1773                 }
1774                 err = 0;
1775
1776         } else if (identifier[0] == '_') {
1777                 err = -ENOENT;
1778                 goto __end;
1779         } else {
1780                 if (identifier[0] == '=') {
1781                         exact = 1;
1782                         identifier++;
1783                 }
1784
1785                 slash1 = strchr(identifier, '/');
1786                 if (slash1) {
1787                         ident = strndup(identifier, slash1 - identifier);
1788
1789                         slash2 = strchr(slash1 + 1, '/');
1790                         if (slash2) {
1791                                 mod_dev_after = slash2;
1792                                 verb = slash2 + 1;
1793                         }
1794                         else {
1795                                 mod_dev_after = slash1 + strlen(slash1);
1796                                 verb = NULL;
1797                         }
1798
1799                         if (mod_dev_after == slash1 + 1)
1800                                 mod_dev = NULL;
1801                         else
1802                                 mod_dev = strndup(slash1 + 1,
1803                                                   mod_dev_after - (slash1 + 1));
1804                 }
1805                 else {
1806                         ident = identifier;
1807                         mod_dev = NULL;
1808                         verb = NULL;
1809                 }
1810
1811                 err = get_value(uc_mgr, ident, (char **)value, mod_dev, verb,
1812                                 exact);
1813                 if (ident != identifier)
1814                         free((void *)ident);
1815                 if (mod_dev)
1816                         free((void *)mod_dev);
1817         }
1818       __end:
1819         pthread_mutex_unlock(&uc_mgr->mutex);
1820         return err;
1821 }
1822
1823
1824 /**
1825  * \brief Get current - integer
1826  * \param uc_mgr Use case manager
1827  * \param identifier 
1828  * \return Value if success, otherwise a negative error code 
1829  */
1830 int snd_use_case_geti(snd_use_case_mgr_t *uc_mgr,
1831                       const char *identifier,
1832                       long *value)
1833 {
1834         char *str, *str1;
1835         long err;
1836
1837         pthread_mutex_lock(&uc_mgr->mutex);
1838         if (0) {
1839                 /* nothing here - prepared for fixed identifiers */
1840         } else {
1841                 str1 = strchr(identifier, '/');
1842                 if (str1) {
1843                         str = strdup(str1 + 1);
1844                         if (str == NULL) {
1845                                 err = -ENOMEM;
1846                                 goto __end;
1847                         }
1848                 } else {
1849                         str = NULL;
1850                 }
1851                 if (check_identifier(identifier, "_devstatus")) {
1852                         if (!str) {
1853                                 err = -EINVAL;
1854                                 goto __end;
1855                         }
1856                         err = device_status(uc_mgr, str);
1857                         if (err >= 0) {
1858                                 *value = err;
1859                                 err = 0;
1860                         }
1861                 } else if (check_identifier(identifier, "_modstatus")) {
1862                         if (!str) {
1863                                 err = -EINVAL;
1864                                 goto __end;
1865                         }
1866                         err = modifier_status(uc_mgr, str);
1867                         if (err >= 0) {
1868                                 *value = err;
1869                                 err = 0;
1870                         }
1871 #if 0
1872                 /*
1873                  * enable this block if the else clause below is expanded to query
1874                  * user-supplied values
1875                  */
1876                 } else if (identifier[0] == '_')
1877                         err = -ENOENT;
1878 #endif
1879                 } else
1880                         err = -ENOENT;
1881                 if (str)
1882                         free(str);
1883         }
1884       __end:
1885         pthread_mutex_unlock(&uc_mgr->mutex);
1886         return err;
1887 }
1888
1889 static int set_boot_user(snd_use_case_mgr_t *uc_mgr,
1890                          const char *value)
1891 {
1892         int err;
1893
1894         if (value != NULL && *value) {
1895                 uc_error("error: wrong value for _boot (%s)", value);
1896                 return -EINVAL;
1897         }
1898         err = execute_sequence(uc_mgr, &uc_mgr->boot_list,
1899                                &uc_mgr->value_list, NULL, NULL);
1900         if (err < 0) {
1901                 uc_error("Unable to execute boot sequence");
1902                 return err;
1903         }
1904         return err;
1905 }
1906
1907 static int set_defaults_user(snd_use_case_mgr_t *uc_mgr,
1908                              const char *value)
1909 {
1910         if (value != NULL && *value) {
1911                 uc_error("error: wrong value for _defaults (%s)", value);
1912                 return -EINVAL;
1913         }
1914         return set_defaults(uc_mgr);
1915 }
1916
1917 static int handle_transition_verb(snd_use_case_mgr_t *uc_mgr,
1918                                   struct use_case_verb *new_verb)
1919 {
1920         struct list_head *pos;
1921         struct transition_sequence *trans;
1922         int err;
1923
1924         list_for_each(pos, &uc_mgr->active_verb->transition_list) {
1925                 trans = list_entry(pos, struct transition_sequence, list);
1926                 if (strcmp(trans->name, new_verb->name) == 0) {
1927                         err = execute_sequence(uc_mgr, &trans->transition_list,
1928                                                &uc_mgr->active_verb->value_list,
1929                                                &uc_mgr->value_list,
1930                                                NULL);
1931                         if (err >= 0)
1932                                 return 1;
1933                         return err;
1934                 }
1935         }
1936         return 0;
1937 }
1938
1939 static int set_verb_user(snd_use_case_mgr_t *uc_mgr,
1940                          const char *verb_name)
1941 {
1942         struct use_case_verb *verb;
1943         int err = 0;
1944
1945         if (uc_mgr->active_verb &&
1946             strcmp(uc_mgr->active_verb->name, verb_name) == 0)
1947                 return 0;
1948         if (strcmp(verb_name, SND_USE_CASE_VERB_INACTIVE) != 0) {
1949                 verb = find_verb(uc_mgr, verb_name);
1950                 if (verb == NULL)
1951                         return -ENOENT;
1952         } else {
1953                 verb = NULL;
1954         }
1955         if (uc_mgr->active_verb) {
1956                 err = handle_transition_verb(uc_mgr, verb);
1957                 if (err == 0) {
1958                         err = dismantle_use_case(uc_mgr);
1959                         if (err < 0)
1960                                 return err;
1961                 } else if (err == 1) {
1962                         uc_mgr->active_verb = verb;
1963                         verb = NULL;
1964                 } else {
1965                         verb = NULL; /* show error */
1966                 }
1967         }
1968         if (verb) {
1969                 err = set_verb(uc_mgr, verb, 1);
1970                 if (err < 0)
1971                         uc_error("error: failed to initialize new use case: %s",
1972                                  verb_name);
1973         }
1974         return err;
1975 }
1976
1977
1978 static int set_device_user(snd_use_case_mgr_t *uc_mgr,
1979                            const char *device_name,
1980                            int enable)
1981 {
1982         struct use_case_device *device;
1983
1984         if (uc_mgr->active_verb == NULL)
1985                 return -ENOENT;
1986         device = find_device(uc_mgr, uc_mgr->active_verb, device_name, 1);
1987         if (device == NULL)
1988                 return -ENOENT;
1989         return set_device(uc_mgr, device, enable);
1990 }
1991
1992 static int set_modifier_user(snd_use_case_mgr_t *uc_mgr,
1993                              const char *modifier_name,
1994                              int enable)
1995 {
1996         struct use_case_modifier *modifier;
1997
1998         if (uc_mgr->active_verb == NULL)
1999                 return -ENOENT;
2000
2001         modifier = find_modifier(uc_mgr, uc_mgr->active_verb, modifier_name, 1);
2002         if (modifier == NULL)
2003                 return -ENOENT;
2004         return set_modifier(uc_mgr, modifier, enable);
2005 }
2006
2007 static int switch_device(snd_use_case_mgr_t *uc_mgr,
2008                          const char *old_device,
2009                          const char *new_device)
2010 {
2011         struct use_case_device *xold, *xnew;
2012         struct transition_sequence *trans;
2013         struct list_head *pos;
2014         int err, seq_found = 0;
2015         
2016         if (uc_mgr->active_verb == NULL)
2017                 return -ENOENT;
2018         if (device_status(uc_mgr, old_device) == 0) {
2019                 uc_error("error: device %s not enabled", old_device);
2020                 return -EINVAL;
2021         }
2022         if (device_status(uc_mgr, new_device) != 0) {
2023                 uc_error("error: device %s already enabled", new_device);
2024                 return -EINVAL;
2025         }
2026         xold = find_device(uc_mgr, uc_mgr->active_verb, old_device, 1);
2027         if (xold == NULL)
2028                 return -ENOENT;
2029         list_del(&xold->active_list);
2030         xnew = find_device(uc_mgr, uc_mgr->active_verb, new_device, 1);
2031         list_add_tail(&xold->active_list, &uc_mgr->active_devices);
2032         if (xnew == NULL)
2033                 return -ENOENT;
2034         err = 0;
2035         list_for_each(pos, &xold->transition_list) {
2036                 trans = list_entry(pos, struct transition_sequence, list);
2037                 if (strcmp(trans->name, new_device) == 0) {
2038                         err = execute_sequence(uc_mgr, &trans->transition_list,
2039                                                &xold->value_list,
2040                                                &uc_mgr->active_verb->value_list,
2041                                                &uc_mgr->value_list);
2042                         if (err >= 0) {
2043                                 list_del(&xold->active_list);
2044                                 list_add_tail(&xnew->active_list, &uc_mgr->active_devices);
2045                         }
2046                         seq_found = 1;
2047                         break;
2048                 }
2049         }
2050         if (!seq_found) {
2051                 err = set_device(uc_mgr, xold, 0);
2052                 if (err < 0)
2053                         return err;
2054                 err = set_device(uc_mgr, xnew, 1);
2055                 if (err < 0)
2056                         return err;
2057         }
2058         return err;
2059 }
2060
2061 static int switch_modifier(snd_use_case_mgr_t *uc_mgr,
2062                            const char *old_modifier,
2063                            const char *new_modifier)
2064 {
2065         struct use_case_modifier *xold, *xnew;
2066         struct transition_sequence *trans;
2067         struct list_head *pos;
2068         int err, seq_found = 0;
2069         
2070         if (uc_mgr->active_verb == NULL)
2071                 return -ENOENT;
2072         if (modifier_status(uc_mgr, old_modifier) == 0) {
2073                 uc_error("error: modifier %s not enabled", old_modifier);
2074                 return -EINVAL;
2075         }
2076         if (modifier_status(uc_mgr, new_modifier) != 0) {
2077                 uc_error("error: modifier %s already enabled", new_modifier);
2078                 return -EINVAL;
2079         }
2080         xold = find_modifier(uc_mgr, uc_mgr->active_verb, old_modifier, 1);
2081         if (xold == NULL)
2082                 return -ENOENT;
2083         xnew = find_modifier(uc_mgr, uc_mgr->active_verb, new_modifier, 1);
2084         if (xnew == NULL)
2085                 return -ENOENT;
2086         err = 0;
2087         list_for_each(pos, &xold->transition_list) {
2088                 trans = list_entry(pos, struct transition_sequence, list);
2089                 if (strcmp(trans->name, new_modifier) == 0) {
2090                         err = execute_sequence(uc_mgr, &trans->transition_list,
2091                                                &xold->value_list,
2092                                                &uc_mgr->active_verb->value_list,
2093                                                &uc_mgr->value_list);
2094                         if (err >= 0) {
2095                                 list_del(&xold->active_list);
2096                                 list_add_tail(&xnew->active_list, &uc_mgr->active_modifiers);
2097                         }
2098                         seq_found = 1;
2099                         break;
2100                 }
2101         }
2102         if (!seq_found) {
2103                 err = set_modifier(uc_mgr, xold, 0);
2104                 if (err < 0)
2105                         return err;
2106                 err = set_modifier(uc_mgr, xnew, 1);
2107                 if (err < 0)
2108                         return err;
2109         }
2110         return err;        
2111 }
2112
2113 /**
2114  * \brief Set new
2115  * \param uc_mgr Use case manager
2116  * \param identifier
2117  * \param value Value
2118  * \return Zero if success, otherwise a negative error code
2119  */
2120 int snd_use_case_set(snd_use_case_mgr_t *uc_mgr,
2121                      const char *identifier,
2122                      const char *value)
2123 {
2124         char *str, *str1;
2125         int err = 0;
2126
2127         pthread_mutex_lock(&uc_mgr->mutex);
2128         if (strcmp(identifier, "_boot") == 0)
2129                 err = set_boot_user(uc_mgr, value);
2130         else if (strcmp(identifier, "_defaults") == 0)
2131                 err = set_defaults_user(uc_mgr, value);
2132         else if (strcmp(identifier, "_verb") == 0)
2133                 err = set_verb_user(uc_mgr, value);
2134         else if (strcmp(identifier, "_enadev") == 0)
2135                 err = set_device_user(uc_mgr, value, 1);
2136         else if (strcmp(identifier, "_disdev") == 0)
2137                 err = set_device_user(uc_mgr, value, 0);
2138         else if (strcmp(identifier, "_enamod") == 0)
2139                 err = set_modifier_user(uc_mgr, value, 1);
2140         else if (strcmp(identifier, "_dismod") == 0)
2141                 err = set_modifier_user(uc_mgr, value, 0);
2142         else {
2143                 str1 = strchr(identifier, '/');
2144                 if (str1) {
2145                         str = strdup(str1 + 1);
2146                         if (str == NULL) {
2147                                 err = -ENOMEM;
2148                                 goto __end;
2149                         }
2150                 } else {
2151                         err = -EINVAL;
2152                         goto __end;
2153                 }
2154                 if (check_identifier(identifier, "_swdev"))
2155                         err = switch_device(uc_mgr, str, value);
2156                 else if (check_identifier(identifier, "_swmod"))
2157                         err = switch_modifier(uc_mgr, str, value);
2158                 else
2159                         err = -EINVAL;
2160                 if (str)
2161                         free(str);
2162         }
2163       __end:
2164         pthread_mutex_unlock(&uc_mgr->mutex);
2165         return err;
2166 }
2167
2168 /**
2169  * \brief Parse control element identifier
2170  * \param elem_id Element identifier
2171  * \param ucm_id Use case identifier
2172  * \param value String value to be parsed
2173  * \return Zero if success, otherwise a negative error code
2174  */
2175 int snd_use_case_parse_ctl_elem_id(snd_ctl_elem_id_t *dst,
2176                                    const char *ucm_id,
2177                                    const char *value)
2178 {
2179         snd_ctl_elem_iface_t iface;
2180         int jack_control;
2181
2182         jack_control = strcmp(ucm_id, "JackControl") == 0;
2183         if (!jack_control &&
2184             strcmp(ucm_id, "PlaybackVolume") &&
2185             strcmp(ucm_id, "PlaybackSwitch") &&
2186             strcmp(ucm_id, "CaptureVolume") &&
2187             strcmp(ucm_id, "CaptureSwitch"))
2188                 return -EINVAL;
2189         snd_ctl_elem_id_clear(dst);
2190         if (strcasestr(ucm_id, "name="))
2191                 return __snd_ctl_ascii_elem_id_parse(dst, value, NULL);
2192         iface = SND_CTL_ELEM_IFACE_MIXER;
2193         if (jack_control)
2194                 iface = SND_CTL_ELEM_IFACE_CARD;
2195         snd_ctl_elem_id_set_interface(dst, iface);
2196         snd_ctl_elem_id_set_name(dst, value);
2197         return 0;
2198 }
2199
2200 /**
2201  * \brief Parse mixer element identifier
2202  * \param dst Simple mixer element identifier
2203  * \param ucm_id Use case identifier
2204  * \param value String value to be parsed
2205  * \return Zero if success, otherwise a negative error code
2206  */
2207 int snd_use_case_parse_selem_id(snd_mixer_selem_id_t *dst,
2208                                 const char *ucm_id,
2209                                 const char *value)
2210 {
2211 #ifdef BUILD_MIXER
2212         if (strcmp(ucm_id, "PlaybackMixerId") == 0 ||
2213             strcmp(ucm_id, "CaptureMixerId") == 0)
2214                 return snd_mixer_selem_id_parse(dst, value);
2215 #endif
2216         return -EINVAL;
2217 }