1c72fcc34Sopenharmony_ci/* 2c72fcc34Sopenharmony_ci Copyright(c) 2021 Intel Corporation 3c72fcc34Sopenharmony_ci All rights reserved. 4c72fcc34Sopenharmony_ci 5c72fcc34Sopenharmony_ci This program is free software; you can redistribute it and/or modify 6c72fcc34Sopenharmony_ci it under the terms of version 2 of the GNU General Public License as 7c72fcc34Sopenharmony_ci published by the Free Software Foundation. 8c72fcc34Sopenharmony_ci 9c72fcc34Sopenharmony_ci This program is distributed in the hope that it will be useful, but 10c72fcc34Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 11c72fcc34Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12c72fcc34Sopenharmony_ci General Public License for more details. 13c72fcc34Sopenharmony_ci 14c72fcc34Sopenharmony_ci You should have received a copy of the GNU General Public License 15c72fcc34Sopenharmony_ci along with this program; if not, write to the Free Software 16c72fcc34Sopenharmony_ci Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 17c72fcc34Sopenharmony_ci The full GNU General Public License is included in this distribution 18c72fcc34Sopenharmony_ci in the file called LICENSE.GPL. 19c72fcc34Sopenharmony_ci*/ 20c72fcc34Sopenharmony_ci#include "aconfig.h" 21c72fcc34Sopenharmony_ci#include <assert.h> 22c72fcc34Sopenharmony_ci#include <errno.h> 23c72fcc34Sopenharmony_ci#include <stddef.h> 24c72fcc34Sopenharmony_ci#include <stdio.h> 25c72fcc34Sopenharmony_ci#include <string.h> 26c72fcc34Sopenharmony_ci#include <ctype.h> 27c72fcc34Sopenharmony_ci#include <alsa/asoundlib.h> 28c72fcc34Sopenharmony_ci#include "gettext.h" 29c72fcc34Sopenharmony_ci#include "topology.h" 30c72fcc34Sopenharmony_ci#include "pre-processor.h" 31c72fcc34Sopenharmony_ci 32c72fcc34Sopenharmony_ci/* Parse VendorToken object, create the "SectionVendorToken" and save it */ 33c72fcc34Sopenharmony_ciint tplg_build_vendor_token_object(struct tplg_pre_processor *tplg_pp, 34c72fcc34Sopenharmony_ci snd_config_t *obj_cfg, 35c72fcc34Sopenharmony_ci snd_config_t *parent ATTRIBUTE_UNUSED) 36c72fcc34Sopenharmony_ci{ 37c72fcc34Sopenharmony_ci snd_config_iterator_t i, next; 38c72fcc34Sopenharmony_ci snd_config_t *vtop, *n, *obj; 39c72fcc34Sopenharmony_ci const char *name; 40c72fcc34Sopenharmony_ci int ret; 41c72fcc34Sopenharmony_ci 42c72fcc34Sopenharmony_ci ret = tplg_build_object_from_template(tplg_pp, obj_cfg, &vtop, NULL, false); 43c72fcc34Sopenharmony_ci if (ret < 0) 44c72fcc34Sopenharmony_ci return ret; 45c72fcc34Sopenharmony_ci 46c72fcc34Sopenharmony_ci ret = snd_config_get_id(vtop, &name); 47c72fcc34Sopenharmony_ci if (ret < 0) 48c72fcc34Sopenharmony_ci return ret; 49c72fcc34Sopenharmony_ci 50c72fcc34Sopenharmony_ci /* add the tuples */ 51c72fcc34Sopenharmony_ci obj = tplg_object_get_instance_config(tplg_pp, obj_cfg); 52c72fcc34Sopenharmony_ci snd_config_for_each(i, next, obj) { 53c72fcc34Sopenharmony_ci snd_config_t *dst; 54c72fcc34Sopenharmony_ci const char *id; 55c72fcc34Sopenharmony_ci 56c72fcc34Sopenharmony_ci n = snd_config_iterator_entry(i); 57c72fcc34Sopenharmony_ci 58c72fcc34Sopenharmony_ci if (snd_config_get_id(n, &id) < 0) 59c72fcc34Sopenharmony_ci continue; 60c72fcc34Sopenharmony_ci 61c72fcc34Sopenharmony_ci if (!strcmp(id, "name")) 62c72fcc34Sopenharmony_ci continue; 63c72fcc34Sopenharmony_ci 64c72fcc34Sopenharmony_ci ret = snd_config_copy(&dst, n); 65c72fcc34Sopenharmony_ci if (ret < 0) { 66c72fcc34Sopenharmony_ci SNDERR("Error copying config node %s for '%s'\n", id, name); 67c72fcc34Sopenharmony_ci return ret; 68c72fcc34Sopenharmony_ci } 69c72fcc34Sopenharmony_ci 70c72fcc34Sopenharmony_ci ret = snd_config_add(vtop, dst); 71c72fcc34Sopenharmony_ci if (ret < 0) { 72c72fcc34Sopenharmony_ci snd_config_delete(dst); 73c72fcc34Sopenharmony_ci SNDERR("Error adding vendortoken %s for %s\n", id, name); 74c72fcc34Sopenharmony_ci return ret; 75c72fcc34Sopenharmony_ci } 76c72fcc34Sopenharmony_ci } 77c72fcc34Sopenharmony_ci 78c72fcc34Sopenharmony_ci return ret; 79c72fcc34Sopenharmony_ci} 80c72fcc34Sopenharmony_ci 81c72fcc34Sopenharmony_ciint tplg_parent_update(struct tplg_pre_processor *tplg_pp, snd_config_t *parent, 82c72fcc34Sopenharmony_ci const char *section_name, const char *item_name) 83c72fcc34Sopenharmony_ci{ 84c72fcc34Sopenharmony_ci snd_config_iterator_t i, next; 85c72fcc34Sopenharmony_ci snd_config_t *child, *cfg, *top, *item_config, *n; 86c72fcc34Sopenharmony_ci const char *parent_name; 87c72fcc34Sopenharmony_ci char *item_id; 88c72fcc34Sopenharmony_ci int ret, id = 0; 89c72fcc34Sopenharmony_ci 90c72fcc34Sopenharmony_ci /* Nothing to do if parent is NULL */ 91c72fcc34Sopenharmony_ci if (!parent) 92c72fcc34Sopenharmony_ci return 0; 93c72fcc34Sopenharmony_ci 94c72fcc34Sopenharmony_ci child = tplg_object_get_instance_config(tplg_pp, parent); 95c72fcc34Sopenharmony_ci ret = snd_config_search(child, "name", &cfg); 96c72fcc34Sopenharmony_ci if (ret < 0) { 97c72fcc34Sopenharmony_ci ret = snd_config_get_id(child, &parent_name); 98c72fcc34Sopenharmony_ci if (ret < 0) { 99c72fcc34Sopenharmony_ci SNDERR("No name config for parent\n"); 100c72fcc34Sopenharmony_ci return ret; 101c72fcc34Sopenharmony_ci } 102c72fcc34Sopenharmony_ci } else { 103c72fcc34Sopenharmony_ci ret = snd_config_get_string(cfg, &parent_name); 104c72fcc34Sopenharmony_ci if (ret < 0) { 105c72fcc34Sopenharmony_ci SNDERR("Invalid name for parent\n"); 106c72fcc34Sopenharmony_ci return ret; 107c72fcc34Sopenharmony_ci } 108c72fcc34Sopenharmony_ci } 109c72fcc34Sopenharmony_ci 110c72fcc34Sopenharmony_ci top = tplg_object_get_section(tplg_pp, parent); 111c72fcc34Sopenharmony_ci if (!top) 112c72fcc34Sopenharmony_ci return -EINVAL; 113c72fcc34Sopenharmony_ci 114c72fcc34Sopenharmony_ci /* get config with name */ 115c72fcc34Sopenharmony_ci cfg = tplg_find_config(top, parent_name); 116c72fcc34Sopenharmony_ci if (!cfg) 117c72fcc34Sopenharmony_ci return ret; 118c72fcc34Sopenharmony_ci 119c72fcc34Sopenharmony_ci /* get section config */ 120c72fcc34Sopenharmony_ci if (!strcmp(section_name, "tlv") || !strcmp(section_name, "texts")) { 121c72fcc34Sopenharmony_ci /* set tlv name if config exists already */ 122c72fcc34Sopenharmony_ci ret = snd_config_search(cfg, section_name, &item_config); 123c72fcc34Sopenharmony_ci if (ret < 0) { 124c72fcc34Sopenharmony_ci ret = tplg_config_make_add(&item_config, section_name, 125c72fcc34Sopenharmony_ci SND_CONFIG_TYPE_STRING, cfg); 126c72fcc34Sopenharmony_ci if (ret < 0) { 127c72fcc34Sopenharmony_ci SNDERR("Error creating section config widget %s for %s\n", 128c72fcc34Sopenharmony_ci section_name, parent_name); 129c72fcc34Sopenharmony_ci return ret; 130c72fcc34Sopenharmony_ci } 131c72fcc34Sopenharmony_ci } 132c72fcc34Sopenharmony_ci 133c72fcc34Sopenharmony_ci return snd_config_set_string(item_config, item_name); 134c72fcc34Sopenharmony_ci } 135c72fcc34Sopenharmony_ci 136c72fcc34Sopenharmony_ci ret = snd_config_search(cfg, section_name, &item_config); 137c72fcc34Sopenharmony_ci if (ret < 0) { 138c72fcc34Sopenharmony_ci ret = tplg_config_make_add(&item_config, section_name, 139c72fcc34Sopenharmony_ci SND_CONFIG_TYPE_COMPOUND, cfg); 140c72fcc34Sopenharmony_ci if (ret < 0) { 141c72fcc34Sopenharmony_ci SNDERR("Error creating section config widget %s for %s\n", 142c72fcc34Sopenharmony_ci section_name, parent_name); 143c72fcc34Sopenharmony_ci return ret; 144c72fcc34Sopenharmony_ci } 145c72fcc34Sopenharmony_ci } 146c72fcc34Sopenharmony_ci 147c72fcc34Sopenharmony_ci snd_config_for_each(i, next, item_config) { 148c72fcc34Sopenharmony_ci const char *name; 149c72fcc34Sopenharmony_ci 150c72fcc34Sopenharmony_ci n = snd_config_iterator_entry(i); 151c72fcc34Sopenharmony_ci if (snd_config_get_string(n, &name) < 0) 152c72fcc34Sopenharmony_ci continue; 153c72fcc34Sopenharmony_ci 154c72fcc34Sopenharmony_ci /* item already exists */ 155c72fcc34Sopenharmony_ci if (!strcmp(name, item_name)) 156c72fcc34Sopenharmony_ci return 0; 157c72fcc34Sopenharmony_ci id++; 158c72fcc34Sopenharmony_ci } 159c72fcc34Sopenharmony_ci 160c72fcc34Sopenharmony_ci /* add new item */ 161c72fcc34Sopenharmony_ci item_id = tplg_snprintf("%d", id); 162c72fcc34Sopenharmony_ci if (!item_id) 163c72fcc34Sopenharmony_ci return -ENOMEM; 164c72fcc34Sopenharmony_ci 165c72fcc34Sopenharmony_ci ret = snd_config_make(&cfg, item_id, SND_CONFIG_TYPE_STRING); 166c72fcc34Sopenharmony_ci free(item_id); 167c72fcc34Sopenharmony_ci if (ret < 0) 168c72fcc34Sopenharmony_ci return ret; 169c72fcc34Sopenharmony_ci 170c72fcc34Sopenharmony_ci ret = snd_config_set_string(cfg, item_name); 171c72fcc34Sopenharmony_ci if (ret < 0) 172c72fcc34Sopenharmony_ci return ret; 173c72fcc34Sopenharmony_ci 174c72fcc34Sopenharmony_ci ret = snd_config_add(item_config, cfg); 175c72fcc34Sopenharmony_ci if (ret < 0) 176c72fcc34Sopenharmony_ci snd_config_delete(cfg); 177c72fcc34Sopenharmony_ci 178c72fcc34Sopenharmony_ci return ret; 179c72fcc34Sopenharmony_ci} 180c72fcc34Sopenharmony_ci 181c72fcc34Sopenharmony_ci/* Parse data object, create the "SectionData" and save it. Only "bytes" data supported for now */ 182c72fcc34Sopenharmony_ciint tplg_build_data_object(struct tplg_pre_processor *tplg_pp, snd_config_t *obj_cfg, 183c72fcc34Sopenharmony_ci snd_config_t *parent) 184c72fcc34Sopenharmony_ci{ 185c72fcc34Sopenharmony_ci snd_config_t *dtop; 186c72fcc34Sopenharmony_ci const char *name; 187c72fcc34Sopenharmony_ci int ret; 188c72fcc34Sopenharmony_ci 189c72fcc34Sopenharmony_ci ret = tplg_build_object_from_template(tplg_pp, obj_cfg, &dtop, NULL, false); 190c72fcc34Sopenharmony_ci if (ret < 0) 191c72fcc34Sopenharmony_ci return ret; 192c72fcc34Sopenharmony_ci 193c72fcc34Sopenharmony_ci ret = snd_config_get_id(dtop, &name); 194c72fcc34Sopenharmony_ci if (ret < 0) 195c72fcc34Sopenharmony_ci return ret; 196c72fcc34Sopenharmony_ci 197c72fcc34Sopenharmony_ci return tplg_parent_update(tplg_pp, parent, "data", name); 198c72fcc34Sopenharmony_ci} 199c72fcc34Sopenharmony_ci 200c72fcc34Sopenharmony_cistatic int tplg_create_config_template(struct tplg_pre_processor *tplg_pp ATTRIBUTE_UNUSED, 201c72fcc34Sopenharmony_ci snd_config_t **template, 202c72fcc34Sopenharmony_ci const struct config_template_items *items) 203c72fcc34Sopenharmony_ci{ 204c72fcc34Sopenharmony_ci snd_config_t *top, *child; 205c72fcc34Sopenharmony_ci int ret, i; 206c72fcc34Sopenharmony_ci 207c72fcc34Sopenharmony_ci ret = snd_config_make(&top, "template", SND_CONFIG_TYPE_COMPOUND); 208c72fcc34Sopenharmony_ci if (ret < 0) 209c72fcc34Sopenharmony_ci return ret; 210c72fcc34Sopenharmony_ci 211c72fcc34Sopenharmony_ci /* add integer configs */ 212c72fcc34Sopenharmony_ci for (i = 0; i < MAX_CONFIGS_IN_TEMPLATE; i++) 213c72fcc34Sopenharmony_ci if (items->int_config_ids[i]) { 214c72fcc34Sopenharmony_ci ret = tplg_config_make_add(&child, items->int_config_ids[i], 215c72fcc34Sopenharmony_ci SND_CONFIG_TYPE_INTEGER, top); 216c72fcc34Sopenharmony_ci if (ret < 0) 217c72fcc34Sopenharmony_ci goto err; 218c72fcc34Sopenharmony_ci } 219c72fcc34Sopenharmony_ci 220c72fcc34Sopenharmony_ci /* add string configs */ 221c72fcc34Sopenharmony_ci for (i = 0; i < MAX_CONFIGS_IN_TEMPLATE; i++) 222c72fcc34Sopenharmony_ci if (items->string_config_ids[i]) { 223c72fcc34Sopenharmony_ci ret = tplg_config_make_add(&child, items->string_config_ids[i], 224c72fcc34Sopenharmony_ci SND_CONFIG_TYPE_STRING, top); 225c72fcc34Sopenharmony_ci if (ret < 0) 226c72fcc34Sopenharmony_ci goto err; 227c72fcc34Sopenharmony_ci } 228c72fcc34Sopenharmony_ci 229c72fcc34Sopenharmony_ci /* add compound configs */ 230c72fcc34Sopenharmony_ci for (i = 0; i < MAX_CONFIGS_IN_TEMPLATE; i++) { 231c72fcc34Sopenharmony_ci if (items->compound_config_ids[i]) { 232c72fcc34Sopenharmony_ci ret = tplg_config_make_add(&child, items->compound_config_ids[i], 233c72fcc34Sopenharmony_ci SND_CONFIG_TYPE_COMPOUND, top); 234c72fcc34Sopenharmony_ci if (ret < 0) 235c72fcc34Sopenharmony_ci goto err; 236c72fcc34Sopenharmony_ci } 237c72fcc34Sopenharmony_ci } 238c72fcc34Sopenharmony_ci 239c72fcc34Sopenharmony_cierr: 240c72fcc34Sopenharmony_ci if (ret < 0) { 241c72fcc34Sopenharmony_ci snd_config_delete(top); 242c72fcc34Sopenharmony_ci return ret; 243c72fcc34Sopenharmony_ci } 244c72fcc34Sopenharmony_ci 245c72fcc34Sopenharmony_ci *template = top; 246c72fcc34Sopenharmony_ci return ret; 247c72fcc34Sopenharmony_ci} 248c72fcc34Sopenharmony_ci 249c72fcc34Sopenharmony_cistatic void tplg_attribute_print_valid_values(snd_config_t *valid_values, const char *name) 250c72fcc34Sopenharmony_ci{ 251c72fcc34Sopenharmony_ci snd_config_iterator_t i, next; 252c72fcc34Sopenharmony_ci snd_config_t *n; 253c72fcc34Sopenharmony_ci 254c72fcc34Sopenharmony_ci SNDERR("valid values for attribute %s are:\n", name); 255c72fcc34Sopenharmony_ci 256c72fcc34Sopenharmony_ci snd_config_for_each(i, next, valid_values) { 257c72fcc34Sopenharmony_ci const char *s, *id; 258c72fcc34Sopenharmony_ci 259c72fcc34Sopenharmony_ci n = snd_config_iterator_entry(i); 260c72fcc34Sopenharmony_ci if (snd_config_get_id(n, &id) < 0) 261c72fcc34Sopenharmony_ci continue; 262c72fcc34Sopenharmony_ci 263c72fcc34Sopenharmony_ci if (snd_config_get_string(n, &s) < 0) 264c72fcc34Sopenharmony_ci continue; 265c72fcc34Sopenharmony_ci 266c72fcc34Sopenharmony_ci SNDERR("%s", s); 267c72fcc34Sopenharmony_ci } 268c72fcc34Sopenharmony_ci} 269c72fcc34Sopenharmony_ci 270c72fcc34Sopenharmony_ci/* check is attribute value belongs in the set of valid values */ 271c72fcc34Sopenharmony_cistatic bool tplg_is_attribute_valid_value(snd_config_t *valid_values, const char *value) 272c72fcc34Sopenharmony_ci{ 273c72fcc34Sopenharmony_ci snd_config_iterator_t i, next; 274c72fcc34Sopenharmony_ci snd_config_t *n; 275c72fcc34Sopenharmony_ci 276c72fcc34Sopenharmony_ci snd_config_for_each(i, next, valid_values) { 277c72fcc34Sopenharmony_ci const char *s, *id; 278c72fcc34Sopenharmony_ci 279c72fcc34Sopenharmony_ci n = snd_config_iterator_entry(i); 280c72fcc34Sopenharmony_ci if (snd_config_get_id(n, &id) < 0) 281c72fcc34Sopenharmony_ci continue; 282c72fcc34Sopenharmony_ci 283c72fcc34Sopenharmony_ci if (snd_config_get_string(n, &s) < 0) 284c72fcc34Sopenharmony_ci continue; 285c72fcc34Sopenharmony_ci 286c72fcc34Sopenharmony_ci if (!strcmp(value, s)) 287c72fcc34Sopenharmony_ci return true; 288c72fcc34Sopenharmony_ci } 289c72fcc34Sopenharmony_ci 290c72fcc34Sopenharmony_ci return false; 291c72fcc34Sopenharmony_ci} 292c72fcc34Sopenharmony_ci 293c72fcc34Sopenharmony_ci#if SND_LIB_VER(1, 2, 5) < SND_LIB_VERSION 294c72fcc34Sopenharmony_cistatic int pre_process_find_variable(snd_config_t **dst, const char *str, snd_config_t *config); 295c72fcc34Sopenharmony_ci 296c72fcc34Sopenharmony_ci/* check is attribute value belongs in the set of valid values after expanding the valid values */ 297c72fcc34Sopenharmony_cistatic bool tplg_is_attribute_valid_expanded_value(struct tplg_pre_processor *tplg_pp, 298c72fcc34Sopenharmony_ci snd_config_t *valid_values, int value) 299c72fcc34Sopenharmony_ci{ 300c72fcc34Sopenharmony_ci snd_config_iterator_t i, next; 301c72fcc34Sopenharmony_ci snd_config_t *n, *var, *conf_defines; 302c72fcc34Sopenharmony_ci int ret; 303c72fcc34Sopenharmony_ci 304c72fcc34Sopenharmony_ci ret = snd_config_search(tplg_pp->input_cfg, "Define", &conf_defines); 305c72fcc34Sopenharmony_ci if (ret < 0) 306c72fcc34Sopenharmony_ci return false; 307c72fcc34Sopenharmony_ci 308c72fcc34Sopenharmony_ci snd_config_for_each(i, next, valid_values) { 309c72fcc34Sopenharmony_ci const char *s, *id; 310c72fcc34Sopenharmony_ci long v; 311c72fcc34Sopenharmony_ci 312c72fcc34Sopenharmony_ci n = snd_config_iterator_entry(i); 313c72fcc34Sopenharmony_ci if (snd_config_get_id(n, &id) < 0) 314c72fcc34Sopenharmony_ci continue; 315c72fcc34Sopenharmony_ci 316c72fcc34Sopenharmony_ci if (snd_config_get_string(n, &s) < 0) 317c72fcc34Sopenharmony_ci continue; 318c72fcc34Sopenharmony_ci 319c72fcc34Sopenharmony_ci if (s[0] != '$') 320c72fcc34Sopenharmony_ci continue; 321c72fcc34Sopenharmony_ci 322c72fcc34Sopenharmony_ci /* find the variable definition */ 323c72fcc34Sopenharmony_ci ret = pre_process_find_variable(&var, s + 1, conf_defines); 324c72fcc34Sopenharmony_ci if (ret < 0) { 325c72fcc34Sopenharmony_ci SNDERR("No definition for variable %s\n", s + 1); 326c72fcc34Sopenharmony_ci return false; 327c72fcc34Sopenharmony_ci } 328c72fcc34Sopenharmony_ci 329c72fcc34Sopenharmony_ci if (snd_config_get_integer(var, &v) < 0) { 330c72fcc34Sopenharmony_ci SNDERR("Invalid definition for %s\n", s); 331c72fcc34Sopenharmony_ci snd_config_delete(var); 332c72fcc34Sopenharmony_ci return false; 333c72fcc34Sopenharmony_ci } 334c72fcc34Sopenharmony_ci 335c72fcc34Sopenharmony_ci snd_config_delete(var); 336c72fcc34Sopenharmony_ci 337c72fcc34Sopenharmony_ci if (value == v) 338c72fcc34Sopenharmony_ci return true; 339c72fcc34Sopenharmony_ci } 340c72fcc34Sopenharmony_ci 341c72fcc34Sopenharmony_ci return false; 342c72fcc34Sopenharmony_ci} 343c72fcc34Sopenharmony_ci#endif 344c72fcc34Sopenharmony_ci 345c72fcc34Sopenharmony_ci/* check if attribute value passes the min/max value constraints */ 346c72fcc34Sopenharmony_cistatic bool tplg_object_is_attribute_min_max_valid(snd_config_t *attr, snd_config_t *obj_attr, 347c72fcc34Sopenharmony_ci bool min_check) 348c72fcc34Sopenharmony_ci{ 349c72fcc34Sopenharmony_ci snd_config_type_t type = snd_config_get_type(obj_attr); 350c72fcc34Sopenharmony_ci snd_config_t *valid; 351c72fcc34Sopenharmony_ci const char *attr_name; 352c72fcc34Sopenharmony_ci int ret; 353c72fcc34Sopenharmony_ci 354c72fcc34Sopenharmony_ci if (snd_config_get_id(attr, &attr_name) < 0) 355c72fcc34Sopenharmony_ci return false; 356c72fcc34Sopenharmony_ci 357c72fcc34Sopenharmony_ci if (min_check) { 358c72fcc34Sopenharmony_ci ret = snd_config_search(attr, "constraints.min", &valid); 359c72fcc34Sopenharmony_ci if (ret < 0) 360c72fcc34Sopenharmony_ci return true; 361c72fcc34Sopenharmony_ci } else { 362c72fcc34Sopenharmony_ci ret = snd_config_search(attr, "constraints.max", &valid); 363c72fcc34Sopenharmony_ci if (ret < 0) 364c72fcc34Sopenharmony_ci return true; 365c72fcc34Sopenharmony_ci } 366c72fcc34Sopenharmony_ci 367c72fcc34Sopenharmony_ci switch(type) { 368c72fcc34Sopenharmony_ci case SND_CONFIG_TYPE_INTEGER: 369c72fcc34Sopenharmony_ci { 370c72fcc34Sopenharmony_ci long v, m; 371c72fcc34Sopenharmony_ci 372c72fcc34Sopenharmony_ci if (snd_config_get_integer(valid, &m) < 0) 373c72fcc34Sopenharmony_ci return true; 374c72fcc34Sopenharmony_ci 375c72fcc34Sopenharmony_ci if (snd_config_get_integer(obj_attr, &v) < 0) 376c72fcc34Sopenharmony_ci return false; 377c72fcc34Sopenharmony_ci 378c72fcc34Sopenharmony_ci if (min_check) { 379c72fcc34Sopenharmony_ci if (v < m) { 380c72fcc34Sopenharmony_ci SNDERR("attribute '%s' value: %ld is less than min value: %d\n", 381c72fcc34Sopenharmony_ci attr_name, v, m); 382c72fcc34Sopenharmony_ci return false; 383c72fcc34Sopenharmony_ci } 384c72fcc34Sopenharmony_ci } else { 385c72fcc34Sopenharmony_ci if (v > m) { 386c72fcc34Sopenharmony_ci SNDERR("attribute '%s' value: %ld is greater than max value: %d\n", 387c72fcc34Sopenharmony_ci attr_name, v, m); 388c72fcc34Sopenharmony_ci return false; 389c72fcc34Sopenharmony_ci } 390c72fcc34Sopenharmony_ci } 391c72fcc34Sopenharmony_ci 392c72fcc34Sopenharmony_ci return true; 393c72fcc34Sopenharmony_ci } 394c72fcc34Sopenharmony_ci case SND_CONFIG_TYPE_INTEGER64: 395c72fcc34Sopenharmony_ci { 396c72fcc34Sopenharmony_ci long long v; 397c72fcc34Sopenharmony_ci long m; 398c72fcc34Sopenharmony_ci 399c72fcc34Sopenharmony_ci if (snd_config_get_integer(valid, &m) < 0) 400c72fcc34Sopenharmony_ci return true; 401c72fcc34Sopenharmony_ci 402c72fcc34Sopenharmony_ci if (snd_config_get_integer64(obj_attr, &v) < 0) 403c72fcc34Sopenharmony_ci return false; 404c72fcc34Sopenharmony_ci 405c72fcc34Sopenharmony_ci if (min_check) { 406c72fcc34Sopenharmony_ci if (v < m) { 407c72fcc34Sopenharmony_ci SNDERR("attribute '%s' value: %ld is less than min value: %d\n", 408c72fcc34Sopenharmony_ci attr_name, v, m); 409c72fcc34Sopenharmony_ci return false; 410c72fcc34Sopenharmony_ci } 411c72fcc34Sopenharmony_ci } else { 412c72fcc34Sopenharmony_ci if (v > m) { 413c72fcc34Sopenharmony_ci SNDERR("attribute '%s' value: %ld is greater than max value: %d\n", 414c72fcc34Sopenharmony_ci attr_name, v, m); 415c72fcc34Sopenharmony_ci return false; 416c72fcc34Sopenharmony_ci } 417c72fcc34Sopenharmony_ci } 418c72fcc34Sopenharmony_ci 419c72fcc34Sopenharmony_ci return true; 420c72fcc34Sopenharmony_ci } 421c72fcc34Sopenharmony_ci default: 422c72fcc34Sopenharmony_ci break; 423c72fcc34Sopenharmony_ci } 424c72fcc34Sopenharmony_ci 425c72fcc34Sopenharmony_ci return false; 426c72fcc34Sopenharmony_ci} 427c72fcc34Sopenharmony_ci 428c72fcc34Sopenharmony_ci/* check for min/max and valid value constraints */ 429c72fcc34Sopenharmony_cistatic bool tplg_object_is_attribute_valid(struct tplg_pre_processor *tplg_pp, 430c72fcc34Sopenharmony_ci snd_config_t *attr, snd_config_t *obj_attr) 431c72fcc34Sopenharmony_ci{ 432c72fcc34Sopenharmony_ci snd_config_iterator_t i, next; 433c72fcc34Sopenharmony_ci snd_config_t *valid, *n; 434c72fcc34Sopenharmony_ci snd_config_type_t type; 435c72fcc34Sopenharmony_ci const char *attr_name, *obj_value; 436c72fcc34Sopenharmony_ci int ret; 437c72fcc34Sopenharmony_ci 438c72fcc34Sopenharmony_ci if (snd_config_get_id(attr, &attr_name) < 0) 439c72fcc34Sopenharmony_ci return false; 440c72fcc34Sopenharmony_ci 441c72fcc34Sopenharmony_ci type = snd_config_get_type(obj_attr); 442c72fcc34Sopenharmony_ci 443c72fcc34Sopenharmony_ci /* check if attribute has valid values */ 444c72fcc34Sopenharmony_ci ret = snd_config_search(attr, "constraints.valid_values", &valid); 445c72fcc34Sopenharmony_ci if (ret < 0) 446c72fcc34Sopenharmony_ci goto min_max_check; 447c72fcc34Sopenharmony_ci 448c72fcc34Sopenharmony_ci switch(type) { 449c72fcc34Sopenharmony_ci case SND_CONFIG_TYPE_STRING: 450c72fcc34Sopenharmony_ci if (snd_config_get_string(obj_attr, &obj_value) < 0) 451c72fcc34Sopenharmony_ci return false; 452c72fcc34Sopenharmony_ci if (!tplg_is_attribute_valid_value(valid, obj_value)) { 453c72fcc34Sopenharmony_ci tplg_attribute_print_valid_values(valid, attr_name); 454c72fcc34Sopenharmony_ci return false; 455c72fcc34Sopenharmony_ci } 456c72fcc34Sopenharmony_ci return true; 457c72fcc34Sopenharmony_ci case SND_CONFIG_TYPE_COMPOUND: 458c72fcc34Sopenharmony_ci snd_config_for_each(i, next, obj_attr) { 459c72fcc34Sopenharmony_ci const char *s, *id; 460c72fcc34Sopenharmony_ci 461c72fcc34Sopenharmony_ci n = snd_config_iterator_entry(i); 462c72fcc34Sopenharmony_ci if (snd_config_get_id(n, &id) < 0) 463c72fcc34Sopenharmony_ci continue; 464c72fcc34Sopenharmony_ci 465c72fcc34Sopenharmony_ci if (snd_config_get_string(n, &s) < 0) 466c72fcc34Sopenharmony_ci continue; 467c72fcc34Sopenharmony_ci 468c72fcc34Sopenharmony_ci if (!tplg_is_attribute_valid_value(valid, s)) { 469c72fcc34Sopenharmony_ci tplg_attribute_print_valid_values(valid, attr_name); 470c72fcc34Sopenharmony_ci return false; 471c72fcc34Sopenharmony_ci } 472c72fcc34Sopenharmony_ci } 473c72fcc34Sopenharmony_ci return true; 474c72fcc34Sopenharmony_ci#if SND_LIB_VER(1, 2, 5) < SND_LIB_VERSION 475c72fcc34Sopenharmony_ci case SND_CONFIG_TYPE_INTEGER: 476c72fcc34Sopenharmony_ci { 477c72fcc34Sopenharmony_ci long v; 478c72fcc34Sopenharmony_ci 479c72fcc34Sopenharmony_ci if (snd_config_get_integer(obj_attr, &v) < 0) 480c72fcc34Sopenharmony_ci return false; 481c72fcc34Sopenharmony_ci 482c72fcc34Sopenharmony_ci if (!tplg_is_attribute_valid_expanded_value(tplg_pp, valid, v)) { 483c72fcc34Sopenharmony_ci tplg_attribute_print_valid_values(valid, attr_name); 484c72fcc34Sopenharmony_ci return false; 485c72fcc34Sopenharmony_ci } 486c72fcc34Sopenharmony_ci return true; 487c72fcc34Sopenharmony_ci } 488c72fcc34Sopenharmony_ci#endif 489c72fcc34Sopenharmony_ci default: 490c72fcc34Sopenharmony_ci break; 491c72fcc34Sopenharmony_ci } 492c72fcc34Sopenharmony_ci 493c72fcc34Sopenharmony_ci return false; 494c72fcc34Sopenharmony_ci 495c72fcc34Sopenharmony_cimin_max_check: 496c72fcc34Sopenharmony_ci if (!tplg_object_is_attribute_min_max_valid(attr, obj_attr, true)) 497c72fcc34Sopenharmony_ci return false; 498c72fcc34Sopenharmony_ci 499c72fcc34Sopenharmony_ci return tplg_object_is_attribute_min_max_valid(attr, obj_attr, false); 500c72fcc34Sopenharmony_ci} 501c72fcc34Sopenharmony_ci 502c72fcc34Sopenharmony_ci/* get object's name attribute value */ 503c72fcc34Sopenharmony_ciconst char *tplg_object_get_name(struct tplg_pre_processor *tplg_pp ATTRIBUTE_UNUSED, 504c72fcc34Sopenharmony_ci snd_config_t *object) 505c72fcc34Sopenharmony_ci{ 506c72fcc34Sopenharmony_ci snd_config_t *cfg; 507c72fcc34Sopenharmony_ci const char *name; 508c72fcc34Sopenharmony_ci int ret; 509c72fcc34Sopenharmony_ci 510c72fcc34Sopenharmony_ci ret = snd_config_search(object, "name", &cfg); 511c72fcc34Sopenharmony_ci if (ret < 0) 512c72fcc34Sopenharmony_ci return NULL; 513c72fcc34Sopenharmony_ci 514c72fcc34Sopenharmony_ci ret = snd_config_get_string(cfg, &name); 515c72fcc34Sopenharmony_ci if (ret < 0) 516c72fcc34Sopenharmony_ci return NULL; 517c72fcc34Sopenharmony_ci 518c72fcc34Sopenharmony_ci return name; 519c72fcc34Sopenharmony_ci} 520c72fcc34Sopenharmony_ci 521c72fcc34Sopenharmony_ci/* look up the instance of object in a config */ 522c72fcc34Sopenharmony_cistatic snd_config_t *tplg_object_lookup_in_config(struct tplg_pre_processor *tplg_pp ATTRIBUTE_UNUSED, 523c72fcc34Sopenharmony_ci snd_config_t *class, const char *type, 524c72fcc34Sopenharmony_ci const char *class_name, const char *id) 525c72fcc34Sopenharmony_ci{ 526c72fcc34Sopenharmony_ci snd_config_t *obj_cfg = NULL; 527c72fcc34Sopenharmony_ci char *config_id; 528c72fcc34Sopenharmony_ci 529c72fcc34Sopenharmony_ci config_id = tplg_snprintf("Object.%s.%s.%s", type, class_name, id); 530c72fcc34Sopenharmony_ci if (!config_id) 531c72fcc34Sopenharmony_ci return NULL; 532c72fcc34Sopenharmony_ci 533c72fcc34Sopenharmony_ci if (snd_config_search(class, config_id, &obj_cfg) < 0) 534c72fcc34Sopenharmony_ci return NULL; 535c72fcc34Sopenharmony_ci free(config_id); 536c72fcc34Sopenharmony_ci return obj_cfg; 537c72fcc34Sopenharmony_ci} 538c72fcc34Sopenharmony_ci 539c72fcc34Sopenharmony_cistatic int tplg_pp_add_object_tuple_section(struct tplg_pre_processor *tplg_pp, 540c72fcc34Sopenharmony_ci snd_config_t *class_cfg, 541c72fcc34Sopenharmony_ci snd_config_t *attr, char *data_name, 542c72fcc34Sopenharmony_ci const char *token_ref, const char *array_name) 543c72fcc34Sopenharmony_ci{ 544c72fcc34Sopenharmony_ci snd_config_t *top, *tuple_cfg, *child, *cfg, *new; 545c72fcc34Sopenharmony_ci const char *id; 546c72fcc34Sopenharmony_ci char *token, *type, *str; 547c72fcc34Sopenharmony_ci long tuple_value; 548c72fcc34Sopenharmony_ci int ret; 549c72fcc34Sopenharmony_ci 550c72fcc34Sopenharmony_ci tplg_pp_debug("Building vendor tuples section: '%s' ...", data_name); 551c72fcc34Sopenharmony_ci 552c72fcc34Sopenharmony_ci ret = snd_config_search(tplg_pp->output_cfg, "SectionVendorTuples", &top); 553c72fcc34Sopenharmony_ci if (ret < 0) { 554c72fcc34Sopenharmony_ci ret = tplg_config_make_add(&top, "SectionVendorTuples", 555c72fcc34Sopenharmony_ci SND_CONFIG_TYPE_COMPOUND, tplg_pp->output_cfg); 556c72fcc34Sopenharmony_ci if (ret < 0) { 557c72fcc34Sopenharmony_ci SNDERR("Error creating SectionVendorTuples config\n"); 558c72fcc34Sopenharmony_ci return ret; 559c72fcc34Sopenharmony_ci } 560c72fcc34Sopenharmony_ci } 561c72fcc34Sopenharmony_ci 562c72fcc34Sopenharmony_ci type = strchr(token_ref, '.'); 563c72fcc34Sopenharmony_ci if(!type) { 564c72fcc34Sopenharmony_ci SNDERR("Error getting type for %s\n", token_ref); 565c72fcc34Sopenharmony_ci return -EINVAL; 566c72fcc34Sopenharmony_ci } 567c72fcc34Sopenharmony_ci 568c72fcc34Sopenharmony_ci token = calloc(1, strlen(token_ref) - strlen(type) + 1); 569c72fcc34Sopenharmony_ci if (!token) 570c72fcc34Sopenharmony_ci return -ENOMEM; 571c72fcc34Sopenharmony_ci snprintf(token, strlen(token_ref) - strlen(type) + 1, "%s", token_ref); 572c72fcc34Sopenharmony_ci 573c72fcc34Sopenharmony_ci if (!array_name) 574c72fcc34Sopenharmony_ci str = strdup(type + 1); 575c72fcc34Sopenharmony_ci else 576c72fcc34Sopenharmony_ci str = tplg_snprintf("%s.%s", type + 1, array_name); 577c72fcc34Sopenharmony_ci if (!str) { 578c72fcc34Sopenharmony_ci ret = -ENOMEM; 579c72fcc34Sopenharmony_ci goto free; 580c72fcc34Sopenharmony_ci } 581c72fcc34Sopenharmony_ci 582c72fcc34Sopenharmony_ci tuple_cfg = tplg_find_config(top, data_name); 583c72fcc34Sopenharmony_ci if (!tuple_cfg) { 584c72fcc34Sopenharmony_ci /* add new SectionVendorTuples */ 585c72fcc34Sopenharmony_ci ret = tplg_config_make_add(&tuple_cfg, data_name, SND_CONFIG_TYPE_COMPOUND, top); 586c72fcc34Sopenharmony_ci if (ret < 0) { 587c72fcc34Sopenharmony_ci SNDERR("Error creating new vendor tuples config %s\n", data_name); 588c72fcc34Sopenharmony_ci goto err; 589c72fcc34Sopenharmony_ci } 590c72fcc34Sopenharmony_ci 591c72fcc34Sopenharmony_ci ret = tplg_config_make_add(&child, "tokens", SND_CONFIG_TYPE_STRING, 592c72fcc34Sopenharmony_ci tuple_cfg); 593c72fcc34Sopenharmony_ci if (ret < 0) { 594c72fcc34Sopenharmony_ci SNDERR("Error creating tokens config for '%s'\n", data_name); 595c72fcc34Sopenharmony_ci goto err; 596c72fcc34Sopenharmony_ci } 597c72fcc34Sopenharmony_ci 598c72fcc34Sopenharmony_ci ret = snd_config_set_string(child, token); 599c72fcc34Sopenharmony_ci if (ret < 0) { 600c72fcc34Sopenharmony_ci SNDERR("Error setting tokens config for '%s'\n", data_name); 601c72fcc34Sopenharmony_ci goto err; 602c72fcc34Sopenharmony_ci } 603c72fcc34Sopenharmony_ci 604c72fcc34Sopenharmony_ci ret = tplg_config_make_add(&child, "tuples", SND_CONFIG_TYPE_COMPOUND, 605c72fcc34Sopenharmony_ci tuple_cfg); 606c72fcc34Sopenharmony_ci if (ret < 0) { 607c72fcc34Sopenharmony_ci SNDERR("Error creating tuples config for '%s'\n", data_name); 608c72fcc34Sopenharmony_ci goto err; 609c72fcc34Sopenharmony_ci } 610c72fcc34Sopenharmony_ci 611c72fcc34Sopenharmony_ci ret = tplg_config_make_add(&cfg, str, SND_CONFIG_TYPE_COMPOUND, 612c72fcc34Sopenharmony_ci child); 613c72fcc34Sopenharmony_ci if (ret < 0) { 614c72fcc34Sopenharmony_ci SNDERR("Error creating tuples type config for '%s'\n", data_name); 615c72fcc34Sopenharmony_ci goto err; 616c72fcc34Sopenharmony_ci } 617c72fcc34Sopenharmony_ci } else { 618c72fcc34Sopenharmony_ci snd_config_t *tuples_cfg; 619c72fcc34Sopenharmony_ci 620c72fcc34Sopenharmony_ci ret = snd_config_search(tuple_cfg, "tuples" , &tuples_cfg); 621c72fcc34Sopenharmony_ci if (ret < 0) { 622c72fcc34Sopenharmony_ci SNDERR("can't find tuples config in %s\n", data_name); 623c72fcc34Sopenharmony_ci goto err; 624c72fcc34Sopenharmony_ci } 625c72fcc34Sopenharmony_ci 626c72fcc34Sopenharmony_ci cfg = tplg_find_config(tuples_cfg, str); 627c72fcc34Sopenharmony_ci if (!cfg) { 628c72fcc34Sopenharmony_ci ret = tplg_config_make_add(&cfg, str, SND_CONFIG_TYPE_COMPOUND, 629c72fcc34Sopenharmony_ci tuples_cfg); 630c72fcc34Sopenharmony_ci if (ret < 0) { 631c72fcc34Sopenharmony_ci SNDERR("Error creating tuples config for '%s' and type name %s\n", data_name, str); 632c72fcc34Sopenharmony_ci goto err; 633c72fcc34Sopenharmony_ci } 634c72fcc34Sopenharmony_ci } 635c72fcc34Sopenharmony_ci } 636c72fcc34Sopenharmony_ci 637c72fcc34Sopenharmony_ci ret = snd_config_get_id(attr, &id); 638c72fcc34Sopenharmony_ci if (ret < 0) 639c72fcc34Sopenharmony_ci goto err; 640c72fcc34Sopenharmony_ci 641c72fcc34Sopenharmony_ci /* tuple exists already? */ 642c72fcc34Sopenharmony_ci ret = snd_config_search(cfg, id, &child); 643c72fcc34Sopenharmony_ci if (ret >=0) 644c72fcc34Sopenharmony_ci goto err; 645c72fcc34Sopenharmony_ci 646c72fcc34Sopenharmony_ci /* add attribute to tuples */ 647c72fcc34Sopenharmony_ci tuple_value = tplg_class_attribute_valid_tuple_value(tplg_pp, class_cfg, attr); 648c72fcc34Sopenharmony_ci if (tuple_value < 0) { 649c72fcc34Sopenharmony_ci /* just copy attribute cfg as is */ 650c72fcc34Sopenharmony_ci ret = snd_config_copy(&new, attr); 651c72fcc34Sopenharmony_ci if (ret < 0) { 652c72fcc34Sopenharmony_ci SNDERR("can't copy attribute for %s\n", data_name); 653c72fcc34Sopenharmony_ci goto err; 654c72fcc34Sopenharmony_ci } 655c72fcc34Sopenharmony_ci } else { 656c72fcc34Sopenharmony_ci ret = snd_config_make(&new, id, SND_CONFIG_TYPE_INTEGER); 657c72fcc34Sopenharmony_ci if (ret < 0) 658c72fcc34Sopenharmony_ci goto err; 659c72fcc34Sopenharmony_ci 660c72fcc34Sopenharmony_ci ret = snd_config_set_integer(new, tuple_value); 661c72fcc34Sopenharmony_ci if (ret < 0) 662c72fcc34Sopenharmony_ci goto err; 663c72fcc34Sopenharmony_ci } 664c72fcc34Sopenharmony_ci 665c72fcc34Sopenharmony_ci ret = snd_config_add(cfg, new); 666c72fcc34Sopenharmony_cierr: 667c72fcc34Sopenharmony_ci free(str); 668c72fcc34Sopenharmony_cifree: 669c72fcc34Sopenharmony_ci free(token); 670c72fcc34Sopenharmony_ci return ret; 671c72fcc34Sopenharmony_ci} 672c72fcc34Sopenharmony_ci 673c72fcc34Sopenharmony_cistatic int tplg_pp_add_object_data_section(struct tplg_pre_processor *tplg_pp, 674c72fcc34Sopenharmony_ci snd_config_t *obj_data, char *data_name) 675c72fcc34Sopenharmony_ci{ 676c72fcc34Sopenharmony_ci snd_config_iterator_t i, next; 677c72fcc34Sopenharmony_ci snd_config_t *top, *data_cfg, *child; 678c72fcc34Sopenharmony_ci char *data_id; 679c72fcc34Sopenharmony_ci int ret, id = 0; 680c72fcc34Sopenharmony_ci 681c72fcc34Sopenharmony_ci ret = snd_config_search(tplg_pp->output_cfg, "SectionData", &top); 682c72fcc34Sopenharmony_ci if (ret < 0) { 683c72fcc34Sopenharmony_ci ret = tplg_config_make_add(&top, "SectionData", SND_CONFIG_TYPE_COMPOUND, 684c72fcc34Sopenharmony_ci tplg_pp->output_cfg); 685c72fcc34Sopenharmony_ci if (ret < 0) { 686c72fcc34Sopenharmony_ci SNDERR("Failed to add SectionData\n"); 687c72fcc34Sopenharmony_ci return ret; 688c72fcc34Sopenharmony_ci } 689c72fcc34Sopenharmony_ci } 690c72fcc34Sopenharmony_ci 691c72fcc34Sopenharmony_ci /* nothing to do if data section already exists */ 692c72fcc34Sopenharmony_ci data_cfg = tplg_find_config(top, data_name); 693c72fcc34Sopenharmony_ci if (data_cfg) 694c72fcc34Sopenharmony_ci return 0; 695c72fcc34Sopenharmony_ci 696c72fcc34Sopenharmony_ci tplg_pp_debug("Building data section %s ...", data_name); 697c72fcc34Sopenharmony_ci 698c72fcc34Sopenharmony_ci /* add new SectionData */ 699c72fcc34Sopenharmony_ci ret = tplg_config_make_add(&data_cfg, data_name, SND_CONFIG_TYPE_COMPOUND, top); 700c72fcc34Sopenharmony_ci if (ret < 0) 701c72fcc34Sopenharmony_ci return ret; 702c72fcc34Sopenharmony_ci 703c72fcc34Sopenharmony_ci ret = tplg_config_make_add(&child, "tuples", SND_CONFIG_TYPE_STRING, data_cfg); 704c72fcc34Sopenharmony_ci if (ret < 0) { 705c72fcc34Sopenharmony_ci SNDERR("error adding data ref for %s\n", data_name); 706c72fcc34Sopenharmony_ci return ret; 707c72fcc34Sopenharmony_ci } 708c72fcc34Sopenharmony_ci 709c72fcc34Sopenharmony_ci ret = snd_config_set_string(child, data_name); 710c72fcc34Sopenharmony_ci if (ret < 0) { 711c72fcc34Sopenharmony_ci SNDERR("error setting tuples ref for %s\n", data_name); 712c72fcc34Sopenharmony_ci return ret; 713c72fcc34Sopenharmony_ci } 714c72fcc34Sopenharmony_ci 715c72fcc34Sopenharmony_ci /* add data item to object */ 716c72fcc34Sopenharmony_ci snd_config_for_each(i, next, obj_data) 717c72fcc34Sopenharmony_ci id++; 718c72fcc34Sopenharmony_ci 719c72fcc34Sopenharmony_ci data_id = tplg_snprintf("%d", id); 720c72fcc34Sopenharmony_ci if (!data_id) 721c72fcc34Sopenharmony_ci return -ENOMEM; 722c72fcc34Sopenharmony_ci 723c72fcc34Sopenharmony_ci ret = tplg_config_make_add(&child, data_id, SND_CONFIG_TYPE_STRING, obj_data); 724c72fcc34Sopenharmony_ci free(data_id); 725c72fcc34Sopenharmony_ci if (ret < 0) { 726c72fcc34Sopenharmony_ci SNDERR("error adding data ref %s\n", data_name); 727c72fcc34Sopenharmony_ci return ret; 728c72fcc34Sopenharmony_ci } 729c72fcc34Sopenharmony_ci 730c72fcc34Sopenharmony_ci return snd_config_set_string(child, data_name); 731c72fcc34Sopenharmony_ci} 732c72fcc34Sopenharmony_ci 733c72fcc34Sopenharmony_ciint tplg_add_object_data(struct tplg_pre_processor *tplg_pp, snd_config_t *obj_cfg, 734c72fcc34Sopenharmony_ci snd_config_t *top, const char *array_name) 735c72fcc34Sopenharmony_ci{ 736c72fcc34Sopenharmony_ci snd_config_iterator_t i, next; 737c72fcc34Sopenharmony_ci snd_config_t *data_cfg, *class_cfg, *n, *obj; 738c72fcc34Sopenharmony_ci const char *object_id; 739c72fcc34Sopenharmony_ci int ret; 740c72fcc34Sopenharmony_ci 741c72fcc34Sopenharmony_ci if (snd_config_get_id(top, &object_id) < 0) 742c72fcc34Sopenharmony_ci return 0; 743c72fcc34Sopenharmony_ci 744c72fcc34Sopenharmony_ci obj = tplg_object_get_instance_config(tplg_pp, obj_cfg); 745c72fcc34Sopenharmony_ci 746c72fcc34Sopenharmony_ci class_cfg = tplg_class_lookup(tplg_pp, obj_cfg); 747c72fcc34Sopenharmony_ci if (!class_cfg) 748c72fcc34Sopenharmony_ci return -EINVAL; 749c72fcc34Sopenharmony_ci 750c72fcc34Sopenharmony_ci /* add data config to top */ 751c72fcc34Sopenharmony_ci ret = snd_config_search(top, "data", &data_cfg); 752c72fcc34Sopenharmony_ci if (ret < 0) { 753c72fcc34Sopenharmony_ci ret = tplg_config_make_add(&data_cfg, "data", SND_CONFIG_TYPE_COMPOUND, top); 754c72fcc34Sopenharmony_ci if (ret < 0) { 755c72fcc34Sopenharmony_ci SNDERR("error creating data config for %s\n", object_id); 756c72fcc34Sopenharmony_ci return ret; 757c72fcc34Sopenharmony_ci } 758c72fcc34Sopenharmony_ci } 759c72fcc34Sopenharmony_ci 760c72fcc34Sopenharmony_ci /* add data items to object's data section */ 761c72fcc34Sopenharmony_ci snd_config_for_each(i, next, obj) { 762c72fcc34Sopenharmony_ci const char *id, *token; 763c72fcc34Sopenharmony_ci char *data_cfg_name; 764c72fcc34Sopenharmony_ci 765c72fcc34Sopenharmony_ci n = snd_config_iterator_entry(i); 766c72fcc34Sopenharmony_ci if (snd_config_get_id(n, &id) < 0) 767c72fcc34Sopenharmony_ci continue; 768c72fcc34Sopenharmony_ci 769c72fcc34Sopenharmony_ci token = tplg_class_get_attribute_token_ref(tplg_pp, class_cfg, id); 770c72fcc34Sopenharmony_ci if (!token) 771c72fcc34Sopenharmony_ci continue; 772c72fcc34Sopenharmony_ci 773c72fcc34Sopenharmony_ci data_cfg_name = tplg_snprintf("%s.%s", object_id, token); 774c72fcc34Sopenharmony_ci if (!data_cfg_name) 775c72fcc34Sopenharmony_ci return -ENOMEM; 776c72fcc34Sopenharmony_ci 777c72fcc34Sopenharmony_ci ret = tplg_pp_add_object_data_section(tplg_pp, data_cfg, data_cfg_name); 778c72fcc34Sopenharmony_ci if (ret < 0) { 779c72fcc34Sopenharmony_ci SNDERR("Failed to add data section %s\n", data_cfg_name); 780c72fcc34Sopenharmony_ci free(data_cfg_name); 781c72fcc34Sopenharmony_ci return ret; 782c72fcc34Sopenharmony_ci } 783c72fcc34Sopenharmony_ci 784c72fcc34Sopenharmony_ci ret = tplg_pp_add_object_tuple_section(tplg_pp, class_cfg, n, data_cfg_name, 785c72fcc34Sopenharmony_ci token, array_name); 786c72fcc34Sopenharmony_ci if (ret < 0) { 787c72fcc34Sopenharmony_ci SNDERR("Failed to add data section %s\n", data_cfg_name); 788c72fcc34Sopenharmony_ci free(data_cfg_name); 789c72fcc34Sopenharmony_ci return ret; 790c72fcc34Sopenharmony_ci } 791c72fcc34Sopenharmony_ci free(data_cfg_name); 792c72fcc34Sopenharmony_ci } 793c72fcc34Sopenharmony_ci 794c72fcc34Sopenharmony_ci return 0; 795c72fcc34Sopenharmony_ci} 796c72fcc34Sopenharmony_ci 797c72fcc34Sopenharmony_ci/* search for all template configs in the source config and copy them to the destination */ 798c72fcc34Sopenharmony_cistatic int tplg_object_add_attributes(snd_config_t *dst, snd_config_t *template, 799c72fcc34Sopenharmony_ci snd_config_t *src) 800c72fcc34Sopenharmony_ci{ 801c72fcc34Sopenharmony_ci snd_config_iterator_t i, next; 802c72fcc34Sopenharmony_ci snd_config_t *n; 803c72fcc34Sopenharmony_ci int ret; 804c72fcc34Sopenharmony_ci 805c72fcc34Sopenharmony_ci snd_config_for_each(i, next, template) { 806c72fcc34Sopenharmony_ci snd_config_t *attr, *new; 807c72fcc34Sopenharmony_ci const char *id; 808c72fcc34Sopenharmony_ci 809c72fcc34Sopenharmony_ci n = snd_config_iterator_entry(i); 810c72fcc34Sopenharmony_ci if (snd_config_get_id(n, &id) < 0) 811c72fcc34Sopenharmony_ci continue; 812c72fcc34Sopenharmony_ci 813c72fcc34Sopenharmony_ci ret = snd_config_search(src, id, &attr); 814c72fcc34Sopenharmony_ci if (ret < 0) 815c72fcc34Sopenharmony_ci continue; 816c72fcc34Sopenharmony_ci 817c72fcc34Sopenharmony_ci /* skip if attribute is already set */ 818c72fcc34Sopenharmony_ci ret = snd_config_search(dst, id, &new); 819c72fcc34Sopenharmony_ci if (ret >= 0) 820c72fcc34Sopenharmony_ci continue; 821c72fcc34Sopenharmony_ci 822c72fcc34Sopenharmony_ci ret = snd_config_copy(&new, attr); 823c72fcc34Sopenharmony_ci if (ret < 0) { 824c72fcc34Sopenharmony_ci SNDERR("failed to copy attribute %s\n", id); 825c72fcc34Sopenharmony_ci return ret; 826c72fcc34Sopenharmony_ci } 827c72fcc34Sopenharmony_ci 828c72fcc34Sopenharmony_ci ret = snd_config_add(dst, new); 829c72fcc34Sopenharmony_ci if (ret < 0) { 830c72fcc34Sopenharmony_ci snd_config_delete(new); 831c72fcc34Sopenharmony_ci SNDERR("failed to add attribute %s\n", id); 832c72fcc34Sopenharmony_ci return ret; 833c72fcc34Sopenharmony_ci } 834c72fcc34Sopenharmony_ci } 835c72fcc34Sopenharmony_ci 836c72fcc34Sopenharmony_ci return 0; 837c72fcc34Sopenharmony_ci} 838c72fcc34Sopenharmony_ci 839c72fcc34Sopenharmony_cistatic const struct build_function_map *tplg_object_get_map(struct tplg_pre_processor *tplg_pp, 840c72fcc34Sopenharmony_ci snd_config_t *obj); 841c72fcc34Sopenharmony_ci 842c72fcc34Sopenharmony_ci/* Add object attributes to the private data of the parent object config */ 843c72fcc34Sopenharmony_cistatic int tplg_build_parent_data(struct tplg_pre_processor *tplg_pp, snd_config_t *obj_cfg, 844c72fcc34Sopenharmony_ci snd_config_t *parent) 845c72fcc34Sopenharmony_ci{ 846c72fcc34Sopenharmony_ci snd_config_t *obj, *parent_obj, *section_cfg, *top; 847c72fcc34Sopenharmony_ci const struct build_function_map *map; 848c72fcc34Sopenharmony_ci const char *id, *parent_id; 849c72fcc34Sopenharmony_ci int ret; 850c72fcc34Sopenharmony_ci 851c72fcc34Sopenharmony_ci /* nothing to do if parent is NULL */ 852c72fcc34Sopenharmony_ci if (!parent) 853c72fcc34Sopenharmony_ci return 0; 854c72fcc34Sopenharmony_ci 855c72fcc34Sopenharmony_ci obj = tplg_object_get_instance_config(tplg_pp, obj_cfg); 856c72fcc34Sopenharmony_ci parent_obj = tplg_object_get_instance_config(tplg_pp, parent); 857c72fcc34Sopenharmony_ci 858c72fcc34Sopenharmony_ci /* get object ID */ 859c72fcc34Sopenharmony_ci if (snd_config_get_id(obj, &id) < 0) { 860c72fcc34Sopenharmony_ci SNDERR("Invalid ID for object\n"); 861c72fcc34Sopenharmony_ci return -EINVAL; 862c72fcc34Sopenharmony_ci } 863c72fcc34Sopenharmony_ci 864c72fcc34Sopenharmony_ci /* get parent object name or ID */ 865c72fcc34Sopenharmony_ci parent_id = tplg_object_get_name(tplg_pp, parent_obj); 866c72fcc34Sopenharmony_ci if (!parent_id) { 867c72fcc34Sopenharmony_ci ret = snd_config_get_id(parent_obj, &parent_id); 868c72fcc34Sopenharmony_ci if (ret < 0) { 869c72fcc34Sopenharmony_ci SNDERR("Invalid ID for parent of object %s\n", id); 870c72fcc34Sopenharmony_ci return ret; 871c72fcc34Sopenharmony_ci } 872c72fcc34Sopenharmony_ci } 873c72fcc34Sopenharmony_ci 874c72fcc34Sopenharmony_ci map = tplg_object_get_map(tplg_pp, parent); 875c72fcc34Sopenharmony_ci if (!map) { 876c72fcc34Sopenharmony_ci SNDERR("Parent object %s not supported\n", parent_id); 877c72fcc34Sopenharmony_ci return -EINVAL; 878c72fcc34Sopenharmony_ci } 879c72fcc34Sopenharmony_ci 880c72fcc34Sopenharmony_ci /* find parent config with ID */ 881c72fcc34Sopenharmony_ci ret = snd_config_search(tplg_pp->output_cfg, map->section_name, §ion_cfg); 882c72fcc34Sopenharmony_ci if (ret < 0) { 883c72fcc34Sopenharmony_ci SNDERR("No SectionBE found\n"); 884c72fcc34Sopenharmony_ci return ret; 885c72fcc34Sopenharmony_ci } 886c72fcc34Sopenharmony_ci 887c72fcc34Sopenharmony_ci top = tplg_find_config(section_cfg, parent_id); 888c72fcc34Sopenharmony_ci if (!top) { 889c72fcc34Sopenharmony_ci SNDERR("SectionBE %s not found\n", parent_id); 890c72fcc34Sopenharmony_ci return -EINVAL; 891c72fcc34Sopenharmony_ci } 892c72fcc34Sopenharmony_ci 893c72fcc34Sopenharmony_ci return tplg_add_object_data(tplg_pp, obj_cfg, top, id); 894c72fcc34Sopenharmony_ci} 895c72fcc34Sopenharmony_ci 896c72fcc34Sopenharmony_ci/* 897c72fcc34Sopenharmony_ci * Function to create a new "section" config based on the template. The new config will be 898c72fcc34Sopenharmony_ci * added to the output_cfg or the top_config input parameter. 899c72fcc34Sopenharmony_ci */ 900c72fcc34Sopenharmony_ciint tplg_build_object_from_template(struct tplg_pre_processor *tplg_pp, snd_config_t *obj_cfg, 901c72fcc34Sopenharmony_ci snd_config_t **wtop, snd_config_t *top_config, 902c72fcc34Sopenharmony_ci bool skip_name) 903c72fcc34Sopenharmony_ci{ 904c72fcc34Sopenharmony_ci snd_config_t *top, *template, *obj; 905c72fcc34Sopenharmony_ci const struct build_function_map *map; 906c72fcc34Sopenharmony_ci const char *object_name; 907c72fcc34Sopenharmony_ci int ret; 908c72fcc34Sopenharmony_ci 909c72fcc34Sopenharmony_ci /* look up object map */ 910c72fcc34Sopenharmony_ci map = tplg_object_get_map(tplg_pp, obj_cfg); 911c72fcc34Sopenharmony_ci if (!map) { 912c72fcc34Sopenharmony_ci SNDERR("unknown object type or class name\n"); 913c72fcc34Sopenharmony_ci return -EINVAL; 914c72fcc34Sopenharmony_ci } 915c72fcc34Sopenharmony_ci 916c72fcc34Sopenharmony_ci obj = tplg_object_get_instance_config(tplg_pp, obj_cfg); 917c72fcc34Sopenharmony_ci 918c72fcc34Sopenharmony_ci /* look up or create the corresponding section config for object */ 919c72fcc34Sopenharmony_ci if (!top_config) 920c72fcc34Sopenharmony_ci top_config = tplg_pp->output_cfg; 921c72fcc34Sopenharmony_ci 922c72fcc34Sopenharmony_ci ret = snd_config_search(top_config, map->section_name, &top); 923c72fcc34Sopenharmony_ci if (ret < 0) { 924c72fcc34Sopenharmony_ci ret = tplg_config_make_add(&top, map->section_name, SND_CONFIG_TYPE_COMPOUND, 925c72fcc34Sopenharmony_ci top_config); 926c72fcc34Sopenharmony_ci if (ret < 0) { 927c72fcc34Sopenharmony_ci SNDERR("Error creating %s config\n", map->section_name); 928c72fcc34Sopenharmony_ci return ret; 929c72fcc34Sopenharmony_ci } 930c72fcc34Sopenharmony_ci } 931c72fcc34Sopenharmony_ci 932c72fcc34Sopenharmony_ci /* get object name */ 933c72fcc34Sopenharmony_ci object_name = tplg_object_get_name(tplg_pp, obj); 934c72fcc34Sopenharmony_ci if (!object_name) { 935c72fcc34Sopenharmony_ci ret = snd_config_get_id(obj, &object_name); 936c72fcc34Sopenharmony_ci if (ret < 0) { 937c72fcc34Sopenharmony_ci SNDERR("Invalid ID for %s\n", map->section_name); 938c72fcc34Sopenharmony_ci return ret; 939c72fcc34Sopenharmony_ci } 940c72fcc34Sopenharmony_ci } 941c72fcc34Sopenharmony_ci 942c72fcc34Sopenharmony_ci tplg_pp_debug("Building object: '%s' ...", object_name); 943c72fcc34Sopenharmony_ci 944c72fcc34Sopenharmony_ci /* create and add new object config with name, if needed */ 945c72fcc34Sopenharmony_ci if (skip_name) { 946c72fcc34Sopenharmony_ci *wtop = top; 947c72fcc34Sopenharmony_ci } else { 948c72fcc34Sopenharmony_ci *wtop = tplg_find_config(top, object_name); 949c72fcc34Sopenharmony_ci if (*wtop) 950c72fcc34Sopenharmony_ci goto template; 951c72fcc34Sopenharmony_ci 952c72fcc34Sopenharmony_ci ret = tplg_config_make_add(wtop, object_name, SND_CONFIG_TYPE_COMPOUND, 953c72fcc34Sopenharmony_ci top); 954c72fcc34Sopenharmony_ci if (ret < 0) { 955c72fcc34Sopenharmony_ci SNDERR("Error creating config for %s\n", object_name); 956c72fcc34Sopenharmony_ci return ret; 957c72fcc34Sopenharmony_ci } 958c72fcc34Sopenharmony_ci } 959c72fcc34Sopenharmony_ci 960c72fcc34Sopenharmony_citemplate: 961c72fcc34Sopenharmony_ci /* create template config */ 962c72fcc34Sopenharmony_ci if (!map->template_items) 963c72fcc34Sopenharmony_ci return 0; 964c72fcc34Sopenharmony_ci 965c72fcc34Sopenharmony_ci ret = tplg_create_config_template(tplg_pp, &template, map->template_items); 966c72fcc34Sopenharmony_ci if (ret < 0) { 967c72fcc34Sopenharmony_ci SNDERR("Error creating template config for %s\n", object_name); 968c72fcc34Sopenharmony_ci return ret; 969c72fcc34Sopenharmony_ci } 970c72fcc34Sopenharmony_ci 971c72fcc34Sopenharmony_ci /* update section config based on template and the attribute values in the object */ 972c72fcc34Sopenharmony_ci ret = tplg_object_add_attributes(*wtop, template, obj); 973c72fcc34Sopenharmony_ci snd_config_delete(template); 974c72fcc34Sopenharmony_ci if (ret < 0) 975c72fcc34Sopenharmony_ci SNDERR("Error adding attributes for object '%s'\n", object_name); 976c72fcc34Sopenharmony_ci 977c72fcc34Sopenharmony_ci return ret; 978c72fcc34Sopenharmony_ci} 979c72fcc34Sopenharmony_ci 980c72fcc34Sopenharmony_cistatic int tplg_build_generic_object(struct tplg_pre_processor *tplg_pp, snd_config_t *obj_cfg, 981c72fcc34Sopenharmony_ci snd_config_t *parent ATTRIBUTE_UNUSED) 982c72fcc34Sopenharmony_ci{ 983c72fcc34Sopenharmony_ci snd_config_t *wtop; 984c72fcc34Sopenharmony_ci const char *name; 985c72fcc34Sopenharmony_ci int ret; 986c72fcc34Sopenharmony_ci 987c72fcc34Sopenharmony_ci ret = tplg_build_object_from_template(tplg_pp, obj_cfg, &wtop, NULL, false); 988c72fcc34Sopenharmony_ci if (ret < 0) 989c72fcc34Sopenharmony_ci return ret; 990c72fcc34Sopenharmony_ci 991c72fcc34Sopenharmony_ci ret = snd_config_get_id(wtop, &name); 992c72fcc34Sopenharmony_ci if (ret < 0) 993c72fcc34Sopenharmony_ci return ret; 994c72fcc34Sopenharmony_ci 995c72fcc34Sopenharmony_ci ret = tplg_add_object_data(tplg_pp, obj_cfg, wtop, NULL); 996c72fcc34Sopenharmony_ci if (ret < 0) 997c72fcc34Sopenharmony_ci SNDERR("Failed to add data section for %s\n", name); 998c72fcc34Sopenharmony_ci 999c72fcc34Sopenharmony_ci return ret; 1000c72fcc34Sopenharmony_ci} 1001c72fcc34Sopenharmony_ci 1002c72fcc34Sopenharmony_ciconst struct config_template_items pcm_caps_config = { 1003c72fcc34Sopenharmony_ci .int_config_ids = {"rate_min", "rate_max", "channels_min", "channels_max", "periods_min", 1004c72fcc34Sopenharmony_ci "periods_max", "period_size_min", "period_size_max", "buffer_size_min", 1005c72fcc34Sopenharmony_ci "buffer_size_max", "sig_bits"}, 1006c72fcc34Sopenharmony_ci .string_config_ids = {"formats", "rates"}, 1007c72fcc34Sopenharmony_ci}; 1008c72fcc34Sopenharmony_ci 1009c72fcc34Sopenharmony_ciconst struct config_template_items fe_dai_config = { 1010c72fcc34Sopenharmony_ci .int_config_ids = {"id"}, 1011c72fcc34Sopenharmony_ci}; 1012c72fcc34Sopenharmony_ci 1013c72fcc34Sopenharmony_ciconst struct config_template_items hwcfg_config = { 1014c72fcc34Sopenharmony_ci .int_config_ids = {"id", "bclk_freq", "bclk_invert", "fsync_invert", "fsync_freq", 1015c72fcc34Sopenharmony_ci "mclk_freq", "pm_gate_clocks", "tdm_slots", "tdm_slot_width", 1016c72fcc34Sopenharmony_ci "tx_slots", "rx_slots", "tx_channels", "rx_channels"}, 1017c72fcc34Sopenharmony_ci .string_config_ids = {"format", "bclk", "fsync", "mclk"}, 1018c72fcc34Sopenharmony_ci}; 1019c72fcc34Sopenharmony_ci 1020c72fcc34Sopenharmony_ciconst struct config_template_items be_dai_config = { 1021c72fcc34Sopenharmony_ci .int_config_ids = {"id", "default_hw_conf_id", "symmertic_rates", "symmetric_channels", 1022c72fcc34Sopenharmony_ci "symmetric_sample_bits"}, 1023c72fcc34Sopenharmony_ci .string_config_ids = {"stream_name"}, 1024c72fcc34Sopenharmony_ci}; 1025c72fcc34Sopenharmony_ci 1026c72fcc34Sopenharmony_ciconst struct config_template_items pcm_config = { 1027c72fcc34Sopenharmony_ci .int_config_ids = {"id", "compress", "symmertic_rates", "symmetric_channels", 1028c72fcc34Sopenharmony_ci "symmetric_sample_bits"}, 1029c72fcc34Sopenharmony_ci}; 1030c72fcc34Sopenharmony_ci 1031c72fcc34Sopenharmony_ciconst struct config_template_items mixer_control_config = { 1032c72fcc34Sopenharmony_ci .int_config_ids = {"index", "max", "invert"}, 1033c72fcc34Sopenharmony_ci .compound_config_ids = {"access"} 1034c72fcc34Sopenharmony_ci}; 1035c72fcc34Sopenharmony_ci 1036c72fcc34Sopenharmony_ciconst struct config_template_items bytes_control_config = { 1037c72fcc34Sopenharmony_ci .int_config_ids = {"index", "base", "num_regs", "max", "mask"}, 1038c72fcc34Sopenharmony_ci .compound_config_ids = {"access"} 1039c72fcc34Sopenharmony_ci}; 1040c72fcc34Sopenharmony_ci 1041c72fcc34Sopenharmony_ciconst struct config_template_items enum_control_config = { 1042c72fcc34Sopenharmony_ci .int_config_ids = {"index"}, 1043c72fcc34Sopenharmony_ci .compound_config_ids = {"access"} 1044c72fcc34Sopenharmony_ci}; 1045c72fcc34Sopenharmony_ci 1046c72fcc34Sopenharmony_ciconst struct config_template_items text_config = { 1047c72fcc34Sopenharmony_ci .compound_config_ids = {"values"} 1048c72fcc34Sopenharmony_ci}; 1049c72fcc34Sopenharmony_ci 1050c72fcc34Sopenharmony_ciconst struct config_template_items scale_config = { 1051c72fcc34Sopenharmony_ci .int_config_ids = {"min", "step", "mute"}, 1052c72fcc34Sopenharmony_ci}; 1053c72fcc34Sopenharmony_ci 1054c72fcc34Sopenharmony_ciconst struct config_template_items ops_config = { 1055c72fcc34Sopenharmony_ci .int_config_ids = {"get", "put"}, 1056c72fcc34Sopenharmony_ci .string_config_ids = {"info"}, 1057c72fcc34Sopenharmony_ci}; 1058c72fcc34Sopenharmony_ci 1059c72fcc34Sopenharmony_ciconst struct config_template_items channel_config = { 1060c72fcc34Sopenharmony_ci .int_config_ids = {"reg", "shift"}, 1061c72fcc34Sopenharmony_ci}; 1062c72fcc34Sopenharmony_ci 1063c72fcc34Sopenharmony_ciconst struct config_template_items widget_config = { 1064c72fcc34Sopenharmony_ci .int_config_ids = {"index", "no_pm", "shift", "invert", "subseq", "event_type", 1065c72fcc34Sopenharmony_ci "event_flags"}, 1066c72fcc34Sopenharmony_ci .string_config_ids = {"type", "stream_name"}, 1067c72fcc34Sopenharmony_ci}; 1068c72fcc34Sopenharmony_ci 1069c72fcc34Sopenharmony_ciconst struct config_template_items data_config = { 1070c72fcc34Sopenharmony_ci .string_config_ids = {"bytes"} 1071c72fcc34Sopenharmony_ci}; 1072c72fcc34Sopenharmony_ci 1073c72fcc34Sopenharmony_ci/* 1074c72fcc34Sopenharmony_ci * Items without class name should be placed lower than those with one, 1075c72fcc34Sopenharmony_ci * because they are much more generic. 1076c72fcc34Sopenharmony_ci */ 1077c72fcc34Sopenharmony_ciconst struct build_function_map object_build_map[] = { 1078c72fcc34Sopenharmony_ci {"Base", "manifest", "SectionManifest", &tplg_build_generic_object, NULL, NULL}, 1079c72fcc34Sopenharmony_ci {"Base", "data", "SectionData", &tplg_build_data_object, NULL, &data_config}, 1080c72fcc34Sopenharmony_ci {"Base", "tlv", "SectionTLV", &tplg_build_tlv_object, NULL, NULL}, 1081c72fcc34Sopenharmony_ci {"Base", "scale", "scale", &tplg_build_scale_object, NULL, &scale_config}, 1082c72fcc34Sopenharmony_ci {"Base", "ops", "ops" ,&tplg_build_ops_object, NULL, &ops_config}, 1083c72fcc34Sopenharmony_ci {"Base", "extops", "extops" ,&tplg_build_ops_object, NULL, &ops_config}, 1084c72fcc34Sopenharmony_ci {"Base", "channel", "channel", &tplg_build_channel_object, NULL, &channel_config}, 1085c72fcc34Sopenharmony_ci {"Base", "text", "SectionText", &tplg_build_text_object, NULL, &text_config}, 1086c72fcc34Sopenharmony_ci {"Base", "VendorToken", "SectionVendorTokens", &tplg_build_vendor_token_object, 1087c72fcc34Sopenharmony_ci NULL, NULL}, 1088c72fcc34Sopenharmony_ci {"Base", "hw_config", "SectionHWConfig", &tplg_build_hw_cfg_object, NULL, 1089c72fcc34Sopenharmony_ci &hwcfg_config}, 1090c72fcc34Sopenharmony_ci {"Base", "fe_dai", "dai", &tplg_build_fe_dai_object, NULL, &fe_dai_config}, 1091c72fcc34Sopenharmony_ci {"Base", "route", "SectionGraph", &tplg_build_dapm_route_object, NULL, NULL}, 1092c72fcc34Sopenharmony_ci {"Widget", "buffer", "SectionWidget", &tplg_build_generic_object, NULL, &widget_config}, 1093c72fcc34Sopenharmony_ci {"Widget", "", "SectionWidget", &tplg_build_generic_object, NULL, &widget_config}, 1094c72fcc34Sopenharmony_ci {"Control", "mixer", "SectionControlMixer", &tplg_build_mixer_control, NULL, 1095c72fcc34Sopenharmony_ci &mixer_control_config}, 1096c72fcc34Sopenharmony_ci {"Control", "bytes", "SectionControlBytes", &tplg_build_bytes_control, NULL, 1097c72fcc34Sopenharmony_ci &bytes_control_config}, 1098c72fcc34Sopenharmony_ci {"Control", "enum", "SectionControlEnum", &tplg_build_enum_control, NULL, 1099c72fcc34Sopenharmony_ci &enum_control_config}, 1100c72fcc34Sopenharmony_ci {"Dai", "", "SectionBE", &tplg_build_generic_object, NULL, &be_dai_config}, 1101c72fcc34Sopenharmony_ci {"PCM", "pcm", "SectionPCM", &tplg_build_generic_object, NULL, &pcm_config}, 1102c72fcc34Sopenharmony_ci {"PCM", "pcm_caps", "SectionPCMCapabilities", &tplg_build_pcm_caps_object, 1103c72fcc34Sopenharmony_ci NULL, &pcm_caps_config}, 1104c72fcc34Sopenharmony_ci}; 1105c72fcc34Sopenharmony_ci 1106c72fcc34Sopenharmony_cistatic const struct build_function_map *tplg_object_get_map(struct tplg_pre_processor *tplg_pp ATTRIBUTE_UNUSED, 1107c72fcc34Sopenharmony_ci snd_config_t *obj) 1108c72fcc34Sopenharmony_ci{ 1109c72fcc34Sopenharmony_ci snd_config_iterator_t first; 1110c72fcc34Sopenharmony_ci snd_config_t *class; 1111c72fcc34Sopenharmony_ci const char *class_type, *class_name; 1112c72fcc34Sopenharmony_ci unsigned int i; 1113c72fcc34Sopenharmony_ci 1114c72fcc34Sopenharmony_ci first = snd_config_iterator_first(obj); 1115c72fcc34Sopenharmony_ci class = snd_config_iterator_entry(first); 1116c72fcc34Sopenharmony_ci 1117c72fcc34Sopenharmony_ci if (snd_config_get_id(class, &class_name) < 0) 1118c72fcc34Sopenharmony_ci return NULL; 1119c72fcc34Sopenharmony_ci 1120c72fcc34Sopenharmony_ci if (snd_config_get_id(obj, &class_type) < 0) 1121c72fcc34Sopenharmony_ci return NULL; 1122c72fcc34Sopenharmony_ci 1123c72fcc34Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(object_build_map); i++) { 1124c72fcc34Sopenharmony_ci if (!strcmp(class_type, "Widget") && 1125c72fcc34Sopenharmony_ci !strcmp(object_build_map[i].class_type, "Widget") && 1126c72fcc34Sopenharmony_ci !strcmp(object_build_map[i].class_name, "")) 1127c72fcc34Sopenharmony_ci return &object_build_map[i]; 1128c72fcc34Sopenharmony_ci 1129c72fcc34Sopenharmony_ci if (!strcmp(class_type, "Dai") && 1130c72fcc34Sopenharmony_ci !strcmp(object_build_map[i].class_type, "Dai")) 1131c72fcc34Sopenharmony_ci return &object_build_map[i]; 1132c72fcc34Sopenharmony_ci 1133c72fcc34Sopenharmony_ci /* for other type objects, also match the object class_name */ 1134c72fcc34Sopenharmony_ci if (!strcmp(class_type, object_build_map[i].class_type) && 1135c72fcc34Sopenharmony_ci !strcmp(object_build_map[i].class_name, class_name)) 1136c72fcc34Sopenharmony_ci return &object_build_map[i]; 1137c72fcc34Sopenharmony_ci } 1138c72fcc34Sopenharmony_ci 1139c72fcc34Sopenharmony_ci return NULL; 1140c72fcc34Sopenharmony_ci} 1141c72fcc34Sopenharmony_ci 1142c72fcc34Sopenharmony_ci/* search for section name based on class type and name and return the config in output_cfg */ 1143c72fcc34Sopenharmony_cisnd_config_t *tplg_object_get_section(struct tplg_pre_processor *tplg_pp, snd_config_t *class) 1144c72fcc34Sopenharmony_ci{ 1145c72fcc34Sopenharmony_ci const struct build_function_map *map; 1146c72fcc34Sopenharmony_ci snd_config_t *cfg = NULL; 1147c72fcc34Sopenharmony_ci int ret; 1148c72fcc34Sopenharmony_ci 1149c72fcc34Sopenharmony_ci map = tplg_object_get_map(tplg_pp, class); 1150c72fcc34Sopenharmony_ci if (!map) 1151c72fcc34Sopenharmony_ci return NULL; 1152c72fcc34Sopenharmony_ci 1153c72fcc34Sopenharmony_ci ret = snd_config_search(tplg_pp->output_cfg, map->section_name, &cfg); 1154c72fcc34Sopenharmony_ci if (ret < 0) 1155c72fcc34Sopenharmony_ci SNDERR("Section config for %s not found\n", map->section_name); 1156c72fcc34Sopenharmony_ci 1157c72fcc34Sopenharmony_ci return cfg; 1158c72fcc34Sopenharmony_ci} 1159c72fcc34Sopenharmony_ci 1160c72fcc34Sopenharmony_ci/* return 1 if attribute not found in search_config, 0 on success and negative value on error */ 1161c72fcc34Sopenharmony_cistatic int tplg_object_copy_and_add_param(struct tplg_pre_processor *tplg_pp ATTRIBUTE_UNUSED, 1162c72fcc34Sopenharmony_ci snd_config_t *obj, 1163c72fcc34Sopenharmony_ci snd_config_t *attr_cfg, 1164c72fcc34Sopenharmony_ci snd_config_t *search_config) 1165c72fcc34Sopenharmony_ci{ 1166c72fcc34Sopenharmony_ci snd_config_iterator_t first = snd_config_iterator_first(obj); 1167c72fcc34Sopenharmony_ci snd_config_t *attr, *new, *first_cfg; 1168c72fcc34Sopenharmony_ci const char *id, *search_id; 1169c72fcc34Sopenharmony_ci int ret; 1170c72fcc34Sopenharmony_ci 1171c72fcc34Sopenharmony_ci first_cfg = snd_config_iterator_entry(first); 1172c72fcc34Sopenharmony_ci 1173c72fcc34Sopenharmony_ci if (snd_config_get_id(attr_cfg, &id) < 0) 1174c72fcc34Sopenharmony_ci return 0; 1175c72fcc34Sopenharmony_ci 1176c72fcc34Sopenharmony_ci if (snd_config_get_id(search_config, &search_id) < 0) 1177c72fcc34Sopenharmony_ci return 0; 1178c72fcc34Sopenharmony_ci 1179c72fcc34Sopenharmony_ci /* copy object value */ 1180c72fcc34Sopenharmony_ci ret = snd_config_search(search_config, id, &attr); 1181c72fcc34Sopenharmony_ci if (ret < 0) 1182c72fcc34Sopenharmony_ci return 1; 1183c72fcc34Sopenharmony_ci 1184c72fcc34Sopenharmony_ci ret = snd_config_copy(&new, attr); 1185c72fcc34Sopenharmony_ci if (ret < 0) { 1186c72fcc34Sopenharmony_ci SNDERR("error copying attribute '%s' value from %s\n", id, search_id); 1187c72fcc34Sopenharmony_ci return ret; 1188c72fcc34Sopenharmony_ci } 1189c72fcc34Sopenharmony_ci 1190c72fcc34Sopenharmony_ci if (first_cfg) { 1191c72fcc34Sopenharmony_ci /* prepend the new config */ 1192c72fcc34Sopenharmony_ci ret = snd_config_add_before(first_cfg, new); 1193c72fcc34Sopenharmony_ci if (ret < 0) { 1194c72fcc34Sopenharmony_ci snd_config_delete(new); 1195c72fcc34Sopenharmony_ci SNDERR("error prepending attribute '%s' value to %s\n", id, search_id); 1196c72fcc34Sopenharmony_ci } 1197c72fcc34Sopenharmony_ci } else { 1198c72fcc34Sopenharmony_ci ret = snd_config_add(obj, new); 1199c72fcc34Sopenharmony_ci if (ret < 0) { 1200c72fcc34Sopenharmony_ci snd_config_delete(new); 1201c72fcc34Sopenharmony_ci SNDERR("error adding attribute '%s' value to %s\n", id, search_id); 1202c72fcc34Sopenharmony_ci } 1203c72fcc34Sopenharmony_ci } 1204c72fcc34Sopenharmony_ci 1205c72fcc34Sopenharmony_ci return ret; 1206c72fcc34Sopenharmony_ci} 1207c72fcc34Sopenharmony_ci 1208c72fcc34Sopenharmony_ci/* 1209c72fcc34Sopenharmony_ci * Attribute values for an object can be set in one of the following in order of 1210c72fcc34Sopenharmony_ci * precedence: 1211c72fcc34Sopenharmony_ci * 1. Value set in object instance 1212c72fcc34Sopenharmony_ci * 2. Default value set in the object's class definition 1213c72fcc34Sopenharmony_ci * 3. Inherited value from the parent object 1214c72fcc34Sopenharmony_ci * 4. Value set in the object instance embedded in the parent object 1215c72fcc34Sopenharmony_ci * 5. Value set in the object instance embedded in the parent class definition 1216c72fcc34Sopenharmony_ci */ 1217c72fcc34Sopenharmony_cistatic int tplg_object_update(struct tplg_pre_processor *tplg_pp, snd_config_t *obj, 1218c72fcc34Sopenharmony_ci snd_config_t *parent) 1219c72fcc34Sopenharmony_ci{ 1220c72fcc34Sopenharmony_ci snd_config_iterator_t i, next; 1221c72fcc34Sopenharmony_ci snd_config_t *n, *cfg, *args; 1222c72fcc34Sopenharmony_ci snd_config_t *obj_cfg, *class_cfg, *parent_obj; 1223c72fcc34Sopenharmony_ci const char *obj_id, *class_name, *class_type; 1224c72fcc34Sopenharmony_ci int ret; 1225c72fcc34Sopenharmony_ci 1226c72fcc34Sopenharmony_ci class_cfg = tplg_class_lookup(tplg_pp, obj); 1227c72fcc34Sopenharmony_ci if (!class_cfg) 1228c72fcc34Sopenharmony_ci return -EINVAL; 1229c72fcc34Sopenharmony_ci 1230c72fcc34Sopenharmony_ci /* find config for class attributes */ 1231c72fcc34Sopenharmony_ci ret = snd_config_search(class_cfg, "DefineAttribute", &args); 1232c72fcc34Sopenharmony_ci if (ret < 0) 1233c72fcc34Sopenharmony_ci return 0; 1234c72fcc34Sopenharmony_ci 1235c72fcc34Sopenharmony_ci if (snd_config_get_id(obj, &class_type) < 0) 1236c72fcc34Sopenharmony_ci return 0; 1237c72fcc34Sopenharmony_ci 1238c72fcc34Sopenharmony_ci if (snd_config_get_id(class_cfg, &class_name) < 0) 1239c72fcc34Sopenharmony_ci return 0; 1240c72fcc34Sopenharmony_ci 1241c72fcc34Sopenharmony_ci /* get obj cfg */ 1242c72fcc34Sopenharmony_ci obj_cfg = tplg_object_get_instance_config(tplg_pp, obj); 1243c72fcc34Sopenharmony_ci if (snd_config_get_id(obj_cfg, &obj_id) < 0) 1244c72fcc34Sopenharmony_ci return 0; 1245c72fcc34Sopenharmony_ci 1246c72fcc34Sopenharmony_ci /* copy and add attributes */ 1247c72fcc34Sopenharmony_ci snd_config_for_each(i, next, args) { 1248c72fcc34Sopenharmony_ci snd_config_t *attr; 1249c72fcc34Sopenharmony_ci const char *id; 1250c72fcc34Sopenharmony_ci 1251c72fcc34Sopenharmony_ci n = snd_config_iterator_entry(i); 1252c72fcc34Sopenharmony_ci if (snd_config_get_id(n, &id) < 0) 1253c72fcc34Sopenharmony_ci continue; 1254c72fcc34Sopenharmony_ci 1255c72fcc34Sopenharmony_ci if (tplg_class_is_attribute_unique(id, class_cfg)) 1256c72fcc34Sopenharmony_ci continue; 1257c72fcc34Sopenharmony_ci 1258c72fcc34Sopenharmony_ci if (tplg_class_is_attribute_immutable(id, class_cfg)) 1259c72fcc34Sopenharmony_ci goto class; 1260c72fcc34Sopenharmony_ci 1261c72fcc34Sopenharmony_ci /* check if attribute value is set in the object */ 1262c72fcc34Sopenharmony_ci ret = snd_config_search(obj_cfg, id, &attr); 1263c72fcc34Sopenharmony_ci if (ret < 0) 1264c72fcc34Sopenharmony_ci goto class; 1265c72fcc34Sopenharmony_ci continue; 1266c72fcc34Sopenharmony_ciclass: 1267c72fcc34Sopenharmony_ci /* search for attributes value in class */ 1268c72fcc34Sopenharmony_ci ret = tplg_object_copy_and_add_param(tplg_pp, obj_cfg, n, class_cfg); 1269c72fcc34Sopenharmony_ci if (ret == 1) { 1270c72fcc34Sopenharmony_ci if (tplg_class_is_attribute_immutable(id, class_cfg)) { 1271c72fcc34Sopenharmony_ci SNDERR("Immutable attribute %s not set in class %s\n", 1272c72fcc34Sopenharmony_ci id, class_name); 1273c72fcc34Sopenharmony_ci return -EINVAL; 1274c72fcc34Sopenharmony_ci } 1275c72fcc34Sopenharmony_ci goto parent; 1276c72fcc34Sopenharmony_ci } 1277c72fcc34Sopenharmony_ci else if (ret < 0) 1278c72fcc34Sopenharmony_ci return ret; 1279c72fcc34Sopenharmony_ci continue; 1280c72fcc34Sopenharmony_ciparent: 1281c72fcc34Sopenharmony_ci /* search for attribute value in parent */ 1282c72fcc34Sopenharmony_ci if (!parent) 1283c72fcc34Sopenharmony_ci goto parent_object; 1284c72fcc34Sopenharmony_ci 1285c72fcc34Sopenharmony_ci /* get parent obj cfg */ 1286c72fcc34Sopenharmony_ci parent_obj = tplg_object_get_instance_config(tplg_pp, parent); 1287c72fcc34Sopenharmony_ci if (!parent_obj) 1288c72fcc34Sopenharmony_ci goto parent_object; 1289c72fcc34Sopenharmony_ci 1290c72fcc34Sopenharmony_ci ret = tplg_object_copy_and_add_param(tplg_pp, obj_cfg, n, parent_obj); 1291c72fcc34Sopenharmony_ci if (ret == 1) 1292c72fcc34Sopenharmony_ci goto parent_object; 1293c72fcc34Sopenharmony_ci else if (ret < 0) 1294c72fcc34Sopenharmony_ci return ret; 1295c72fcc34Sopenharmony_ci continue; 1296c72fcc34Sopenharmony_ciparent_object: 1297c72fcc34Sopenharmony_ci if (!parent) 1298c72fcc34Sopenharmony_ci goto parent_class; 1299c72fcc34Sopenharmony_ci 1300c72fcc34Sopenharmony_ci cfg = tplg_object_lookup_in_config(tplg_pp, parent_obj, class_type, 1301c72fcc34Sopenharmony_ci class_name, obj_id); 1302c72fcc34Sopenharmony_ci if (!cfg) 1303c72fcc34Sopenharmony_ci goto parent_class; 1304c72fcc34Sopenharmony_ci 1305c72fcc34Sopenharmony_ci ret = tplg_object_copy_and_add_param(tplg_pp, obj_cfg, n, cfg); 1306c72fcc34Sopenharmony_ci if (ret == 1) 1307c72fcc34Sopenharmony_ci goto parent_class; 1308c72fcc34Sopenharmony_ci else if (ret < 0) 1309c72fcc34Sopenharmony_ci return ret; 1310c72fcc34Sopenharmony_ci continue; 1311c72fcc34Sopenharmony_ciparent_class: 1312c72fcc34Sopenharmony_ci if (!parent) 1313c72fcc34Sopenharmony_ci goto check; 1314c72fcc34Sopenharmony_ci 1315c72fcc34Sopenharmony_ci cfg = tplg_class_lookup(tplg_pp, parent); 1316c72fcc34Sopenharmony_ci if (!cfg) 1317c72fcc34Sopenharmony_ci return -EINVAL; 1318c72fcc34Sopenharmony_ci 1319c72fcc34Sopenharmony_ci cfg = tplg_object_lookup_in_config(tplg_pp, cfg, class_type, 1320c72fcc34Sopenharmony_ci class_name, obj_id); 1321c72fcc34Sopenharmony_ci if (!cfg) 1322c72fcc34Sopenharmony_ci goto check; 1323c72fcc34Sopenharmony_ci 1324c72fcc34Sopenharmony_ci ret = tplg_object_copy_and_add_param(tplg_pp, obj_cfg, n, cfg); 1325c72fcc34Sopenharmony_ci if (ret == 1) 1326c72fcc34Sopenharmony_ci goto check; 1327c72fcc34Sopenharmony_ci else if (ret < 0) 1328c72fcc34Sopenharmony_ci return ret; 1329c72fcc34Sopenharmony_ci continue; 1330c72fcc34Sopenharmony_cicheck: 1331c72fcc34Sopenharmony_ci if (tplg_class_is_attribute_mandatory(id, class_cfg)) { 1332c72fcc34Sopenharmony_ci SNDERR("Mandatory attribute %s not set for class %s\n", id, class_name); 1333c72fcc34Sopenharmony_ci return -EINVAL; 1334c72fcc34Sopenharmony_ci } 1335c72fcc34Sopenharmony_ci } 1336c72fcc34Sopenharmony_ci 1337c72fcc34Sopenharmony_ci return 0; 1338c72fcc34Sopenharmony_ci} 1339c72fcc34Sopenharmony_ci 1340c72fcc34Sopenharmony_cistatic int tplg_object_pre_process_children(struct tplg_pre_processor *tplg_pp, 1341c72fcc34Sopenharmony_ci snd_config_t *parent, snd_config_t *cfg) 1342c72fcc34Sopenharmony_ci{ 1343c72fcc34Sopenharmony_ci snd_config_iterator_t i, next; 1344c72fcc34Sopenharmony_ci snd_config_t *children, *n; 1345c72fcc34Sopenharmony_ci int ret; 1346c72fcc34Sopenharmony_ci 1347c72fcc34Sopenharmony_ci ret = snd_config_search(cfg, "Object", &children); 1348c72fcc34Sopenharmony_ci if (ret < 0) 1349c72fcc34Sopenharmony_ci return 0; 1350c72fcc34Sopenharmony_ci 1351c72fcc34Sopenharmony_ci /* create all embedded objects */ 1352c72fcc34Sopenharmony_ci snd_config_for_each(i, next, children) { 1353c72fcc34Sopenharmony_ci const char *id; 1354c72fcc34Sopenharmony_ci 1355c72fcc34Sopenharmony_ci n = snd_config_iterator_entry(i); 1356c72fcc34Sopenharmony_ci if (snd_config_get_id(n, &id) < 0) 1357c72fcc34Sopenharmony_ci continue; 1358c72fcc34Sopenharmony_ci 1359c72fcc34Sopenharmony_ci ret = tplg_pre_process_objects(tplg_pp, n, parent); 1360c72fcc34Sopenharmony_ci if (ret < 0) 1361c72fcc34Sopenharmony_ci return ret; 1362c72fcc34Sopenharmony_ci } 1363c72fcc34Sopenharmony_ci 1364c72fcc34Sopenharmony_ci return 0; 1365c72fcc34Sopenharmony_ci} 1366c72fcc34Sopenharmony_ci 1367c72fcc34Sopenharmony_cistatic int tplg_construct_object_name(struct tplg_pre_processor *tplg_pp ATTRIBUTE_UNUSED, 1368c72fcc34Sopenharmony_ci snd_config_t *obj, snd_config_t *class_cfg) 1369c72fcc34Sopenharmony_ci{ 1370c72fcc34Sopenharmony_ci snd_config_iterator_t i, next; 1371c72fcc34Sopenharmony_ci snd_config_t *args, *n; 1372c72fcc34Sopenharmony_ci const char *id, *class_id, *obj_id, *s; 1373c72fcc34Sopenharmony_ci char *new_name; 1374c72fcc34Sopenharmony_ci int ret; 1375c72fcc34Sopenharmony_ci 1376c72fcc34Sopenharmony_ci /* find config for class constructor attributes. Nothing to do if not defined */ 1377c72fcc34Sopenharmony_ci ret = snd_config_search(class_cfg, "attributes.constructor", &args); 1378c72fcc34Sopenharmony_ci if (ret < 0) 1379c72fcc34Sopenharmony_ci return 0; 1380c72fcc34Sopenharmony_ci 1381c72fcc34Sopenharmony_ci /* set class name as the name prefix for the object */ 1382c72fcc34Sopenharmony_ci if (snd_config_get_id(obj, &obj_id) < 0) 1383c72fcc34Sopenharmony_ci return -EINVAL; 1384c72fcc34Sopenharmony_ci if (snd_config_get_id(class_cfg, &class_id) < 0) 1385c72fcc34Sopenharmony_ci return -EINVAL; 1386c72fcc34Sopenharmony_ci new_name = strdup(class_id); 1387c72fcc34Sopenharmony_ci if (!new_name) 1388c72fcc34Sopenharmony_ci return -ENOMEM; 1389c72fcc34Sopenharmony_ci 1390c72fcc34Sopenharmony_ci /* iterate through all class arguments and set object name */ 1391c72fcc34Sopenharmony_ci snd_config_for_each(i, next, args) { 1392c72fcc34Sopenharmony_ci snd_config_t *arg; 1393c72fcc34Sopenharmony_ci char *arg_value, *temp; 1394c72fcc34Sopenharmony_ci 1395c72fcc34Sopenharmony_ci n = snd_config_iterator_entry(i); 1396c72fcc34Sopenharmony_ci 1397c72fcc34Sopenharmony_ci if (snd_config_get_id(n, &id) < 0) { 1398c72fcc34Sopenharmony_ci SNDERR("Invalid ID for constructor argument\n"); 1399c72fcc34Sopenharmony_ci ret = -EINVAL; 1400c72fcc34Sopenharmony_ci goto err; 1401c72fcc34Sopenharmony_ci } 1402c72fcc34Sopenharmony_ci 1403c72fcc34Sopenharmony_ci if (snd_config_get_string(n, &s) < 0) { 1404c72fcc34Sopenharmony_ci SNDERR("Invalid value for constructor argument\n"); 1405c72fcc34Sopenharmony_ci ret = -EINVAL; 1406c72fcc34Sopenharmony_ci goto err; 1407c72fcc34Sopenharmony_ci } 1408c72fcc34Sopenharmony_ci 1409c72fcc34Sopenharmony_ci /* find and replace with value set in object */ 1410c72fcc34Sopenharmony_ci ret = snd_config_search(obj, s, &arg); 1411c72fcc34Sopenharmony_ci if (ret < 0) { 1412c72fcc34Sopenharmony_ci SNDERR("Argument %s not set for object '%s.%s'\n", s, class_id, obj_id); 1413c72fcc34Sopenharmony_ci ret = -ENOENT; 1414c72fcc34Sopenharmony_ci goto err; 1415c72fcc34Sopenharmony_ci } 1416c72fcc34Sopenharmony_ci 1417c72fcc34Sopenharmony_ci /* concat arg value to object name. arg types must be either integer or string */ 1418c72fcc34Sopenharmony_ci switch (snd_config_get_type(arg)) { 1419c72fcc34Sopenharmony_ci case SND_CONFIG_TYPE_INTEGER: 1420c72fcc34Sopenharmony_ci { 1421c72fcc34Sopenharmony_ci long v; 1422c72fcc34Sopenharmony_ci ret = snd_config_get_integer(arg, &v); 1423c72fcc34Sopenharmony_ci assert(ret >= 0); 1424c72fcc34Sopenharmony_ci 1425c72fcc34Sopenharmony_ci arg_value = tplg_snprintf("%ld", v); 1426c72fcc34Sopenharmony_ci if (!arg_value) { 1427c72fcc34Sopenharmony_ci ret = -ENOMEM; 1428c72fcc34Sopenharmony_ci goto err; 1429c72fcc34Sopenharmony_ci } 1430c72fcc34Sopenharmony_ci break; 1431c72fcc34Sopenharmony_ci } 1432c72fcc34Sopenharmony_ci case SND_CONFIG_TYPE_STRING: 1433c72fcc34Sopenharmony_ci { 1434c72fcc34Sopenharmony_ci const char *s; 1435c72fcc34Sopenharmony_ci 1436c72fcc34Sopenharmony_ci ret = snd_config_get_string(arg, &s); 1437c72fcc34Sopenharmony_ci assert(ret >= 0); 1438c72fcc34Sopenharmony_ci 1439c72fcc34Sopenharmony_ci arg_value = strdup(s); 1440c72fcc34Sopenharmony_ci if (!arg_value) { 1441c72fcc34Sopenharmony_ci ret = -ENOMEM; 1442c72fcc34Sopenharmony_ci goto err; 1443c72fcc34Sopenharmony_ci } 1444c72fcc34Sopenharmony_ci break; 1445c72fcc34Sopenharmony_ci } 1446c72fcc34Sopenharmony_ci default: 1447c72fcc34Sopenharmony_ci SNDERR("Argument '%s' in object '%s.%s' is not an integer or a string\n", 1448c72fcc34Sopenharmony_ci s, class_id, obj_id); 1449c72fcc34Sopenharmony_ci ret = -EINVAL; 1450c72fcc34Sopenharmony_ci goto err; 1451c72fcc34Sopenharmony_ci } 1452c72fcc34Sopenharmony_ci 1453c72fcc34Sopenharmony_ci /* alloc and concat arg value to the name */ 1454c72fcc34Sopenharmony_ci temp = tplg_snprintf("%s.%s", new_name, arg_value); 1455c72fcc34Sopenharmony_ci free(arg_value); 1456c72fcc34Sopenharmony_ci if (!temp) { 1457c72fcc34Sopenharmony_ci ret = -ENOMEM; 1458c72fcc34Sopenharmony_ci goto err; 1459c72fcc34Sopenharmony_ci } 1460c72fcc34Sopenharmony_ci free(new_name); 1461c72fcc34Sopenharmony_ci new_name = temp; 1462c72fcc34Sopenharmony_ci } 1463c72fcc34Sopenharmony_ci 1464c72fcc34Sopenharmony_ci ret = snd_config_set_id(obj, new_name); 1465c72fcc34Sopenharmony_cierr: 1466c72fcc34Sopenharmony_ci free(new_name); 1467c72fcc34Sopenharmony_ci return ret; 1468c72fcc34Sopenharmony_ci} 1469c72fcc34Sopenharmony_ci 1470c72fcc34Sopenharmony_ci/* set the attribute value by type */ 1471c72fcc34Sopenharmony_cistatic int tplg_set_attribute_value(snd_config_t *attr, const char *value) 1472c72fcc34Sopenharmony_ci{ 1473c72fcc34Sopenharmony_ci int err; 1474c72fcc34Sopenharmony_ci snd_config_type_t type = snd_config_get_type(attr); 1475c72fcc34Sopenharmony_ci 1476c72fcc34Sopenharmony_ci switch (type) { 1477c72fcc34Sopenharmony_ci case SND_CONFIG_TYPE_INTEGER: 1478c72fcc34Sopenharmony_ci { 1479c72fcc34Sopenharmony_ci long v; 1480c72fcc34Sopenharmony_ci 1481c72fcc34Sopenharmony_ci v = strtol(value, NULL, 10); 1482c72fcc34Sopenharmony_ci err = snd_config_set_integer(attr, v); 1483c72fcc34Sopenharmony_ci assert(err >= 0); 1484c72fcc34Sopenharmony_ci break; 1485c72fcc34Sopenharmony_ci } 1486c72fcc34Sopenharmony_ci case SND_CONFIG_TYPE_INTEGER64: 1487c72fcc34Sopenharmony_ci { 1488c72fcc34Sopenharmony_ci long long v; 1489c72fcc34Sopenharmony_ci 1490c72fcc34Sopenharmony_ci v = strtoll(value, NULL, 10); 1491c72fcc34Sopenharmony_ci err = snd_config_set_integer64(attr, v); 1492c72fcc34Sopenharmony_ci assert(err >= 0); 1493c72fcc34Sopenharmony_ci break; 1494c72fcc34Sopenharmony_ci } 1495c72fcc34Sopenharmony_ci case SND_CONFIG_TYPE_STRING: 1496c72fcc34Sopenharmony_ci { 1497c72fcc34Sopenharmony_ci err = snd_config_set_string(attr, value); 1498c72fcc34Sopenharmony_ci assert(err >= 0); 1499c72fcc34Sopenharmony_ci break; 1500c72fcc34Sopenharmony_ci } 1501c72fcc34Sopenharmony_ci default: 1502c72fcc34Sopenharmony_ci return -EINVAL; 1503c72fcc34Sopenharmony_ci } 1504c72fcc34Sopenharmony_ci 1505c72fcc34Sopenharmony_ci return 0; 1506c72fcc34Sopenharmony_ci} 1507c72fcc34Sopenharmony_ci 1508c72fcc34Sopenharmony_ci 1509c72fcc34Sopenharmony_ci/* 1510c72fcc34Sopenharmony_ci * Find the unique attribute in the class definition and set its value and type. 1511c72fcc34Sopenharmony_ci * Only string or integer types are allowed for unique values. 1512c72fcc34Sopenharmony_ci */ 1513c72fcc34Sopenharmony_cistatic int tplg_object_set_unique_attribute(struct tplg_pre_processor *tplg_pp, 1514c72fcc34Sopenharmony_ci snd_config_t *obj, snd_config_t *class_cfg, 1515c72fcc34Sopenharmony_ci const char *id) 1516c72fcc34Sopenharmony_ci{ 1517c72fcc34Sopenharmony_ci snd_config_t *unique_attr, *new; 1518c72fcc34Sopenharmony_ci const char *unique_name, *class_id; 1519c72fcc34Sopenharmony_ci int ret; 1520c72fcc34Sopenharmony_ci 1521c72fcc34Sopenharmony_ci if (snd_config_get_id(class_cfg, &class_id) < 0) 1522c72fcc34Sopenharmony_ci return 0; 1523c72fcc34Sopenharmony_ci 1524c72fcc34Sopenharmony_ci /* find config for class unique attribute */ 1525c72fcc34Sopenharmony_ci unique_name = tplg_class_get_unique_attribute_name(tplg_pp, class_cfg); 1526c72fcc34Sopenharmony_ci if (!unique_name) 1527c72fcc34Sopenharmony_ci return -ENOENT; 1528c72fcc34Sopenharmony_ci 1529c72fcc34Sopenharmony_ci /* find the unique attribute definition in the class */ 1530c72fcc34Sopenharmony_ci unique_attr = tplg_class_find_attribute_by_name(tplg_pp, class_cfg, unique_name); 1531c72fcc34Sopenharmony_ci if (!unique_attr) 1532c72fcc34Sopenharmony_ci return -ENOENT; 1533c72fcc34Sopenharmony_ci 1534c72fcc34Sopenharmony_ci /* override value if unique attribute is set in the object instance */ 1535c72fcc34Sopenharmony_ci ret = snd_config_search(obj, unique_name, &new); 1536c72fcc34Sopenharmony_ci if (ret < 0) { 1537c72fcc34Sopenharmony_ci ret = snd_config_make(&new, unique_name, 1538c72fcc34Sopenharmony_ci tplg_class_get_attribute_type(tplg_pp, unique_attr)); 1539c72fcc34Sopenharmony_ci if (ret < 0) { 1540c72fcc34Sopenharmony_ci SNDERR("error creating new attribute cfg for object %s\n", id); 1541c72fcc34Sopenharmony_ci return ret; 1542c72fcc34Sopenharmony_ci } 1543c72fcc34Sopenharmony_ci ret = snd_config_add(obj, new); 1544c72fcc34Sopenharmony_ci if (ret < 0) { 1545c72fcc34Sopenharmony_ci SNDERR("error adding new attribute cfg for object %s\n", id); 1546c72fcc34Sopenharmony_ci return ret; 1547c72fcc34Sopenharmony_ci } 1548c72fcc34Sopenharmony_ci } 1549c72fcc34Sopenharmony_ci 1550c72fcc34Sopenharmony_ci ret = tplg_set_attribute_value(new, id); 1551c72fcc34Sopenharmony_ci if (ret < 0) { 1552c72fcc34Sopenharmony_ci SNDERR("error setting unique attribute cfg for object %s\n", id); 1553c72fcc34Sopenharmony_ci return ret; 1554c72fcc34Sopenharmony_ci } 1555c72fcc34Sopenharmony_ci 1556c72fcc34Sopenharmony_ci return ret; 1557c72fcc34Sopenharmony_ci} 1558c72fcc34Sopenharmony_ci 1559c72fcc34Sopenharmony_ci/* 1560c72fcc34Sopenharmony_ci * Helper function to get object instance config which is 2 nodes down from class_type config. 1561c72fcc34Sopenharmony_ci * ex: Get the pointer to the config node with ID "0" from the input config Widget.pga.0 {} 1562c72fcc34Sopenharmony_ci */ 1563c72fcc34Sopenharmony_cisnd_config_t *tplg_object_get_instance_config(struct tplg_pre_processor *tplg_pp ATTRIBUTE_UNUSED, 1564c72fcc34Sopenharmony_ci snd_config_t *class_type) 1565c72fcc34Sopenharmony_ci{ 1566c72fcc34Sopenharmony_ci snd_config_iterator_t first; 1567c72fcc34Sopenharmony_ci snd_config_t *cfg; 1568c72fcc34Sopenharmony_ci 1569c72fcc34Sopenharmony_ci first = snd_config_iterator_first(class_type); 1570c72fcc34Sopenharmony_ci cfg = snd_config_iterator_entry(first); 1571c72fcc34Sopenharmony_ci first = snd_config_iterator_first(cfg); 1572c72fcc34Sopenharmony_ci return snd_config_iterator_entry(first); 1573c72fcc34Sopenharmony_ci} 1574c72fcc34Sopenharmony_ci 1575c72fcc34Sopenharmony_ci#if SND_LIB_VER(1, 2, 5) < SND_LIB_VERSION 1576c72fcc34Sopenharmony_cistatic int pre_process_find_variable(snd_config_t **dst, const char *str, snd_config_t *config) 1577c72fcc34Sopenharmony_ci{ 1578c72fcc34Sopenharmony_ci snd_config_iterator_t i, next; 1579c72fcc34Sopenharmony_ci 1580c72fcc34Sopenharmony_ci snd_config_for_each(i, next, config) { 1581c72fcc34Sopenharmony_ci snd_config_t *n; 1582c72fcc34Sopenharmony_ci const char *id; 1583c72fcc34Sopenharmony_ci 1584c72fcc34Sopenharmony_ci n = snd_config_iterator_entry(i); 1585c72fcc34Sopenharmony_ci if (snd_config_get_id(n, &id) < 0) 1586c72fcc34Sopenharmony_ci continue; 1587c72fcc34Sopenharmony_ci 1588c72fcc34Sopenharmony_ci if (strcmp(id, str)) 1589c72fcc34Sopenharmony_ci continue; 1590c72fcc34Sopenharmony_ci 1591c72fcc34Sopenharmony_ci /* found definition, copy config */ 1592c72fcc34Sopenharmony_ci return snd_config_copy(dst, n); 1593c72fcc34Sopenharmony_ci } 1594c72fcc34Sopenharmony_ci 1595c72fcc34Sopenharmony_ci return -EINVAL; 1596c72fcc34Sopenharmony_ci} 1597c72fcc34Sopenharmony_ci 1598c72fcc34Sopenharmony_cistatic int 1599c72fcc34Sopenharmony_cipre_process_object_variables_expand_fcn(snd_config_t **dst, const char *str, void *private_data) 1600c72fcc34Sopenharmony_ci{ 1601c72fcc34Sopenharmony_ci 1602c72fcc34Sopenharmony_ci struct tplg_pre_processor *tplg_pp = private_data; 1603c72fcc34Sopenharmony_ci snd_config_t *object_cfg = tplg_pp->current_obj_cfg; 1604c72fcc34Sopenharmony_ci snd_config_t *conf_defines; 1605c72fcc34Sopenharmony_ci const char *object_id; 1606c72fcc34Sopenharmony_ci const char *val; 1607c72fcc34Sopenharmony_ci int ret; 1608c72fcc34Sopenharmony_ci 1609c72fcc34Sopenharmony_ci ret = snd_config_search(tplg_pp->input_cfg, "Define", &conf_defines); 1610c72fcc34Sopenharmony_ci if (ret < 0) 1611c72fcc34Sopenharmony_ci return 0; 1612c72fcc34Sopenharmony_ci 1613c72fcc34Sopenharmony_ci /* find variable from global definitions first */ 1614c72fcc34Sopenharmony_ci ret = pre_process_find_variable(dst, str, conf_defines); 1615c72fcc34Sopenharmony_ci if (ret >= 0) 1616c72fcc34Sopenharmony_ci return ret; 1617c72fcc34Sopenharmony_ci 1618c72fcc34Sopenharmony_ci /* No global define found, proceeed to object attribute search */ 1619c72fcc34Sopenharmony_ci if (snd_config_get_id(object_cfg, &object_id) < 0) 1620c72fcc34Sopenharmony_ci return -EINVAL; 1621c72fcc34Sopenharmony_ci 1622c72fcc34Sopenharmony_ci /* find variable from object attribute values if not found in global definitions */ 1623c72fcc34Sopenharmony_ci ret = pre_process_find_variable(dst, str, object_cfg); 1624c72fcc34Sopenharmony_ci if (ret < 0) { 1625c72fcc34Sopenharmony_ci SNDERR("Failed to find definition for attribute %s in '%s' object\n", 1626c72fcc34Sopenharmony_ci str, object_id); 1627c72fcc34Sopenharmony_ci return ret; 1628c72fcc34Sopenharmony_ci } 1629c72fcc34Sopenharmony_ci 1630c72fcc34Sopenharmony_ci /* the extracted value may contain a nested $-expression */ 1631c72fcc34Sopenharmony_ci if (snd_config_get_string(*dst, &val) >= 0) { 1632c72fcc34Sopenharmony_ci if (val[0] == '$') { 1633c72fcc34Sopenharmony_ci char *var = strdup(val); 1634c72fcc34Sopenharmony_ci 1635c72fcc34Sopenharmony_ci snd_config_delete(*dst); 1636c72fcc34Sopenharmony_ci ret = snd_config_evaluate_string(dst, var, 1637c72fcc34Sopenharmony_ci pre_process_object_variables_expand_fcn, 1638c72fcc34Sopenharmony_ci tplg_pp); 1639c72fcc34Sopenharmony_ci free(var); 1640c72fcc34Sopenharmony_ci } 1641c72fcc34Sopenharmony_ci } 1642c72fcc34Sopenharmony_ci 1643c72fcc34Sopenharmony_ci return ret; 1644c72fcc34Sopenharmony_ci} 1645c72fcc34Sopenharmony_ci 1646c72fcc34Sopenharmony_ci/* 1647c72fcc34Sopenharmony_ci * Searches for the first '$VAR_NAME' or '$[<contents>]' occurrence in 1648c72fcc34Sopenharmony_ci * *stringp. Allocates memory for it and copies it there. The 1649c72fcc34Sopenharmony_ci * allocated string is returned in '*varname'. If there was a prefix 1650c72fcc34Sopenharmony_ci * before $VAR_NAME, it is returned in '*prefix'. The *stringp is 1651c72fcc34Sopenharmony_ci * moved forward to the char after the $VAR_NAME. 1652c72fcc34Sopenharmony_ci * 1653c72fcc34Sopenharmony_ci * The end of $VAR_NAME is the first char that is not alpha numeric, '_', 1654c72fcc34Sopenharmony_ci * or '\0'. 1655c72fcc34Sopenharmony_ci * 1656c72fcc34Sopenharmony_ci * In '$[<contents>]' case all letters but '[' and ']' are allow in 1657c72fcc34Sopenharmony_ci * any sequence. Nested '[]' is also allowed if the number of '[' and 1658c72fcc34Sopenharmony_ci * ']' match. 1659c72fcc34Sopenharmony_ci * 1660c72fcc34Sopenharmony_ci * The function modifies *stringp, and *prefix - if not NULL - points 1661c72fcc34Sopenharmony_ci * to the original *stringp, *varname - if not NULL - is malloced and 1662c72fcc34Sopenharmony_ci * should be freed by the caller. 1663c72fcc34Sopenharmony_ci * 1664c72fcc34Sopenharmony_ci * Returns 0 if the *stringp was an empty string. 1665c72fcc34Sopenharmony_ci * 1 if *prefix or *varname was set 1666c72fcc34Sopenharmony_ci * -ENOMEM if malloc failed 1667c72fcc34Sopenharmony_ci */ 1668c72fcc34Sopenharmony_cistatic int tplg_get_varname(char **stringp, char **prefix, char **varname) 1669c72fcc34Sopenharmony_ci{ 1670c72fcc34Sopenharmony_ci size_t prefix_len, varname_len = 0; 1671c72fcc34Sopenharmony_ci 1672c72fcc34Sopenharmony_ci *prefix = NULL; 1673c72fcc34Sopenharmony_ci *varname = NULL; 1674c72fcc34Sopenharmony_ci 1675c72fcc34Sopenharmony_ci prefix_len = strcspn(*stringp, "$"); 1676c72fcc34Sopenharmony_ci *prefix = *stringp; 1677c72fcc34Sopenharmony_ci (*stringp) += prefix_len; 1678c72fcc34Sopenharmony_ci if (**stringp == '$') { 1679c72fcc34Sopenharmony_ci if ((*stringp)[1] == '[') { 1680c72fcc34Sopenharmony_ci int brackets = 1; 1681c72fcc34Sopenharmony_ci varname_len = 1; 1682c72fcc34Sopenharmony_ci 1683c72fcc34Sopenharmony_ci do { 1684c72fcc34Sopenharmony_ci varname_len += strcspn((*stringp) + varname_len + 1, "[]") + 1; 1685c72fcc34Sopenharmony_ci if ((*stringp)[varname_len] == '[') 1686c72fcc34Sopenharmony_ci brackets++; 1687c72fcc34Sopenharmony_ci else if ((*stringp)[varname_len] == ']') 1688c72fcc34Sopenharmony_ci brackets--; 1689c72fcc34Sopenharmony_ci else 1690c72fcc34Sopenharmony_ci break; 1691c72fcc34Sopenharmony_ci } while (brackets > 0); 1692c72fcc34Sopenharmony_ci if (brackets != 0) 1693c72fcc34Sopenharmony_ci return -EINVAL; 1694c72fcc34Sopenharmony_ci varname_len++; 1695c72fcc34Sopenharmony_ci } else { 1696c72fcc34Sopenharmony_ci varname_len = 1; 1697c72fcc34Sopenharmony_ci while (isalnum((*stringp)[varname_len]) || (*stringp)[varname_len] == '_') 1698c72fcc34Sopenharmony_ci varname_len++; 1699c72fcc34Sopenharmony_ci } 1700c72fcc34Sopenharmony_ci } 1701c72fcc34Sopenharmony_ci 1702c72fcc34Sopenharmony_ci if (varname_len == 0 && prefix_len == 0) 1703c72fcc34Sopenharmony_ci return 0; 1704c72fcc34Sopenharmony_ci 1705c72fcc34Sopenharmony_ci if (varname_len) { 1706c72fcc34Sopenharmony_ci *varname = malloc(varname_len + 1); 1707c72fcc34Sopenharmony_ci if (*varname == NULL) 1708c72fcc34Sopenharmony_ci return -ENOMEM; 1709c72fcc34Sopenharmony_ci strncpy(*varname, *stringp, varname_len); 1710c72fcc34Sopenharmony_ci (*varname)[varname_len] = '\0'; 1711c72fcc34Sopenharmony_ci (*stringp) += varname_len; 1712c72fcc34Sopenharmony_ci } 1713c72fcc34Sopenharmony_ci 1714c72fcc34Sopenharmony_ci if (prefix_len) 1715c72fcc34Sopenharmony_ci (*prefix)[prefix_len] = '\0'; 1716c72fcc34Sopenharmony_ci else 1717c72fcc34Sopenharmony_ci *prefix = NULL; 1718c72fcc34Sopenharmony_ci 1719c72fcc34Sopenharmony_ci return 1; 1720c72fcc34Sopenharmony_ci} 1721c72fcc34Sopenharmony_ci 1722c72fcc34Sopenharmony_cistatic int tplg_evaluate_config_string(struct tplg_pre_processor *tplg_pp, 1723c72fcc34Sopenharmony_ci snd_config_t **dst, const char *s, const char *id) 1724c72fcc34Sopenharmony_ci{ 1725c72fcc34Sopenharmony_ci char *str = strdup(s); 1726c72fcc34Sopenharmony_ci char *varname, *prefix, *freep = str; 1727c72fcc34Sopenharmony_ci int ret; 1728c72fcc34Sopenharmony_ci 1729c72fcc34Sopenharmony_ci if (!str) 1730c72fcc34Sopenharmony_ci return -ENOMEM; 1731c72fcc34Sopenharmony_ci 1732c72fcc34Sopenharmony_ci *dst = NULL; 1733c72fcc34Sopenharmony_ci 1734c72fcc34Sopenharmony_ci /* split the string and expand global definitions or object attribute values */ 1735c72fcc34Sopenharmony_ci while (tplg_get_varname(&str, &prefix, &varname) == 1) { 1736c72fcc34Sopenharmony_ci const char *current_str; 1737c72fcc34Sopenharmony_ci char *temp; 1738c72fcc34Sopenharmony_ci 1739c72fcc34Sopenharmony_ci if (prefix) { 1740c72fcc34Sopenharmony_ci if (*dst == NULL) { 1741c72fcc34Sopenharmony_ci ret = snd_config_make(dst, id, SND_CONFIG_TYPE_STRING); 1742c72fcc34Sopenharmony_ci if (ret < 0) 1743c72fcc34Sopenharmony_ci goto out; 1744c72fcc34Sopenharmony_ci ret = snd_config_set_string(*dst, prefix); 1745c72fcc34Sopenharmony_ci if (ret < 0) 1746c72fcc34Sopenharmony_ci goto out; 1747c72fcc34Sopenharmony_ci } else { 1748c72fcc34Sopenharmony_ci /* concat the prefix */ 1749c72fcc34Sopenharmony_ci snd_config_get_string(*dst, ¤t_str); 1750c72fcc34Sopenharmony_ci temp = tplg_snprintf("%s%s", current_str, prefix); 1751c72fcc34Sopenharmony_ci if (!temp) { 1752c72fcc34Sopenharmony_ci ret = -ENOMEM; 1753c72fcc34Sopenharmony_ci goto out; 1754c72fcc34Sopenharmony_ci } 1755c72fcc34Sopenharmony_ci 1756c72fcc34Sopenharmony_ci ret = snd_config_set_string(*dst, temp); 1757c72fcc34Sopenharmony_ci free(temp); 1758c72fcc34Sopenharmony_ci if (ret < 0) 1759c72fcc34Sopenharmony_ci goto out; 1760c72fcc34Sopenharmony_ci } 1761c72fcc34Sopenharmony_ci } 1762c72fcc34Sopenharmony_ci 1763c72fcc34Sopenharmony_ci if (varname) { 1764c72fcc34Sopenharmony_ci snd_config_t *tmp_config; 1765c72fcc34Sopenharmony_ci 1766c72fcc34Sopenharmony_ci ret = snd_config_evaluate_string(&tmp_config, varname, 1767c72fcc34Sopenharmony_ci pre_process_object_variables_expand_fcn, 1768c72fcc34Sopenharmony_ci tplg_pp); 1769c72fcc34Sopenharmony_ci if (ret < 0) 1770c72fcc34Sopenharmony_ci goto out; 1771c72fcc34Sopenharmony_ci 1772c72fcc34Sopenharmony_ci if (*dst == NULL) { 1773c72fcc34Sopenharmony_ci *dst = tmp_config; 1774c72fcc34Sopenharmony_ci } else { 1775c72fcc34Sopenharmony_ci char *ascii; 1776c72fcc34Sopenharmony_ci 1777c72fcc34Sopenharmony_ci snd_config_get_string(*dst, ¤t_str); 1778c72fcc34Sopenharmony_ci 1779c72fcc34Sopenharmony_ci ret = snd_config_get_ascii(tmp_config, &ascii); 1780c72fcc34Sopenharmony_ci if (ret) 1781c72fcc34Sopenharmony_ci goto out; 1782c72fcc34Sopenharmony_ci 1783c72fcc34Sopenharmony_ci temp = tplg_snprintf("%s%s", current_str, ascii); 1784c72fcc34Sopenharmony_ci free(ascii); 1785c72fcc34Sopenharmony_ci 1786c72fcc34Sopenharmony_ci if (!temp) { 1787c72fcc34Sopenharmony_ci ret = -ENOMEM; 1788c72fcc34Sopenharmony_ci goto out; 1789c72fcc34Sopenharmony_ci } 1790c72fcc34Sopenharmony_ci 1791c72fcc34Sopenharmony_ci ret = snd_config_set_string(*dst, temp); 1792c72fcc34Sopenharmony_ci free(temp); 1793c72fcc34Sopenharmony_ci snd_config_delete(tmp_config); 1794c72fcc34Sopenharmony_ci if (ret < 0) 1795c72fcc34Sopenharmony_ci goto out; 1796c72fcc34Sopenharmony_ci } 1797c72fcc34Sopenharmony_ci free(varname); 1798c72fcc34Sopenharmony_ci } 1799c72fcc34Sopenharmony_ci } 1800c72fcc34Sopenharmony_ci 1801c72fcc34Sopenharmony_ci free(freep); 1802c72fcc34Sopenharmony_ci snd_config_set_id(*dst, id); 1803c72fcc34Sopenharmony_ci 1804c72fcc34Sopenharmony_ci return 0; 1805c72fcc34Sopenharmony_ciout: 1806c72fcc34Sopenharmony_ci if (*dst) 1807c72fcc34Sopenharmony_ci snd_config_delete(*dst); 1808c72fcc34Sopenharmony_ci free(varname); 1809c72fcc34Sopenharmony_ci free(freep); 1810c72fcc34Sopenharmony_ci return ret; 1811c72fcc34Sopenharmony_ci} 1812c72fcc34Sopenharmony_ci 1813c72fcc34Sopenharmony_ci#endif 1814c72fcc34Sopenharmony_ci 1815c72fcc34Sopenharmony_ci/* build object config and its child objects recursively */ 1816c72fcc34Sopenharmony_cistatic int tplg_build_object(struct tplg_pre_processor *tplg_pp, snd_config_t *new_obj, 1817c72fcc34Sopenharmony_ci snd_config_t *parent) 1818c72fcc34Sopenharmony_ci{ 1819c72fcc34Sopenharmony_ci snd_config_t *obj_local, *class_cfg; 1820c72fcc34Sopenharmony_ci const struct build_function_map *map; 1821c72fcc34Sopenharmony_ci snd_config_iterator_t i, next; 1822c72fcc34Sopenharmony_ci build_func builder; 1823c72fcc34Sopenharmony_ci update_auto_attr_func auto_attr_updater; 1824c72fcc34Sopenharmony_ci const char *id, *class_id; 1825c72fcc34Sopenharmony_ci int ret; 1826c72fcc34Sopenharmony_ci 1827c72fcc34Sopenharmony_ci obj_local = tplg_object_get_instance_config(tplg_pp, new_obj); 1828c72fcc34Sopenharmony_ci if (!obj_local) 1829c72fcc34Sopenharmony_ci return -EINVAL; 1830c72fcc34Sopenharmony_ci 1831c72fcc34Sopenharmony_ci class_cfg = tplg_class_lookup(tplg_pp, new_obj); 1832c72fcc34Sopenharmony_ci if (!class_cfg) 1833c72fcc34Sopenharmony_ci return -EINVAL; 1834c72fcc34Sopenharmony_ci 1835c72fcc34Sopenharmony_ci if (snd_config_get_id(obj_local, &id) < 0) 1836c72fcc34Sopenharmony_ci return 0; 1837c72fcc34Sopenharmony_ci 1838c72fcc34Sopenharmony_ci if (snd_config_get_id(class_cfg, &class_id) < 0) 1839c72fcc34Sopenharmony_ci return 0; 1840c72fcc34Sopenharmony_ci 1841c72fcc34Sopenharmony_ci /* set unique attribute value */ 1842c72fcc34Sopenharmony_ci ret = tplg_object_set_unique_attribute(tplg_pp, obj_local, class_cfg, id); 1843c72fcc34Sopenharmony_ci if (ret < 0) { 1844c72fcc34Sopenharmony_ci SNDERR("error setting unique attribute value for '%s.%s'\n", class_id, id); 1845c72fcc34Sopenharmony_ci return ret; 1846c72fcc34Sopenharmony_ci } 1847c72fcc34Sopenharmony_ci 1848c72fcc34Sopenharmony_ci /* update object attributes and validate them */ 1849c72fcc34Sopenharmony_ci ret = tplg_object_update(tplg_pp, new_obj, parent); 1850c72fcc34Sopenharmony_ci if (ret < 0) { 1851c72fcc34Sopenharmony_ci SNDERR("Failed to update attributes for object '%s.%s'\n", class_id, id); 1852c72fcc34Sopenharmony_ci return ret; 1853c72fcc34Sopenharmony_ci } 1854c72fcc34Sopenharmony_ci 1855c72fcc34Sopenharmony_ci#if SND_LIB_VER(1, 2, 5) < SND_LIB_VERSION 1856c72fcc34Sopenharmony_ci tplg_pp_config_debug(tplg_pp, obj_local); 1857c72fcc34Sopenharmony_ci 1858c72fcc34Sopenharmony_ci /* expand all non-compound type child configs in object */ 1859c72fcc34Sopenharmony_ci snd_config_for_each(i, next, obj_local) { 1860c72fcc34Sopenharmony_ci snd_config_t *n, *new, *class_attr; 1861c72fcc34Sopenharmony_ci const char *id, *s; 1862c72fcc34Sopenharmony_ci char *attr_config_name; 1863c72fcc34Sopenharmony_ci 1864c72fcc34Sopenharmony_ci n = snd_config_iterator_entry(i); 1865c72fcc34Sopenharmony_ci 1866c72fcc34Sopenharmony_ci if (snd_config_get_type(n) == SND_CONFIG_TYPE_COMPOUND) 1867c72fcc34Sopenharmony_ci continue; 1868c72fcc34Sopenharmony_ci 1869c72fcc34Sopenharmony_ci if (snd_config_get_id(n, &id) < 0) 1870c72fcc34Sopenharmony_ci continue; 1871c72fcc34Sopenharmony_ci 1872c72fcc34Sopenharmony_ci if (snd_config_get_string(n, &s) < 0) 1873c72fcc34Sopenharmony_ci continue; 1874c72fcc34Sopenharmony_ci 1875c72fcc34Sopenharmony_ci if (!strstr(s, "$")) 1876c72fcc34Sopenharmony_ci goto validate; 1877c72fcc34Sopenharmony_ci 1878c72fcc34Sopenharmony_ci tplg_pp->current_obj_cfg = obj_local; 1879c72fcc34Sopenharmony_ci 1880c72fcc34Sopenharmony_ci /* Expand definitions and object attribute references. */ 1881c72fcc34Sopenharmony_ci ret = tplg_evaluate_config_string(tplg_pp, &new, s, id); 1882c72fcc34Sopenharmony_ci if (ret < 0) { 1883c72fcc34Sopenharmony_ci SNDERR("Failed to evaluate attributes %s in %s, from '%s'\n", 1884c72fcc34Sopenharmony_ci id, class_id, s); 1885c72fcc34Sopenharmony_ci return ret; 1886c72fcc34Sopenharmony_ci } 1887c72fcc34Sopenharmony_ci 1888c72fcc34Sopenharmony_ci ret = snd_config_merge(n, new, true); 1889c72fcc34Sopenharmony_ci if (ret < 0) 1890c72fcc34Sopenharmony_ci return ret; 1891c72fcc34Sopenharmony_civalidate: 1892c72fcc34Sopenharmony_ci /* validate attribute value */ 1893c72fcc34Sopenharmony_ci snd_config_get_id(n, &id); 1894c72fcc34Sopenharmony_ci attr_config_name = tplg_snprintf("DefineAttribute.%s", id); 1895c72fcc34Sopenharmony_ci if (!attr_config_name) 1896c72fcc34Sopenharmony_ci return -ENOMEM; 1897c72fcc34Sopenharmony_ci 1898c72fcc34Sopenharmony_ci ret = snd_config_search(class_cfg, attr_config_name, &class_attr); 1899c72fcc34Sopenharmony_ci free(attr_config_name); 1900c72fcc34Sopenharmony_ci if (ret < 0) 1901c72fcc34Sopenharmony_ci continue; 1902c72fcc34Sopenharmony_ci 1903c72fcc34Sopenharmony_ci if (!tplg_object_is_attribute_valid(tplg_pp, class_attr, n)) { 1904c72fcc34Sopenharmony_ci SNDERR("Failed to validate attribute %s in %s\n", id, class_id); 1905c72fcc34Sopenharmony_ci return -EINVAL; 1906c72fcc34Sopenharmony_ci } 1907c72fcc34Sopenharmony_ci } 1908c72fcc34Sopenharmony_ci#endif 1909c72fcc34Sopenharmony_ci 1910c72fcc34Sopenharmony_ci /* construct object name using class constructor */ 1911c72fcc34Sopenharmony_ci ret = tplg_construct_object_name(tplg_pp, obj_local, class_cfg); 1912c72fcc34Sopenharmony_ci if (ret < 0) { 1913c72fcc34Sopenharmony_ci SNDERR("Failed to construct object name for %s\n", id); 1914c72fcc34Sopenharmony_ci return ret; 1915c72fcc34Sopenharmony_ci } 1916c72fcc34Sopenharmony_ci 1917c72fcc34Sopenharmony_ci /* 1918c72fcc34Sopenharmony_ci * Build objects if object type is supported. 1919c72fcc34Sopenharmony_ci * If not, process object attributes and add to parent's data section 1920c72fcc34Sopenharmony_ci */ 1921c72fcc34Sopenharmony_ci map = tplg_object_get_map(tplg_pp, new_obj); 1922c72fcc34Sopenharmony_ci if (map) { 1923c72fcc34Sopenharmony_ci builder = map->builder; 1924c72fcc34Sopenharmony_ci 1925c72fcc34Sopenharmony_ci /* update automatic attribute for current object */ 1926c72fcc34Sopenharmony_ci auto_attr_updater = map->auto_attr_updater; 1927c72fcc34Sopenharmony_ci if(auto_attr_updater) { 1928c72fcc34Sopenharmony_ci ret = auto_attr_updater(tplg_pp, obj_local, parent); 1929c72fcc34Sopenharmony_ci if (ret < 0) { 1930c72fcc34Sopenharmony_ci SNDERR("Failed to update automatic attributes for %s\n", id); 1931c72fcc34Sopenharmony_ci return ret; 1932c72fcc34Sopenharmony_ci } 1933c72fcc34Sopenharmony_ci } 1934c72fcc34Sopenharmony_ci } else { 1935c72fcc34Sopenharmony_ci builder = &tplg_build_parent_data; 1936c72fcc34Sopenharmony_ci } 1937c72fcc34Sopenharmony_ci 1938c72fcc34Sopenharmony_ci ret = builder(tplg_pp, new_obj, parent); 1939c72fcc34Sopenharmony_ci if (ret < 0) 1940c72fcc34Sopenharmony_ci return ret; 1941c72fcc34Sopenharmony_ci 1942c72fcc34Sopenharmony_ci /* create child objects in the object instance */ 1943c72fcc34Sopenharmony_ci ret = tplg_object_pre_process_children(tplg_pp, new_obj, obj_local); 1944c72fcc34Sopenharmony_ci if (ret < 0) { 1945c72fcc34Sopenharmony_ci SNDERR("error processing child objects in object %s\n", id); 1946c72fcc34Sopenharmony_ci return ret; 1947c72fcc34Sopenharmony_ci } 1948c72fcc34Sopenharmony_ci 1949c72fcc34Sopenharmony_ci /* create child objects in the object's class definition */ 1950c72fcc34Sopenharmony_ci ret = tplg_object_pre_process_children(tplg_pp, new_obj, class_cfg); 1951c72fcc34Sopenharmony_ci if (ret < 0) 1952c72fcc34Sopenharmony_ci SNDERR("error processing child objects in class %s\n", class_id); 1953c72fcc34Sopenharmony_ci 1954c72fcc34Sopenharmony_ci return ret; 1955c72fcc34Sopenharmony_ci} 1956c72fcc34Sopenharmony_ci 1957c72fcc34Sopenharmony_ci/* create top-level topology objects */ 1958c72fcc34Sopenharmony_ciint tplg_pre_process_objects(struct tplg_pre_processor *tplg_pp, snd_config_t *cfg, 1959c72fcc34Sopenharmony_ci snd_config_t *parent) 1960c72fcc34Sopenharmony_ci{ 1961c72fcc34Sopenharmony_ci snd_config_iterator_t i, next, i2, next2; 1962c72fcc34Sopenharmony_ci snd_config_t *n, *n2, *_obj_type, *_obj_class, *_obj; 1963c72fcc34Sopenharmony_ci const char *id, *class_type, *class_name; 1964c72fcc34Sopenharmony_ci int ret; 1965c72fcc34Sopenharmony_ci 1966c72fcc34Sopenharmony_ci if (snd_config_get_id(cfg, &class_type) < 0) 1967c72fcc34Sopenharmony_ci return 0; 1968c72fcc34Sopenharmony_ci 1969c72fcc34Sopenharmony_ci /* create all objects of the same type and class */ 1970c72fcc34Sopenharmony_ci snd_config_for_each(i, next, cfg) { 1971c72fcc34Sopenharmony_ci n = snd_config_iterator_entry(i); 1972c72fcc34Sopenharmony_ci if (snd_config_get_id(n, &class_name) < 0) 1973c72fcc34Sopenharmony_ci continue; 1974c72fcc34Sopenharmony_ci snd_config_for_each(i2, next2, n) { 1975c72fcc34Sopenharmony_ci snd_config_t *temp_n2; 1976c72fcc34Sopenharmony_ci 1977c72fcc34Sopenharmony_ci n2 = snd_config_iterator_entry(i2); 1978c72fcc34Sopenharmony_ci if (snd_config_get_id(n2, &id) < 0) { 1979c72fcc34Sopenharmony_ci SNDERR("Invalid id for object\n"); 1980c72fcc34Sopenharmony_ci return -EINVAL; 1981c72fcc34Sopenharmony_ci } 1982c72fcc34Sopenharmony_ci 1983c72fcc34Sopenharmony_ci ret = snd_config_copy(&temp_n2, n2); 1984c72fcc34Sopenharmony_ci if (ret < 0) 1985c72fcc34Sopenharmony_ci return ret; 1986c72fcc34Sopenharmony_ci 1987c72fcc34Sopenharmony_ci /* 1988c72fcc34Sopenharmony_ci * An object declared within a class definition as follows: 1989c72fcc34Sopenharmony_ci * Class.Pipeline.volume-playback { 1990c72fcc34Sopenharmony_ci * Object.Widget.pga.0 { 1991c72fcc34Sopenharmony_ci * ramp_step_ms 250 1992c72fcc34Sopenharmony_ci * } 1993c72fcc34Sopenharmony_ci * } 1994c72fcc34Sopenharmony_ci * 1995c72fcc34Sopenharmony_ci * While instantiating the volume-pipeline class, the pga object 1996c72fcc34Sopenharmony_ci * could be modified as follows: 1997c72fcc34Sopenharmony_ci * Object.Pipeline.volume-playback.0 { 1998c72fcc34Sopenharmony_ci * Object.Widget.pga.0 { 1999c72fcc34Sopenharmony_ci * format "s24le" 2000c72fcc34Sopenharmony_ci * } 2001c72fcc34Sopenharmony_ci * } 2002c72fcc34Sopenharmony_ci * When building the pga.0 object in the class definition, merge 2003c72fcc34Sopenharmony_ci * the attributes declared in the volume-playback.0 object to create 2004c72fcc34Sopenharmony_ci * a new config as follows to make sure that all attributes are 2005c72fcc34Sopenharmony_ci * set for the pga object. 2006c72fcc34Sopenharmony_ci * Object.Widget.pga.0 { 2007c72fcc34Sopenharmony_ci * ramp_step_ms 250 2008c72fcc34Sopenharmony_ci * format "s24le" 2009c72fcc34Sopenharmony_ci * } 2010c72fcc34Sopenharmony_ci */ 2011c72fcc34Sopenharmony_ci 2012c72fcc34Sopenharmony_ci if (parent) { 2013c72fcc34Sopenharmony_ci snd_config_t *parent_instance, *parent_obj, *temp; 2014c72fcc34Sopenharmony_ci char *obj_cfg_name; 2015c72fcc34Sopenharmony_ci 2016c72fcc34Sopenharmony_ci obj_cfg_name = tplg_snprintf("%s%s.%s.%s", "Object.", 2017c72fcc34Sopenharmony_ci class_type, class_name, id); 2018c72fcc34Sopenharmony_ci 2019c72fcc34Sopenharmony_ci /* search for object instance in the parent */ 2020c72fcc34Sopenharmony_ci parent_instance = tplg_object_get_instance_config(tplg_pp, parent); 2021c72fcc34Sopenharmony_ci if (!parent_instance) 2022c72fcc34Sopenharmony_ci goto temp_cfg; 2023c72fcc34Sopenharmony_ci 2024c72fcc34Sopenharmony_ci ret = snd_config_search(parent_instance, obj_cfg_name, &parent_obj); 2025c72fcc34Sopenharmony_ci free(obj_cfg_name); 2026c72fcc34Sopenharmony_ci if (ret < 0) 2027c72fcc34Sopenharmony_ci goto temp_cfg; 2028c72fcc34Sopenharmony_ci 2029c72fcc34Sopenharmony_ci /* don't merge if the object configs are the same */ 2030c72fcc34Sopenharmony_ci if (parent_obj == n2) 2031c72fcc34Sopenharmony_ci goto temp_cfg; 2032c72fcc34Sopenharmony_ci 2033c72fcc34Sopenharmony_ci /* create a temp config copying the parent object config */ 2034c72fcc34Sopenharmony_ci ret = snd_config_copy(&temp, parent_obj); 2035c72fcc34Sopenharmony_ci if (ret < 0) { 2036c72fcc34Sopenharmony_ci snd_config_delete(temp_n2); 2037c72fcc34Sopenharmony_ci return ret; 2038c72fcc34Sopenharmony_ci } 2039c72fcc34Sopenharmony_ci 2040c72fcc34Sopenharmony_ci /* 2041c72fcc34Sopenharmony_ci * Merge parent object with the current object instance. 2042c72fcc34Sopenharmony_ci * temp will be deleted by merge 2043c72fcc34Sopenharmony_ci */ 2044c72fcc34Sopenharmony_ci ret = snd_config_merge(temp_n2, temp, false); 2045c72fcc34Sopenharmony_ci if (ret < 0) { 2046c72fcc34Sopenharmony_ci SNDERR("error merging parent object config for %s.%s.%s\n", 2047c72fcc34Sopenharmony_ci class_type, class_name, id); 2048c72fcc34Sopenharmony_ci snd_config_delete(temp_n2); 2049c72fcc34Sopenharmony_ci return ret; 2050c72fcc34Sopenharmony_ci } 2051c72fcc34Sopenharmony_ci } 2052c72fcc34Sopenharmony_citemp_cfg: 2053c72fcc34Sopenharmony_ci /* create a temp config for object with class type as the root node */ 2054c72fcc34Sopenharmony_ci ret = snd_config_make(&_obj_type, class_type, SND_CONFIG_TYPE_COMPOUND); 2055c72fcc34Sopenharmony_ci if (ret < 0) { 2056c72fcc34Sopenharmony_ci snd_config_delete(temp_n2); 2057c72fcc34Sopenharmony_ci return ret; 2058c72fcc34Sopenharmony_ci } 2059c72fcc34Sopenharmony_ci 2060c72fcc34Sopenharmony_ci ret = snd_config_make(&_obj_class, class_name, SND_CONFIG_TYPE_COMPOUND); 2061c72fcc34Sopenharmony_ci if (ret < 0) 2062c72fcc34Sopenharmony_ci goto err; 2063c72fcc34Sopenharmony_ci 2064c72fcc34Sopenharmony_ci ret = snd_config_add(_obj_type, _obj_class); 2065c72fcc34Sopenharmony_ci if (ret < 0) { 2066c72fcc34Sopenharmony_ci snd_config_delete(_obj_class); 2067c72fcc34Sopenharmony_ci goto err; 2068c72fcc34Sopenharmony_ci } 2069c72fcc34Sopenharmony_ci 2070c72fcc34Sopenharmony_ci ret = snd_config_copy(&_obj, temp_n2); 2071c72fcc34Sopenharmony_ci if (ret < 0) 2072c72fcc34Sopenharmony_ci goto err; 2073c72fcc34Sopenharmony_ci 2074c72fcc34Sopenharmony_ci ret = snd_config_add(_obj_class, _obj); 2075c72fcc34Sopenharmony_ci if (ret < 0) { 2076c72fcc34Sopenharmony_ci snd_config_delete(_obj); 2077c72fcc34Sopenharmony_ci goto err; 2078c72fcc34Sopenharmony_ci } 2079c72fcc34Sopenharmony_ci 2080c72fcc34Sopenharmony_ci /* Build the object now */ 2081c72fcc34Sopenharmony_ci ret = tplg_build_object(tplg_pp, _obj_type, parent); 2082c72fcc34Sopenharmony_ci if (ret < 0) 2083c72fcc34Sopenharmony_ci SNDERR("Error building object %s.%s.%s\n", 2084c72fcc34Sopenharmony_ci class_type, class_name, id); 2085c72fcc34Sopenharmony_cierr: 2086c72fcc34Sopenharmony_ci snd_config_delete(temp_n2); 2087c72fcc34Sopenharmony_ci snd_config_delete(_obj_type); 2088c72fcc34Sopenharmony_ci if (ret < 0) 2089c72fcc34Sopenharmony_ci return ret; 2090c72fcc34Sopenharmony_ci } 2091c72fcc34Sopenharmony_ci } 2092c72fcc34Sopenharmony_ci 2093c72fcc34Sopenharmony_ci return 0; 2094c72fcc34Sopenharmony_ci} 2095