On Fri, 2016-11-18 at 15:13 +0800, mengdong.lin@xxxxxxxxxxxxxxx wrote: > From: Mengdong Lin <mengdong.lin@xxxxxxxxxxxxxxx> > > A machine device's sequence can enable or disable a component device. So > when executing a machine device's sequence, the enable or disable sequence > of its component devices will also be excecuted. > > Components don't define card device cdev in their sequences. So before > executing a component device sequence, UCM manager will > - store cdev defined by the sequence of its parent, the machine device; > - mark itself entering 'component domain'. > > Then this cdev will be used to excute the sequence of the component > device. > > Signed-off-by: Mengdong Lin <mengdong.lin@xxxxxxxxxxxxxxx> > > diff --git a/src/ucm/main.c b/src/ucm/main.c > index 8cc9208..4a78877 100644 > --- a/src/ucm/main.c > +++ b/src/ucm/main.c > @@ -35,6 +35,7 @@ > #include <stdarg.h> > #include <pthread.h> > #include <sys/stat.h> > +#include <limits.h> > > /* > * misc > @@ -48,6 +49,30 @@ static int get_value3(char **value, > struct list_head *value_list2, > struct list_head *value_list3); > > +/* enter component domain and store cdev for the component */ > +#define ENTER_COMPONENT_DOMAIN(uc_mgr, cdev) \ > + do {\ > + (uc_mgr)->in_component_domain = 1;\ > + (uc_mgr)->cdev = (cdev);\ > + } while (0) > + > +/* exit component domain and clear cdev */ > +#define EXIT_COMPONENT_DOMAIN(uc_mgr) \ > + do {\ > + (uc_mgr)->in_component_domain = 0;\ > + (uc_mgr)->cdev = NULL;\ > + } while (0) > + Do we need these macros ? It seems like we only use these once. > +#define IN_COMPONENT_DOMAIN(uc_mgr) \ > + ((uc_mgr)->in_component_domain) > + cant see where we use this ? Is it not just better to use "if (uc_mgr->in_component_domain)" > +static int execute_component_seq(snd_use_case_mgr_t *uc_mgr, > + struct component_sequence *cmpt_seq, > + struct list_head *value_list1, > + struct list_head *value_list2, > + struct list_head *value_list3, > + char *cdev); > + > static int check_identifier(const char *identifier, const char *prefix) > { > int len; > @@ -366,7 +391,19 @@ static int execute_sequence(snd_use_case_mgr_t *uc_mgr, > case SEQUENCE_ELEMENT_TYPE_CSET: > case SEQUENCE_ELEMENT_TYPE_CSET_BIN_FILE: > case SEQUENCE_ELEMENT_TYPE_CSET_TLV: > - if (cdev == NULL) { > + if (cdev == NULL && IN_COMPONENT_DOMAIN(uc_mgr)) { > + /* For sequence of a component device, use > + * parent's cdev stored by ucm manager. > + */ > + if (uc_mgr->cdev == NULL) { > + uc_error("cdev is not defined!"); > + return err; > + } > + > + cdev = strndup(uc_mgr->cdev, PATH_MAX); > + if (!cdev) > + return -ENOMEM; > + } else if (cdev == NULL) { > char *playback_ctl = NULL; > char *capture_ctl = NULL; > > @@ -427,6 +464,19 @@ static int execute_sequence(snd_use_case_mgr_t *uc_mgr, > if (err < 0) > goto __fail; > break; > + case SEQUENCE_ELEMENT_TYPE_CMPT_SEQ: > + /* Execute enable or disable sequence of a component > + * device. Pass the cdev defined by the machine device. > + */ > + err = execute_component_seq(uc_mgr, > + &s->data.cmpt_seq, > + value_list1, > + value_list2, > + value_list3, > + cdev); > + if (err < 0) > + goto __fail; > + break; > default: > uc_error("unknown sequence command %i", s->type); > break; > @@ -442,6 +492,42 @@ static int execute_sequence(snd_use_case_mgr_t *uc_mgr, > > } > > +/* Execute enable or disable sequence of a component device. > + * > + * For a component device (a codec or embedded DSP), its sequence doesn't > + * specify the sound card device 'cdev', because a component can be reused > + * by different sound cards (machines). So when executing its sequence, a > + * parameter 'cdev' is used to pass cdev defined by the sequence of its > + * parent, the machine device. UCM manger will store the cdev when entering > + * the component domain. > + */ > +static int execute_component_seq(snd_use_case_mgr_t *uc_mgr, > + struct component_sequence *cmpt_seq, > + struct list_head *value_list1, > + struct list_head *value_list2, > + struct list_head *value_list3, > + char *cdev) > +{ > + struct use_case_device *device = cmpt_seq->device; > + struct list_head *seq; > + int err; > + > + ENTER_COMPONENT_DOMAIN(uc_mgr, cdev); > + > + if (cmpt_seq->enable) > + seq = &device->enable_list; > + else > + seq = &device->disable_list; > + > + err = execute_sequence(uc_mgr, seq, > + &device->value_list, > + &uc_mgr->active_verb->value_list, > + &uc_mgr->value_list); > + > + EXIT_COMPONENT_DOMAIN(uc_mgr); > + return err; > +} > + > /** > * \brief Import master config and execute the default sequence > * \param uc_mgr Use case manager > diff --git a/src/ucm/ucm_local.h b/src/ucm/ucm_local.h > index 3bfdd67..614e786 100644 > --- a/src/ucm/ucm_local.h > +++ b/src/ucm/ucm_local.h > @@ -212,6 +212,14 @@ struct snd_use_case_mgr { > /* change to list of ctl handles */ > snd_ctl_t *ctl; > char *ctl_dev; > + > + /* Components don't define cdev, the card device. When executing > + * a sequence of a component device, ucm manager enters component > + * domain and needs to provide cdev to the component. This cdev > + * should be defined by the machine, parent of the component. > + */ > + int in_component_domain; > + char *cdev; > }; > > #define uc_error SNDERR _______________________________________________ Alsa-devel mailing list Alsa-devel@xxxxxxxxxxxxxxxx http://mailman.alsa-project.org/mailman/listinfo/alsa-devel