Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 0 additions & 25 deletions topology/pre-process-class.c
Original file line number Diff line number Diff line change
Expand Up @@ -150,31 +150,6 @@ snd_config_t *tplg_class_find_attribute_by_name(struct tplg_pre_processor *tplg_
return attr;
}

/* get the name of the attribute that must have a unique value in the object instance */
const char *tplg_class_get_unique_attribute_name(struct tplg_pre_processor *tplg_pp,
snd_config_t *class)
{
snd_config_t *unique;
const char *unique_name, *class_id;
int ret;

if (snd_config_get_id(class, &class_id) < 0)
return NULL;

ret = snd_config_search(class, "attributes.unique", &unique);
if (ret < 0) {
SNDERR("No unique attribute in class '%s'\n", class_id);
return NULL;
}

if (snd_config_get_string(unique, &unique_name) < 0) {
SNDERR("Invalid name for unique attribute in class '%s'\n", class_id);
return NULL;
}

return unique_name;
}

/* get attribute type from the definition */
snd_config_type_t tplg_class_get_attribute_type(struct tplg_pre_processor *tplg_pp,
snd_config_t *attr)
Expand Down
19 changes: 8 additions & 11 deletions topology/pre-process-object.c
Original file line number Diff line number Diff line change
Expand Up @@ -1500,26 +1500,23 @@ static int tplg_object_set_unique_attribute(struct tplg_pre_processor *tplg_pp,
const char *id)
{
snd_config_t *unique_attr, *new;
const char *unique_name, *class_id;
const char *class_id;
int ret;

if (snd_config_get_id(class_cfg, &class_id) < 0)
return 0;

/* find config for class unique attribute */
unique_name = tplg_class_get_unique_attribute_name(tplg_pp, class_cfg);
if (!unique_name)
return -ENOENT;

/* find the unique attribute definition in the class */
unique_attr = tplg_class_find_attribute_by_name(tplg_pp, class_cfg, unique_name);
if (!unique_attr)
unique_attr = tplg_class_find_attribute_by_name(tplg_pp, class_cfg, "instance");
if (!unique_attr) {
SNDERR("No instance attribute defined in class %s\n", class_id);
return -ENOENT;
}

/* override value if unique attribute is set in the object instance */
ret = snd_config_search(obj, unique_name, &new);
/* override instance if set in the object */
ret = snd_config_search(obj, "instance", &new);
if (ret < 0) {
ret = snd_config_make(&new, unique_name,
ret = snd_config_make(&new, "instance",
tplg_class_get_attribute_type(tplg_pp, unique_attr));
if (ret < 0) {
SNDERR("error creating new attribute cfg for object %s\n", id);
Expand Down
139 changes: 137 additions & 2 deletions topology/pre-processor.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@

#define SND_TOPOLOGY_MAX_PLUGINS 32

typedef void (*pre_process_config_function)(struct tplg_pre_processor *tplg_pp,
snd_config_t *instance_cfg, snd_config_t *parent,
long *id);

static int get_plugin_string(struct tplg_pre_processor *tplg_pp, char **plugin_string)
{
const char *lib_names_t = NULL;
Expand Down Expand Up @@ -427,10 +431,112 @@ static int pre_process_add_defines(struct tplg_pre_processor *tplg_pp, snd_confi
return 0;
}

/*
* helper function to walk through all child nodes in a given config and apply the config update
* at the tagetted node based on the config function.
*/
static void pre_process_config_at_level(struct tplg_pre_processor *tplg_pp,
pre_process_config_function func,
snd_config_t *cfg, int current_node_level,
int target_node_level, long *start_id)
{
snd_config_iterator_t i, next;

snd_config_for_each(i, next, cfg) {
snd_config_t *n;

n = snd_config_iterator_entry(i);
if (current_node_level < target_node_level) {
pre_process_config_at_level(tplg_pp, func, n, current_node_level + 1,
target_node_level, start_id);
continue;
}

func(tplg_pp, n, cfg, start_id);
}
}


/* helper function to update the instance ID */
static void pre_process_uniquify_instance_conf(struct tplg_pre_processor *tplg_pp,
snd_config_t *instance_cfg,
snd_config_t *parent, long *id)
{
const char*parent_id;
char *instance_id;

if (snd_config_get_id(parent, &parent_id) < 0)
return;

/* do not substitute instance ID's for objects that are included conditionally */
if (!strcmp(parent_id, "IncludeByKey"))
return;

instance_id = tplg_snprintf("%ld", (*id)++);
snd_config_set_id(instance_cfg, instance_id);
free(instance_id);
}

/*
* Included conf files could contain additional object instantiations with the same instance ID as
* top-level conf file. For example, the top-level conf file could contain a PCM object as below:
* Object.PCM {
* pcm.10 {
* name "ssp-capture"
* }
* }
* If the included conf file could contain a PCM object with the same instance ID of 1 like:
* Object.PCM {
* pcm.10 {
* name "DMIC"
* }
* }
*
* In this case when merging the above conf file with the top-level file, the first PCM object
* with name "ssp-capture" will get overridden with the new one "DMIC". To prevent this and make
* sure that 2 separate PCM instances are added, this function makes sure that the instance ID for
* the PCM object in the included file does not clash with the top-level object instances. So the
* new conf node will modified as below before getting merged.
* Object.PCM {
* pcm.11 {
* name "DMIC"
* }
* }
*
* All additional objects in the same included file or any subsequent includes will use
* incremental values starting from 1000
*/
static int pre_process_inspect_objects_in_conf(struct tplg_pre_processor *tplg_pp,
pre_process_config_function func,
snd_config_t *cfg, long *starting_id)
{
snd_config_iterator_t i, next;

snd_config_for_each(i, next, cfg) {
snd_config_t *n;
const char *id;

n = snd_config_iterator_entry(i);
if (snd_config_get_id(n, &id) < 0)
continue;

if (strcmp(id, "Object"))
continue;

/*
* modify the instance ID for all objects to ensure that they do not conflict with
* the instance ID's in the top-level conf.
*/
pre_process_config_at_level(tplg_pp, func, n, 1,
3, starting_id);
}
return 0;
}

static int pre_process_includes(struct tplg_pre_processor *tplg_pp, snd_config_t *top);

static int pre_process_include_conf(struct tplg_pre_processor *tplg_pp, snd_config_t *config,
snd_config_t **new, snd_config_t *variable)
snd_config_t **new, snd_config_t *variable, long *starting_id)
{
snd_config_iterator_t i, next;
const char *variable_name;
Expand Down Expand Up @@ -537,6 +643,14 @@ static int pre_process_include_conf(struct tplg_pre_processor *tplg_pp, snd_conf
fprintf(stderr, "Unable to load included configuration\n");
goto err;
}

ret = pre_process_inspect_objects_in_conf(tplg_pp,
pre_process_uniquify_instance_conf,
*new, starting_id);
if (ret < 0) {
fprintf(stderr, "Failed to uniquify included configuration\n");
goto err;
}
}

/* forcefully overwrite with defines from the command line */
Expand All @@ -557,16 +671,37 @@ static int pre_process_include_conf(struct tplg_pre_processor *tplg_pp, snd_conf
return ret;
}

static void pre_process_update_start_instance_id(struct tplg_pre_processor *tplg_pp,
snd_config_t *instance_cfg,
snd_config_t *parent, long *start_id)
{
const char *instance_id;
long instance;

if (snd_config_get_id(instance_cfg, &instance_id) < 0)
return;

instance = strtol(instance_id, NULL, 10);
if (instance > *start_id)
*start_id = instance;
}

static int pre_process_includes(struct tplg_pre_processor *tplg_pp, snd_config_t *top)
{
snd_config_iterator_t i, next;
snd_config_t *includes;
const char *top_id;
long start_id = 0;
int ret;

if (tplg_pp->define_cfg_merged == NULL)
return 0;

/* get the largest object instance ID in the top-level conf */
pre_process_inspect_objects_in_conf(tplg_pp, pre_process_update_start_instance_id,
top, &start_id);
start_id++;

ret = snd_config_search(top, "IncludeByKey", &includes);
if (ret < 0)
return 0;
Expand All @@ -589,7 +724,7 @@ static int pre_process_includes(struct tplg_pre_processor *tplg_pp, snd_config_t
}

/* create conf node from included file */
ret = pre_process_include_conf(tplg_pp, n, &new, define);
ret = pre_process_include_conf(tplg_pp, n, &new, define, &start_id);
if (ret < 0) {
fprintf(stderr, "Unable to process include file \n");
return ret;
Expand Down
2 changes: 0 additions & 2 deletions topology/pre-processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,6 @@ snd_config_t *tplg_class_find_attribute_by_name(struct tplg_pre_processor *tplg_
bool tplg_class_is_attribute_mandatory(const char *attr, snd_config_t *class_cfg);
bool tplg_class_is_attribute_immutable(const char *attr, snd_config_t *class_cfg);
bool tplg_class_is_attribute_unique(const char *attr, snd_config_t *class_cfg);
const char *tplg_class_get_unique_attribute_name(struct tplg_pre_processor *tplg_pp,
snd_config_t *class);
snd_config_type_t tplg_class_get_attribute_type(struct tplg_pre_processor *tplg_pp,
snd_config_t *attr);
const char *tplg_class_get_attribute_token_ref(struct tplg_pre_processor *tplg_pp,
Expand Down