]> git.alsa-project.org Git - alsa-lib.git/commitdiff
ucm: debug parser
authorJaroslav Kysela <perex@perex.cz>
Tue, 26 Oct 2010 12:26:46 +0000 (14:26 +0200)
committerJaroslav Kysela <perex@perex.cz>
Tue, 26 Oct 2010 12:26:46 +0000 (14:26 +0200)
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
src/ucm/parser.c
src/ucm/ucm_local.h
src/ucm/utils.c
test/ucm/TestHDA/Case1.conf [new file with mode: 0644]
test/ucm/TestHDA/TestHDA.conf [new file with mode: 0644]

index 4e2a9d74d59218b2b144ce3df991cf6b29c9c859..1b5a43107d3dc14b60bdd2e26f2d14b7f0118d2c 100644 (file)
@@ -33,6 +33,9 @@
 #include "ucm_local.h"
 #include <dirent.h>
 
+/** The name of the environment variable containing the UCM directory */
+#define ALSA_CONFIG_UCM_VAR "ALSA_CONFIG_UCM"
+
 static int parse_sequence(snd_use_case_mgr_t *uc_mgr,
                          struct list_head *base,
                          snd_config_t *cfg);
@@ -70,43 +73,37 @@ static int parse_transition(snd_use_case_mgr_t *uc_mgr,
        if (snd_config_get_id(cfg, &id) < 0)
                return -EINVAL;
 
-       tseq = calloc(1, sizeof(*tseq));
-       if (tseq == NULL)
-               return -ENOMEM;
-       INIT_LIST_HEAD(&tseq->transition_list);
-
-       tseq->name = strdup(id);
-       if (tseq->name == NULL) {
-               free(tseq);
-               return -ENOMEM;
-       }
-       
        if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) {
                uc_error("compound type expected for %s", id);
-               err = -EINVAL;
-               goto __err;
+               return -EINVAL;
        }
-       /* parse master config sections */
+
        snd_config_for_each(i, next, cfg) {
                n = snd_config_iterator_entry(i);
 
-               if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) {
-                       uc_error("compound type expected for %s", id);
-                       err = -EINVAL;
-                       goto __err;
+               if (snd_config_get_id(n, &id) < 0)
+                       return -EINVAL;
+
+               tseq = calloc(1, sizeof(*tseq));
+               if (tseq == NULL)
+                       return -ENOMEM;
+               INIT_LIST_HEAD(&tseq->transition_list);
+
+               tseq->name = strdup(id);
+               if (tseq->name == NULL) {
+                       free(tseq);
+                       return -ENOMEM;
                }
-               
+       
                err = parse_sequence(uc_mgr, &tseq->transition_list, n);
-               if (err < 0)
+               if (err < 0) {
+                       uc_mgr_free_transition_element(tseq);
                        return err;
-       }
+               }
 
-       list_add(&tseq->list, tlist);
+               list_add(&tseq->list, tlist);
+       }
        return 0;
-      __err:
-       free(tseq->name);
-       free(tseq);
-       return err;
 }
 
 /*
@@ -128,7 +125,7 @@ static int parse_compound(snd_use_case_mgr_t *uc_mgr, snd_config_t *cfg,
                uc_error("compound type expected for %s", id);
                return -EINVAL;
        }
-       /* parse master config sections */
+       /* parse compound */
        snd_config_for_each(i, next, cfg) {
                n = snd_config_iterator_entry(i);
 
@@ -145,6 +142,47 @@ static int parse_compound(snd_use_case_mgr_t *uc_mgr, snd_config_t *cfg,
        return 0;
 }
 
+
+/*
+ * Parse transition
+ */
+static int parse_supported_device(snd_use_case_mgr_t *uc_mgr ATTRIBUTE_UNUSED,
+                                 struct list_head *dlist,
+                                 snd_config_t *cfg)
+{
+       struct dev_list *sdev;
+       const char *id;
+       snd_config_iterator_t i, next;
+       snd_config_t *n;
+       int err;
+
+       if (snd_config_get_id(cfg, &id) < 0)
+               return -EINVAL;
+
+       if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) {
+               uc_error("compound type expected for %s", id);
+               return -EINVAL;
+       }
+
+       snd_config_for_each(i, next, cfg) {
+               n = snd_config_iterator_entry(i);
+
+               if (snd_config_get_id(n, &id) < 0)
+                       return -EINVAL;
+
+               sdev = calloc(1, sizeof(struct dev_list));
+               if (sdev == NULL)
+                       return -ENOMEM;
+               err = parse_string(n, &sdev->name);
+               if (err < 0) {
+                       free(sdev);
+                       return err;
+               }
+               list_add(&sdev->list, dlist);
+       }
+       return 0;
+}
+
 /*
  * Parse sequences.
  *
@@ -163,58 +201,60 @@ static int parse_sequence(snd_use_case_mgr_t *uc_mgr ATTRIBUTE_UNUSED,
                          snd_config_t *cfg)
 {
        struct sequence_element *curr;
-       snd_config_iterator_t i, next, j, next2;
-       snd_config_t *n, *n2;
+       snd_config_iterator_t i, next;
+       snd_config_t *n;
        int err;
 
+       if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) {
+               uc_error("error: compound is expected for sequence definition");
+               return -EINVAL;
+       }
+
        snd_config_for_each(i, next, cfg) {
+               const char *id;
                n = snd_config_iterator_entry(i);
-               snd_config_for_each(j, next2, n) {
-                       const char *id;
-                       n2 = snd_config_iterator_entry(i);
-                       err = snd_config_get_id(n2, &id);
-                       if (err < 0)
-                               continue;
+               err = snd_config_get_id(n, &id);
+               if (err < 0)
+                       continue;
 
-                       /* alloc new sequence element */
-                       curr = calloc(1, sizeof(struct sequence_element));
-                       if (curr == NULL)
-                               return -ENOMEM;
-                       list_add_tail(&curr->list, base);
-
-                       if (strcmp(id, "cset") == 0) {
-                               curr->type = SEQUENCE_ELEMENT_TYPE_CSET;
-                               err = parse_string(n2, &curr->data.cset);
-                               if (err < 0) {
-                                       uc_error("error: cset requires a string!");
-                                       return err;
-                               }
-                               continue;
+               /* alloc new sequence element */
+               curr = calloc(1, sizeof(struct sequence_element));
+               if (curr == NULL)
+                       return -ENOMEM;
+               list_add_tail(&curr->list, base);
+
+               if (strcmp(id, "cset") == 0) {
+                       curr->type = SEQUENCE_ELEMENT_TYPE_CSET;
+                       err = parse_string(n, &curr->data.cset);
+                       if (err < 0) {
+                               uc_error("error: cset requires a string!");
+                               return err;
                        }
+                       continue;
+               }
 
-                       if (strcmp(id, "usleep") == 0) {
-                               curr->type = SEQUENCE_ELEMENT_TYPE_SLEEP;
-                               err = snd_config_get_integer(n2, &curr->data.sleep);
-                               if (err < 0) {
-                                       uc_error("error: usleep requires integer!");
-                                       return err;
-                               }
-                               continue;
+               if (strcmp(id, "usleep") == 0) {
+                       curr->type = SEQUENCE_ELEMENT_TYPE_SLEEP;
+                       err = snd_config_get_integer(n, &curr->data.sleep);
+                       if (err < 0) {
+                               uc_error("error: usleep requires integer!");
+                               return err;
                        }
+                       continue;
+               }
 
-                       if (strcmp(id, "exec") == 0) {
-                               curr->type = SEQUENCE_ELEMENT_TYPE_EXEC;
-                               err = parse_string(n2, &curr->data.exec);
-                               if (err < 0) {
-                                       uc_error("error: exec requires a string!");
-                                       return err;
-                               }
-                               continue;
+               if (strcmp(id, "exec") == 0) {
+                       curr->type = SEQUENCE_ELEMENT_TYPE_EXEC;
+                       err = parse_string(n, &curr->data.exec);
+                       if (err < 0) {
+                               uc_error("error: exec requires a string!");
+                               return err;
                        }
-                       
-                       list_del(&curr->list);
-                       uc_mgr_free_sequence_element(curr);
+                       continue;
                }
+               
+               list_del(&curr->list);
+               uc_mgr_free_sequence_element(curr);
        }
 
        return 0;
@@ -237,65 +277,66 @@ static int parse_value(snd_use_case_mgr_t *uc_mgr ATTRIBUTE_UNUSED,
                          snd_config_t *cfg)
 {
        struct ucm_value *curr;
-       snd_config_iterator_t i, next, j, next2;
-       snd_config_t *n, *n2;
+       snd_config_iterator_t i, next;
+       snd_config_t *n;
        long l;
        long long ll;
        double d;
        snd_config_type_t type;
        int err;
 
+       if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) {
+               uc_error("error: compound is expected for value definition");
+               return -EINVAL;
+       }
        snd_config_for_each(i, next, cfg) {
+               const char *id;
                n = snd_config_iterator_entry(i);
-               snd_config_for_each(j, next2, n) {
-                       const char *id;
-                       n2 = snd_config_iterator_entry(i);
-                       err = snd_config_get_id(n2, &id);
-                       if (err < 0)
-                               continue;
+               err = snd_config_get_id(n, &id);
+               if (err < 0)
+                       continue;
 
-                       /* alloc new value */
-                       curr = calloc(1, sizeof(struct ucm_value));
-                       if (curr == NULL)
+               /* alloc new value */
+               curr = calloc(1, sizeof(struct ucm_value));
+               if (curr == NULL)
+                       return -ENOMEM;
+               list_add_tail(&curr->list, base);
+               curr->name = strdup(id);
+               if (curr->name == NULL)
+                       return -ENOMEM;
+               type = snd_config_get_type(n);
+               switch (type) {
+               case SND_CONFIG_TYPE_INTEGER:
+                       curr->data = malloc(16);
+                       if (curr->data == NULL)
                                return -ENOMEM;
-                       list_add_tail(&curr->list, base);
-                       curr->name = strdup(id);
-                       if (curr->name == NULL)
+                       snd_config_get_integer(n, &l);
+                       sprintf(curr->data, "%li", l);
+                       break;
+               case SND_CONFIG_TYPE_INTEGER64:
+                       curr->data = malloc(32);
+                       if (curr->data == NULL)
                                return -ENOMEM;
-                       type = snd_config_get_type(n2);
-                       switch (type) {
-                       case SND_CONFIG_TYPE_INTEGER:
-                               curr->data = malloc(16);
-                               if (curr->data == NULL)
-                                       return -ENOMEM;
-                               snd_config_get_integer(n2, &l);
-                               sprintf(curr->data, "%li", l);
-                               break;
-                       case SND_CONFIG_TYPE_INTEGER64:
-                               curr->data = malloc(32);
-                               if (curr->data == NULL)
-                                       return -ENOMEM;
-                               snd_config_get_integer64(n2, &ll);
-                               sprintf(curr->data, "%lli", ll);
-                               break;
-                       case SND_CONFIG_TYPE_REAL:
-                               curr->data = malloc(64);
-                               if (curr->data == NULL)
-                                       return -ENOMEM;
-                               snd_config_get_real(n2, &d);
-                               sprintf(curr->data, "%-16g", d);
-                               break;
-                       case SND_CONFIG_TYPE_STRING:
-                               err = parse_string(n2, &curr->data);
-                               if (err < 0) {
-                                       uc_error("error: unable to parse a string for id '%s'!", id);
-                                       return err;
-                               }
-                               break;
-                       default:
-                               uc_error("error: invalid type %i in Value compound", type);
-                               return -EINVAL;
+                       snd_config_get_integer64(n, &ll);
+                       sprintf(curr->data, "%lli", ll);
+                       break;
+               case SND_CONFIG_TYPE_REAL:
+                       curr->data = malloc(64);
+                       if (curr->data == NULL)
+                               return -ENOMEM;
+                       snd_config_get_real(n, &d);
+                       sprintf(curr->data, "%-16g", d);
+                       break;
+               case SND_CONFIG_TYPE_STRING:
+                       err = parse_string(n, &curr->data);
+                       if (err < 0) {
+                               uc_error("error: unable to parse a string for id '%s'!", id);
+                               return err;
                        }
+                       break;
+               default:
+                       uc_error("error: invalid type %i in Value compound", type);
+                       return -EINVAL;
                }
        }
 
@@ -322,6 +363,10 @@ static int parse_value(snd_use_case_mgr_t *uc_mgr ATTRIBUTE_UNUSED,
  *                     ...
  *             ]
  *
+ *              TransitionSequence."ToModifierName" [
+ *                     ...
+ *             ]
+ *
  *             # Optional TQ and ALSA PCMs
  *             Value {
  *                     TQ Voice
@@ -377,18 +422,12 @@ static int parse_modifier(snd_use_case_mgr_t *uc_mgr,
                }
 
                if (strcmp(id, "SupportedDevice") == 0) {
-                       struct dev_list *sdev;
-                       
-                       sdev = calloc(1, sizeof(struct dev_list));
-                       if (sdev == NULL)
-                               return -ENOMEM;
-                       err = parse_string(n, &sdev->name);
+                       err = parse_supported_device(uc_mgr, &modifier->dev_list, n);
                        if (err < 0) {
-                               free(sdev);
+                               uc_error("error: failed to parse supported"
+                                       " device list");
                                return err;
                        }
-                       list_add(&sdev->list, &modifier->dev_list);
-                       continue;
                }
 
                if (strcmp(id, "EnableSequence") == 0) {
@@ -411,7 +450,7 @@ static int parse_modifier(snd_use_case_mgr_t *uc_mgr,
                        continue;
                }
 
-               if (strcmp(id, "TransitionModifier") == 0) {
+               if (strcmp(id, "TransitionSequence") == 0) {
                        err = parse_transition(uc_mgr, &modifier->transition_list, n);
                        if (err < 0) {
                                uc_error("error: failed to parse transition"
@@ -454,6 +493,10 @@ static int parse_modifier(snd_use_case_mgr_t *uc_mgr,
  *             ...
  *     ]
  *
+ *      TransitionSequence."ToDevice" [
+ *             ...
+ *     ]
+ *
  *     Value {
  *             PlaybackVolume "name='Master Playback Volume',index=2"
  *             PlaybackSwitch "name='Master Playback Switch',index=2"
@@ -527,8 +570,8 @@ static int parse_device_index(snd_use_case_mgr_t *uc_mgr,
                        continue;
                }
 
-               if (strcmp(id, "TransitionDevice") == 0) {
-                       uc_dbg("TransitionDevice");
+               if (strcmp(id, "TransitionSequence") == 0) {
+                       uc_dbg("TransitionSequence");
                        err = parse_transition(uc_mgr, &device->transition_list, n);
                        if (err < 0) {
                                uc_error("error: failed to parse transition"
@@ -596,11 +639,16 @@ static int parse_device(snd_use_case_mgr_t *uc_mgr,
  *             cset "name='Master Playback Volume',index=2 50,50"
  *     ]
  *
+ *      # Optional transition verb
+ *      TransitionSequence."ToCaseName" [
+ *             msleep 1
+ *      ]
+ *
  *     # Optional TQ and ALSA PCMs
  *     Value {
  *             TQ HiFi
- *             CapturePCM 0
- *             PlaybackPCM 0
+ *             CapturePCM "hw:0"
+ *             PlaybackPCM "hw:0"
  *     }
  * }
  */
@@ -621,7 +669,7 @@ static int parse_verb(snd_use_case_mgr_t *uc_mgr,
 
                if (strcmp(id, "EnableSequence") == 0) {
                        uc_dbg("Parse EnableSequence");
-                       err = parse_sequence(uc_mgr, &verb->enable_list, cfg);
+                       err = parse_sequence(uc_mgr, &verb->enable_list, n);
                        if (err < 0) {
                                uc_error("error: failed to parse verb enable sequence");
                                return err;
@@ -631,7 +679,7 @@ static int parse_verb(snd_use_case_mgr_t *uc_mgr,
 
                if (strcmp(id, "DisableSequence") == 0) {
                        uc_dbg("Parse DisableSequence");
-                       err = parse_sequence(uc_mgr, &verb->disable_list, cfg);
+                       err = parse_sequence(uc_mgr, &verb->disable_list, n);
                        if (err < 0) {
                                uc_error("error: failed to parse verb disable sequence");
                                return err;
@@ -639,11 +687,11 @@ static int parse_verb(snd_use_case_mgr_t *uc_mgr,
                        continue;
                }
 
-               if (strcmp(id, "TransitionVerb") == 0) {
-                       uc_dbg("Parse TransitionVerb");
+               if (strcmp(id, "TransitionSequence") == 0) {
+                       uc_dbg("Parse TransitionSequence");
                        err = parse_transition(uc_mgr, &verb->transition_list, n);
                        if (err < 0) {
-                               uc_error("error: failed to parse transition verb");
+                               uc_error("error: failed to parse transition sequence");
                                return err;
                        }
                        continue;
@@ -682,6 +730,7 @@ static int parse_verb_file(snd_use_case_mgr_t *uc_mgr,
        struct use_case_verb *verb;
        snd_config_t *cfg;
        char filename[MAX_FILE];
+       char *env = getenv(ALSA_CONFIG_UCM_VAR);
        int err;
 
        /* allocate verb */
@@ -703,7 +752,8 @@ static int parse_verb_file(snd_use_case_mgr_t *uc_mgr,
                return -ENOMEM;
 
        /* open Verb file for reading */
-       snprintf(filename, sizeof(filename), "%s/%s/%s", ALSA_USE_CASE_DIR,
+       snprintf(filename, sizeof(filename), "%s/%s/%s",
+               env ? env : ALSA_USE_CASE_DIR,
                uc_mgr->card_name, file);
        filename[sizeof(filename)-1] = '\0';
        
@@ -832,16 +882,18 @@ static int parse_master_section(snd_use_case_mgr_t *uc_mgr, snd_config_t *cfg,
  */
 static int parse_controls(snd_use_case_mgr_t *uc_mgr, snd_config_t *cfg)
 {
-       struct list_head list;
        int err;
        
-       INIT_LIST_HEAD(&list);
-       err = parse_sequence(uc_mgr, &list, cfg);
+       if (!list_empty(&uc_mgr->default_list)) {
+               uc_error("Default list is not empty");
+               return -EINVAL;
+       }
+       err = parse_sequence(uc_mgr, &uc_mgr->default_list, cfg);
        if (err < 0) {
                uc_error("Unable to parse SectionDefaults");
                return err;
        }
-       printf("parse_controls - not yet implemented\n");
+       
        return 0;
 }
 
@@ -931,9 +983,6 @@ static int parse_master_file(snd_use_case_mgr_t *uc_mgr, snd_config_t *cfg)
        return 0;
 }
 
-/** The name of the environment variable containing the UCM directory */
-#define ALSA_CONFIG_UCM_VAR "ALSA_CONFIG_UCM"
-
 static int load_master_config(const char *card_name, snd_config_t **cfg)
 {
        char filename[MAX_FILE];
@@ -992,18 +1041,19 @@ static int filename_filter(const struct dirent *dirent)
 /* scan all cards and comments */
 int uc_mgr_scan_master_configs(const char **_list[])
 {
-       char filename[MAX_FILE];
+       char filename[MAX_FILE], dfl[MAX_FILE];
        char *env = getenv(ALSA_CONFIG_UCM_VAR);
        const char **list;
        snd_config_t *cfg, *c;
        int i, cnt, err;
+       ssize_t ss;
        struct dirent **namelist;
 
        snprintf(filename, sizeof(filename)-1,
                "%s", env ? env : ALSA_USE_CASE_DIR);
        filename[MAX_FILE-1] = '\0';
 
-       err = scandir(filename, &namelist, filename_filter, alphasort);
+       err = scandir(filename, &namelist, filename_filter, versionsort);
        if (err < 0) {
                err = -errno;
                uc_error("error: could not scan directory %s: %s",
@@ -1012,6 +1062,20 @@ int uc_mgr_scan_master_configs(const char **_list[])
        }
        cnt = err;
 
+       dfl[0] = '\0';
+       if (strlen(filename) + 8 < sizeof(filename)) {
+               strcat(filename, "/default");
+               ss = readlink(filename, dfl, sizeof(dfl)-1);
+               if (ss >= 0) {
+                       dfl[ss] = '\0';
+                       dfl[sizeof(dfl)-1] = '\0';
+                       if (dfl[0] && dfl[strlen(dfl)-1] == '/')
+                               dfl[strlen(dfl)-1] = '\0';
+               } else {
+                       dfl[0] = '\0';
+               }
+       }
+
        list = calloc(1, cnt * 2 * sizeof(char *));
        if (list == NULL) {
                err = -ENOMEM;
@@ -1036,6 +1100,14 @@ int uc_mgr_scan_master_configs(const char **_list[])
                        err = -ENOMEM;
                        goto __err;
                }
+               if (strcmp(dfl, list[i * 2]) == 0) {
+                       /* default to top */
+                       const char *save1 = list[i * 2];
+                       const char *save2 = list[i * 2 + 1];
+                       memmove(list + 2, list, i * 2 * sizeof(char *));
+                       list[0] = save1;
+                       list[1] = save2;
+               }
        }
        err = cnt * 2;
 
index 7dae5b6af5d5ecf88eb28170cd0d5fe852825f0a..0515de1727801af3b490c68b30caf9ab57e14194 100644 (file)
@@ -196,5 +196,6 @@ int uc_mgr_import_master_config(snd_use_case_mgr_t *uc_mgr);
 int uc_mgr_scan_master_configs(const char **_list[]);
 
 void uc_mgr_free_sequence_element(struct sequence_element *seq);
+void uc_mgr_free_transition_element(struct transition_sequence *seq);
 void uc_mgr_free_verb(snd_use_case_mgr_t *uc_mgr);
 void uc_mgr_free(snd_use_case_mgr_t *uc_mgr);
index 0f8207e8aeca0ccbe0ecdbd83f7a01a638286521..267a13c91c21791b1f38707083a14d43dec633cc 100644 (file)
@@ -94,7 +94,8 @@ void uc_mgr_free_value(struct list_head *base)
                val = list_entry(pos, struct ucm_value, list);
                free(val->name);
                free(val->data);
-               list_del(pos);
+               list_del(&val->list);
+               free(val);
        }
 }
 
@@ -106,8 +107,8 @@ void uc_mgr_free_dev_list(struct list_head *base)
        list_for_each_safe(pos, npos, base) {
                dlist = list_entry(pos, struct dev_list, list);
                free(dlist->name);
+               list_del(&dlist->list);
                free(dlist);
-               list_del(pos);
        }
 }
 
@@ -133,11 +134,18 @@ void uc_mgr_free_sequence(struct list_head *base)
        
        list_for_each_safe(pos, npos, base) {
                seq = list_entry(pos, struct sequence_element, list);
+               list_del(&seq->list);
                uc_mgr_free_sequence_element(seq);
-               list_del(pos);
        }
 }
 
+void uc_mgr_free_transition_element(struct transition_sequence *tseq)
+{
+       free(tseq->name);
+       uc_mgr_free_sequence(&tseq->transition_list);
+       free(tseq);
+}
+
 void uc_mgr_free_transition(struct list_head *base)
 {
        struct list_head *pos, *npos;
@@ -145,10 +153,8 @@ void uc_mgr_free_transition(struct list_head *base)
        
        list_for_each_safe(pos, npos, base) {
                tseq = list_entry(pos, struct transition_sequence, list);
-               free(tseq->name);
-               uc_mgr_free_sequence(&tseq->transition_list);
-               free(tseq);
-               list_del(pos);
+               list_del(&tseq->list);
+               uc_mgr_free_transition_element(tseq);
        }
 }
 
@@ -166,8 +172,8 @@ void uc_mgr_free_modifier(struct list_head *base)
                uc_mgr_free_transition(&mod->transition_list);
                uc_mgr_free_dev_list(&mod->dev_list);
                uc_mgr_free_value(&mod->value_list);
+               list_del(&mod->list);
                free(mod);
-               list_del(pos);
        }
 }
 
@@ -184,8 +190,8 @@ void uc_mgr_free_device(struct list_head *base)
                uc_mgr_free_sequence(&dev->disable_list);
                uc_mgr_free_transition(&dev->transition_list);
                uc_mgr_free_value(&dev->value_list);
+               list_del(&dev->list);
                free(dev);
-               list_del(pos);
        }
 }
 
@@ -204,8 +210,8 @@ void uc_mgr_free_verb(snd_use_case_mgr_t *uc_mgr)
                uc_mgr_free_value(&verb->value_list);
                uc_mgr_free_device(&verb->device_list);
                uc_mgr_free_modifier(&verb->modifier_list);
+               list_del(&verb->list);
                free(verb);
-               list_del(pos);
        }
        uc_mgr_free_sequence(&uc_mgr->default_list);
        free(uc_mgr->comment);
diff --git a/test/ucm/TestHDA/Case1.conf b/test/ucm/TestHDA/Case1.conf
new file mode 100644 (file)
index 0000000..65af260
--- /dev/null
@@ -0,0 +1,24 @@
+SectionVerb {
+       EnableSequence [
+               exec "Case1 enable seq"
+       ]
+       DisableSequence [
+               exec "Case2 disable seq"
+       ]
+       TransitionVerb."Case2" [
+               exec "Case1->Case2 transition seq"
+       ]
+       Value {
+               TestValue1 "123"
+       }
+}
+
+SectionDevice."Device1".0 {
+       
+}
+
+SectionModifier."Modifier1" {
+       SupportedDevice [
+               "Device1"
+       ]
+}
diff --git a/test/ucm/TestHDA/TestHDA.conf b/test/ucm/TestHDA/TestHDA.conf
new file mode 100644 (file)
index 0000000..9b93b96
--- /dev/null
@@ -0,0 +1,11 @@
+Comment "A test HDA card"
+
+SectionUseCase."Case1" {
+       File "Case1.conf"
+       Comment "Case1 Comment"
+}
+
+SectionDefaults [
+       exec "my prg"
+       msleep 1
+]