1d5ac70f0Sopenharmony_ci/* 2d5ac70f0Sopenharmony_ci Copyright(c) 2014-2015 Intel Corporation 3d5ac70f0Sopenharmony_ci All rights reserved. 4d5ac70f0Sopenharmony_ci 5d5ac70f0Sopenharmony_ci This library is free software; you can redistribute it and/or modify 6d5ac70f0Sopenharmony_ci it under the terms of the GNU Lesser General Public License as 7d5ac70f0Sopenharmony_ci published by the Free Software Foundation; either version 2.1 of 8d5ac70f0Sopenharmony_ci the License, or (at your option) any later version. 9d5ac70f0Sopenharmony_ci 10d5ac70f0Sopenharmony_ci This program is distributed in the hope that it will be useful, 11d5ac70f0Sopenharmony_ci but WITHOUT ANY WARRANTY; without even the implied warranty of 12d5ac70f0Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13d5ac70f0Sopenharmony_ci GNU Lesser General Public License for more details. 14d5ac70f0Sopenharmony_ci 15d5ac70f0Sopenharmony_ci Authors: Mengdong Lin <mengdong.lin@intel.com> 16d5ac70f0Sopenharmony_ci Yao Jin <yao.jin@intel.com> 17d5ac70f0Sopenharmony_ci Liam Girdwood <liam.r.girdwood@linux.intel.com> 18d5ac70f0Sopenharmony_ci*/ 19d5ac70f0Sopenharmony_ci 20d5ac70f0Sopenharmony_ci#include "tplg_local.h" 21d5ac70f0Sopenharmony_ci#include <sys/stat.h> 22d5ac70f0Sopenharmony_ci 23d5ac70f0Sopenharmony_ci/* 24d5ac70f0Sopenharmony_ci * Get integer value 25d5ac70f0Sopenharmony_ci */ 26d5ac70f0Sopenharmony_ciint tplg_get_integer(snd_config_t *n, int *val, int base) 27d5ac70f0Sopenharmony_ci{ 28d5ac70f0Sopenharmony_ci const char *str; 29d5ac70f0Sopenharmony_ci long lval; 30d5ac70f0Sopenharmony_ci int err; 31d5ac70f0Sopenharmony_ci 32d5ac70f0Sopenharmony_ci switch (snd_config_get_type(n)) { 33d5ac70f0Sopenharmony_ci case SND_CONFIG_TYPE_INTEGER: 34d5ac70f0Sopenharmony_ci err = snd_config_get_integer(n, &lval); 35d5ac70f0Sopenharmony_ci if (err < 0) 36d5ac70f0Sopenharmony_ci return err; 37d5ac70f0Sopenharmony_ci goto __retval; 38d5ac70f0Sopenharmony_ci case SND_CONFIG_TYPE_STRING: 39d5ac70f0Sopenharmony_ci err = snd_config_get_string(n, &str); 40d5ac70f0Sopenharmony_ci if (err < 0) 41d5ac70f0Sopenharmony_ci return err; 42d5ac70f0Sopenharmony_ci err = safe_strtol_base(str, &lval, base); 43d5ac70f0Sopenharmony_ci if (err < 0) 44d5ac70f0Sopenharmony_ci return err; 45d5ac70f0Sopenharmony_ci goto __retval; 46d5ac70f0Sopenharmony_ci default: 47d5ac70f0Sopenharmony_ci return -EINVAL; 48d5ac70f0Sopenharmony_ci } 49d5ac70f0Sopenharmony_ci __retval: 50d5ac70f0Sopenharmony_ci if (lval < INT_MIN || lval > INT_MAX) 51d5ac70f0Sopenharmony_ci return -ERANGE; 52d5ac70f0Sopenharmony_ci *val = lval; 53d5ac70f0Sopenharmony_ci return 0; 54d5ac70f0Sopenharmony_ci} 55d5ac70f0Sopenharmony_ci 56d5ac70f0Sopenharmony_ci/* 57d5ac70f0Sopenharmony_ci * Get unsigned integer value 58d5ac70f0Sopenharmony_ci */ 59d5ac70f0Sopenharmony_ciint tplg_get_unsigned(snd_config_t *n, unsigned *val, int base) 60d5ac70f0Sopenharmony_ci{ 61d5ac70f0Sopenharmony_ci const char *str; 62d5ac70f0Sopenharmony_ci long lval; 63d5ac70f0Sopenharmony_ci long long llval; 64d5ac70f0Sopenharmony_ci unsigned long uval; 65d5ac70f0Sopenharmony_ci int err; 66d5ac70f0Sopenharmony_ci 67d5ac70f0Sopenharmony_ci switch (snd_config_get_type(n)) { 68d5ac70f0Sopenharmony_ci case SND_CONFIG_TYPE_INTEGER: 69d5ac70f0Sopenharmony_ci err = snd_config_get_integer(n, &lval); 70d5ac70f0Sopenharmony_ci if (err < 0) 71d5ac70f0Sopenharmony_ci return err; 72d5ac70f0Sopenharmony_ci if (lval < 0 && lval >= INT_MIN) 73d5ac70f0Sopenharmony_ci lval = UINT_MAX + lval + 1; 74d5ac70f0Sopenharmony_ci if (lval < 0 || lval > UINT_MAX) 75d5ac70f0Sopenharmony_ci return -ERANGE; 76d5ac70f0Sopenharmony_ci *val = lval; 77d5ac70f0Sopenharmony_ci return err; 78d5ac70f0Sopenharmony_ci case SND_CONFIG_TYPE_INTEGER64: 79d5ac70f0Sopenharmony_ci err = snd_config_get_integer64(n, &llval); 80d5ac70f0Sopenharmony_ci if (err < 0) 81d5ac70f0Sopenharmony_ci return err; 82d5ac70f0Sopenharmony_ci if (llval < 0 && llval >= INT_MIN) 83d5ac70f0Sopenharmony_ci llval = UINT_MAX + llval + 1; 84d5ac70f0Sopenharmony_ci if (llval < 0 || llval > UINT_MAX) 85d5ac70f0Sopenharmony_ci return -ERANGE; 86d5ac70f0Sopenharmony_ci *val = llval; 87d5ac70f0Sopenharmony_ci return err; 88d5ac70f0Sopenharmony_ci case SND_CONFIG_TYPE_STRING: 89d5ac70f0Sopenharmony_ci err = snd_config_get_string(n, &str); 90d5ac70f0Sopenharmony_ci if (err < 0) 91d5ac70f0Sopenharmony_ci return err; 92d5ac70f0Sopenharmony_ci errno = 0; 93d5ac70f0Sopenharmony_ci uval = strtoul(str, NULL, base); 94d5ac70f0Sopenharmony_ci if (errno == ERANGE && uval == ULONG_MAX) 95d5ac70f0Sopenharmony_ci return -ERANGE; 96d5ac70f0Sopenharmony_ci if (errno && uval == 0) 97d5ac70f0Sopenharmony_ci return -EINVAL; 98d5ac70f0Sopenharmony_ci if (uval > UINT_MAX) 99d5ac70f0Sopenharmony_ci return -ERANGE; 100d5ac70f0Sopenharmony_ci *val = uval; 101d5ac70f0Sopenharmony_ci return 0; 102d5ac70f0Sopenharmony_ci default: 103d5ac70f0Sopenharmony_ci return -EINVAL; 104d5ac70f0Sopenharmony_ci } 105d5ac70f0Sopenharmony_ci} 106d5ac70f0Sopenharmony_ci 107d5ac70f0Sopenharmony_ci/* 108d5ac70f0Sopenharmony_ci * Parse compound 109d5ac70f0Sopenharmony_ci */ 110d5ac70f0Sopenharmony_ciint tplg_parse_compound(snd_tplg_t *tplg, snd_config_t *cfg, 111d5ac70f0Sopenharmony_ci int (*fcn)(snd_tplg_t *, snd_config_t *, void *), 112d5ac70f0Sopenharmony_ci void *private) 113d5ac70f0Sopenharmony_ci{ 114d5ac70f0Sopenharmony_ci const char *id; 115d5ac70f0Sopenharmony_ci snd_config_iterator_t i, next; 116d5ac70f0Sopenharmony_ci snd_config_t *n; 117d5ac70f0Sopenharmony_ci int err = -EINVAL; 118d5ac70f0Sopenharmony_ci 119d5ac70f0Sopenharmony_ci if (snd_config_get_id(cfg, &id) < 0) 120d5ac70f0Sopenharmony_ci return -EINVAL; 121d5ac70f0Sopenharmony_ci 122d5ac70f0Sopenharmony_ci if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) { 123d5ac70f0Sopenharmony_ci SNDERR("compound type expected for %s", id); 124d5ac70f0Sopenharmony_ci return -EINVAL; 125d5ac70f0Sopenharmony_ci } 126d5ac70f0Sopenharmony_ci 127d5ac70f0Sopenharmony_ci /* parse compound */ 128d5ac70f0Sopenharmony_ci snd_config_for_each(i, next, cfg) { 129d5ac70f0Sopenharmony_ci n = snd_config_iterator_entry(i); 130d5ac70f0Sopenharmony_ci 131d5ac70f0Sopenharmony_ci if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) { 132d5ac70f0Sopenharmony_ci SNDERR("compound type expected for %s, is %d", 133d5ac70f0Sopenharmony_ci id, snd_config_get_type(cfg)); 134d5ac70f0Sopenharmony_ci return -EINVAL; 135d5ac70f0Sopenharmony_ci } 136d5ac70f0Sopenharmony_ci 137d5ac70f0Sopenharmony_ci err = fcn(tplg, n, private); 138d5ac70f0Sopenharmony_ci if (err < 0) 139d5ac70f0Sopenharmony_ci return err; 140d5ac70f0Sopenharmony_ci } 141d5ac70f0Sopenharmony_ci 142d5ac70f0Sopenharmony_ci return err; 143d5ac70f0Sopenharmony_ci} 144d5ac70f0Sopenharmony_ci 145d5ac70f0Sopenharmony_cistatic int tplg_parse_config(snd_tplg_t *tplg, snd_config_t *cfg) 146d5ac70f0Sopenharmony_ci{ 147d5ac70f0Sopenharmony_ci int (*parser)(snd_tplg_t *tplg, snd_config_t *cfg, void *priv); 148d5ac70f0Sopenharmony_ci snd_config_iterator_t i, next; 149d5ac70f0Sopenharmony_ci snd_config_t *n; 150d5ac70f0Sopenharmony_ci const char *id; 151d5ac70f0Sopenharmony_ci struct tplg_table *p; 152d5ac70f0Sopenharmony_ci unsigned int idx; 153d5ac70f0Sopenharmony_ci int err; 154d5ac70f0Sopenharmony_ci 155d5ac70f0Sopenharmony_ci if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) { 156d5ac70f0Sopenharmony_ci SNDERR("compound type expected at top level"); 157d5ac70f0Sopenharmony_ci return -EINVAL; 158d5ac70f0Sopenharmony_ci } 159d5ac70f0Sopenharmony_ci 160d5ac70f0Sopenharmony_ci /* parse topology config sections */ 161d5ac70f0Sopenharmony_ci snd_config_for_each(i, next, cfg) { 162d5ac70f0Sopenharmony_ci 163d5ac70f0Sopenharmony_ci n = snd_config_iterator_entry(i); 164d5ac70f0Sopenharmony_ci if (snd_config_get_id(n, &id) < 0) 165d5ac70f0Sopenharmony_ci continue; 166d5ac70f0Sopenharmony_ci 167d5ac70f0Sopenharmony_ci parser = NULL; 168d5ac70f0Sopenharmony_ci for (idx = 0; idx < tplg_table_items; idx++) { 169d5ac70f0Sopenharmony_ci p = &tplg_table[idx]; 170d5ac70f0Sopenharmony_ci if (p->id && strcmp(id, p->id) == 0) { 171d5ac70f0Sopenharmony_ci parser = p->parse; 172d5ac70f0Sopenharmony_ci break; 173d5ac70f0Sopenharmony_ci } 174d5ac70f0Sopenharmony_ci if (p->id2 && strcmp(id, p->id2) == 0) { 175d5ac70f0Sopenharmony_ci parser = p->parse; 176d5ac70f0Sopenharmony_ci break; 177d5ac70f0Sopenharmony_ci } 178d5ac70f0Sopenharmony_ci } 179d5ac70f0Sopenharmony_ci 180d5ac70f0Sopenharmony_ci if (parser == NULL) { 181d5ac70f0Sopenharmony_ci SNDERR("unknown section %s", id); 182d5ac70f0Sopenharmony_ci continue; 183d5ac70f0Sopenharmony_ci } 184d5ac70f0Sopenharmony_ci 185d5ac70f0Sopenharmony_ci err = tplg_parse_compound(tplg, n, parser, NULL); 186d5ac70f0Sopenharmony_ci if (err < 0) 187d5ac70f0Sopenharmony_ci return err; 188d5ac70f0Sopenharmony_ci } 189d5ac70f0Sopenharmony_ci return 0; 190d5ac70f0Sopenharmony_ci} 191d5ac70f0Sopenharmony_ci 192d5ac70f0Sopenharmony_cistatic int tplg_load_config(snd_tplg_t *tplg, snd_input_t *in) 193d5ac70f0Sopenharmony_ci{ 194d5ac70f0Sopenharmony_ci snd_config_t *top; 195d5ac70f0Sopenharmony_ci int ret; 196d5ac70f0Sopenharmony_ci 197d5ac70f0Sopenharmony_ci ret = snd_config_top(&top); 198d5ac70f0Sopenharmony_ci if (ret < 0) 199d5ac70f0Sopenharmony_ci return ret; 200d5ac70f0Sopenharmony_ci 201d5ac70f0Sopenharmony_ci ret = snd_config_load(top, in); 202d5ac70f0Sopenharmony_ci if (ret < 0) { 203d5ac70f0Sopenharmony_ci SNDERR("could not load configuration"); 204d5ac70f0Sopenharmony_ci snd_config_delete(top); 205d5ac70f0Sopenharmony_ci return ret; 206d5ac70f0Sopenharmony_ci } 207d5ac70f0Sopenharmony_ci 208d5ac70f0Sopenharmony_ci ret = tplg_parse_config(tplg, top); 209d5ac70f0Sopenharmony_ci snd_config_delete(top); 210d5ac70f0Sopenharmony_ci if (ret < 0) { 211d5ac70f0Sopenharmony_ci SNDERR("failed to parse topology"); 212d5ac70f0Sopenharmony_ci return ret; 213d5ac70f0Sopenharmony_ci } 214d5ac70f0Sopenharmony_ci 215d5ac70f0Sopenharmony_ci return 0; 216d5ac70f0Sopenharmony_ci} 217d5ac70f0Sopenharmony_ci 218d5ac70f0Sopenharmony_cistatic int tplg_build_integ(snd_tplg_t *tplg) 219d5ac70f0Sopenharmony_ci{ 220d5ac70f0Sopenharmony_ci int err; 221d5ac70f0Sopenharmony_ci 222d5ac70f0Sopenharmony_ci err = tplg_build_data(tplg); 223d5ac70f0Sopenharmony_ci if (err < 0) 224d5ac70f0Sopenharmony_ci return err; 225d5ac70f0Sopenharmony_ci 226d5ac70f0Sopenharmony_ci err = tplg_build_manifest_data(tplg); 227d5ac70f0Sopenharmony_ci if (err < 0) 228d5ac70f0Sopenharmony_ci return err; 229d5ac70f0Sopenharmony_ci 230d5ac70f0Sopenharmony_ci err = tplg_build_controls(tplg); 231d5ac70f0Sopenharmony_ci if (err < 0) 232d5ac70f0Sopenharmony_ci return err; 233d5ac70f0Sopenharmony_ci 234d5ac70f0Sopenharmony_ci err = tplg_build_widgets(tplg); 235d5ac70f0Sopenharmony_ci if (err < 0) 236d5ac70f0Sopenharmony_ci return err; 237d5ac70f0Sopenharmony_ci 238d5ac70f0Sopenharmony_ci err = tplg_build_pcms(tplg, SND_TPLG_TYPE_PCM); 239d5ac70f0Sopenharmony_ci if (err < 0) 240d5ac70f0Sopenharmony_ci return err; 241d5ac70f0Sopenharmony_ci 242d5ac70f0Sopenharmony_ci err = tplg_build_dais(tplg, SND_TPLG_TYPE_DAI); 243d5ac70f0Sopenharmony_ci if (err < 0) 244d5ac70f0Sopenharmony_ci return err; 245d5ac70f0Sopenharmony_ci 246d5ac70f0Sopenharmony_ci err = tplg_build_links(tplg, SND_TPLG_TYPE_BE); 247d5ac70f0Sopenharmony_ci if (err < 0) 248d5ac70f0Sopenharmony_ci return err; 249d5ac70f0Sopenharmony_ci 250d5ac70f0Sopenharmony_ci err = tplg_build_links(tplg, SND_TPLG_TYPE_CC); 251d5ac70f0Sopenharmony_ci if (err < 0) 252d5ac70f0Sopenharmony_ci return err; 253d5ac70f0Sopenharmony_ci 254d5ac70f0Sopenharmony_ci err = tplg_build_routes(tplg); 255d5ac70f0Sopenharmony_ci if (err < 0) 256d5ac70f0Sopenharmony_ci return err; 257d5ac70f0Sopenharmony_ci 258d5ac70f0Sopenharmony_ci return err; 259d5ac70f0Sopenharmony_ci} 260d5ac70f0Sopenharmony_ci 261d5ac70f0Sopenharmony_ciint snd_tplg_load(snd_tplg_t *tplg, const char *buf, size_t size) 262d5ac70f0Sopenharmony_ci{ 263d5ac70f0Sopenharmony_ci snd_input_t *in; 264d5ac70f0Sopenharmony_ci int err; 265d5ac70f0Sopenharmony_ci 266d5ac70f0Sopenharmony_ci err = snd_input_buffer_open(&in, buf, size); 267d5ac70f0Sopenharmony_ci if (err < 0) { 268d5ac70f0Sopenharmony_ci SNDERR("could not create input buffer"); 269d5ac70f0Sopenharmony_ci return err; 270d5ac70f0Sopenharmony_ci } 271d5ac70f0Sopenharmony_ci 272d5ac70f0Sopenharmony_ci err = tplg_load_config(tplg, in); 273d5ac70f0Sopenharmony_ci snd_input_close(in); 274d5ac70f0Sopenharmony_ci return err; 275d5ac70f0Sopenharmony_ci} 276d5ac70f0Sopenharmony_ci 277d5ac70f0Sopenharmony_cistatic int tplg_build(snd_tplg_t *tplg) 278d5ac70f0Sopenharmony_ci{ 279d5ac70f0Sopenharmony_ci int err; 280d5ac70f0Sopenharmony_ci 281d5ac70f0Sopenharmony_ci err = tplg_build_integ(tplg); 282d5ac70f0Sopenharmony_ci if (err < 0) { 283d5ac70f0Sopenharmony_ci SNDERR("failed to check topology integrity"); 284d5ac70f0Sopenharmony_ci return err; 285d5ac70f0Sopenharmony_ci } 286d5ac70f0Sopenharmony_ci 287d5ac70f0Sopenharmony_ci err = tplg_write_data(tplg); 288d5ac70f0Sopenharmony_ci if (err < 0) { 289d5ac70f0Sopenharmony_ci SNDERR("failed to write data %d", err); 290d5ac70f0Sopenharmony_ci return err; 291d5ac70f0Sopenharmony_ci } 292d5ac70f0Sopenharmony_ci return 0; 293d5ac70f0Sopenharmony_ci} 294d5ac70f0Sopenharmony_ci 295d5ac70f0Sopenharmony_ciint snd_tplg_build_file(snd_tplg_t *tplg, 296d5ac70f0Sopenharmony_ci const char *infile, 297d5ac70f0Sopenharmony_ci const char *outfile) 298d5ac70f0Sopenharmony_ci{ 299d5ac70f0Sopenharmony_ci FILE *fp; 300d5ac70f0Sopenharmony_ci snd_input_t *in; 301d5ac70f0Sopenharmony_ci int err; 302d5ac70f0Sopenharmony_ci 303d5ac70f0Sopenharmony_ci fp = fopen(infile, "r"); 304d5ac70f0Sopenharmony_ci if (fp == NULL) { 305d5ac70f0Sopenharmony_ci SNDERR("could not open configuration file %s", infile); 306d5ac70f0Sopenharmony_ci return -errno; 307d5ac70f0Sopenharmony_ci } 308d5ac70f0Sopenharmony_ci 309d5ac70f0Sopenharmony_ci err = snd_input_stdio_attach(&in, fp, 1); 310d5ac70f0Sopenharmony_ci if (err < 0) { 311d5ac70f0Sopenharmony_ci fclose(fp); 312d5ac70f0Sopenharmony_ci SNDERR("could not attach stdio %s", infile); 313d5ac70f0Sopenharmony_ci return err; 314d5ac70f0Sopenharmony_ci } 315d5ac70f0Sopenharmony_ci 316d5ac70f0Sopenharmony_ci err = tplg_load_config(tplg, in); 317d5ac70f0Sopenharmony_ci snd_input_close(in); 318d5ac70f0Sopenharmony_ci if (err < 0) 319d5ac70f0Sopenharmony_ci return err; 320d5ac70f0Sopenharmony_ci 321d5ac70f0Sopenharmony_ci return snd_tplg_build(tplg, outfile); 322d5ac70f0Sopenharmony_ci} 323d5ac70f0Sopenharmony_ci 324d5ac70f0Sopenharmony_ciint snd_tplg_add_object(snd_tplg_t *tplg, snd_tplg_obj_template_t *t) 325d5ac70f0Sopenharmony_ci{ 326d5ac70f0Sopenharmony_ci switch (t->type) { 327d5ac70f0Sopenharmony_ci case SND_TPLG_TYPE_MIXER: 328d5ac70f0Sopenharmony_ci return tplg_add_mixer_object(tplg, t); 329d5ac70f0Sopenharmony_ci case SND_TPLG_TYPE_ENUM: 330d5ac70f0Sopenharmony_ci return tplg_add_enum_object(tplg, t); 331d5ac70f0Sopenharmony_ci case SND_TPLG_TYPE_BYTES: 332d5ac70f0Sopenharmony_ci return tplg_add_bytes_object(tplg, t); 333d5ac70f0Sopenharmony_ci case SND_TPLG_TYPE_DAPM_WIDGET: 334d5ac70f0Sopenharmony_ci return tplg_add_widget_object(tplg, t); 335d5ac70f0Sopenharmony_ci case SND_TPLG_TYPE_DAPM_GRAPH: 336d5ac70f0Sopenharmony_ci return tplg_add_graph_object(tplg, t); 337d5ac70f0Sopenharmony_ci case SND_TPLG_TYPE_PCM: 338d5ac70f0Sopenharmony_ci return tplg_add_pcm_object(tplg, t); 339d5ac70f0Sopenharmony_ci case SND_TPLG_TYPE_DAI: 340d5ac70f0Sopenharmony_ci return tplg_add_dai_object(tplg, t); 341d5ac70f0Sopenharmony_ci case SND_TPLG_TYPE_LINK: 342d5ac70f0Sopenharmony_ci case SND_TPLG_TYPE_BE: 343d5ac70f0Sopenharmony_ci case SND_TPLG_TYPE_CC: 344d5ac70f0Sopenharmony_ci return tplg_add_link_object(tplg, t); 345d5ac70f0Sopenharmony_ci default: 346d5ac70f0Sopenharmony_ci SNDERR("invalid object type %d", t->type); 347d5ac70f0Sopenharmony_ci return -EINVAL; 348d5ac70f0Sopenharmony_ci }; 349d5ac70f0Sopenharmony_ci} 350d5ac70f0Sopenharmony_ci 351d5ac70f0Sopenharmony_ciint snd_tplg_build(snd_tplg_t *tplg, const char *outfile) 352d5ac70f0Sopenharmony_ci{ 353d5ac70f0Sopenharmony_ci int fd, err; 354d5ac70f0Sopenharmony_ci ssize_t r; 355d5ac70f0Sopenharmony_ci 356d5ac70f0Sopenharmony_ci err = tplg_build(tplg); 357d5ac70f0Sopenharmony_ci if (err < 0) 358d5ac70f0Sopenharmony_ci return err; 359d5ac70f0Sopenharmony_ci 360d5ac70f0Sopenharmony_ci fd = open(outfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); 361d5ac70f0Sopenharmony_ci if (fd < 0) { 362d5ac70f0Sopenharmony_ci SNDERR("failed to open %s err %d", outfile, -errno); 363d5ac70f0Sopenharmony_ci return -errno; 364d5ac70f0Sopenharmony_ci } 365d5ac70f0Sopenharmony_ci r = write(fd, tplg->bin, tplg->bin_size); 366d5ac70f0Sopenharmony_ci close(fd); 367d5ac70f0Sopenharmony_ci if (r < 0) { 368d5ac70f0Sopenharmony_ci err = -errno; 369d5ac70f0Sopenharmony_ci SNDERR("write error: %s", strerror(errno)); 370d5ac70f0Sopenharmony_ci return err; 371d5ac70f0Sopenharmony_ci } 372d5ac70f0Sopenharmony_ci if ((size_t)r != tplg->bin_size) { 373d5ac70f0Sopenharmony_ci SNDERR("partial write (%zd != %zd)", r, tplg->bin_size); 374d5ac70f0Sopenharmony_ci return -EIO; 375d5ac70f0Sopenharmony_ci } 376d5ac70f0Sopenharmony_ci return 0; 377d5ac70f0Sopenharmony_ci} 378d5ac70f0Sopenharmony_ci 379d5ac70f0Sopenharmony_ciint snd_tplg_build_bin(snd_tplg_t *tplg, 380d5ac70f0Sopenharmony_ci void **bin, size_t *size) 381d5ac70f0Sopenharmony_ci{ 382d5ac70f0Sopenharmony_ci int err; 383d5ac70f0Sopenharmony_ci 384d5ac70f0Sopenharmony_ci err = tplg_build(tplg); 385d5ac70f0Sopenharmony_ci if (err < 0) 386d5ac70f0Sopenharmony_ci return err; 387d5ac70f0Sopenharmony_ci 388d5ac70f0Sopenharmony_ci *bin = tplg->bin; 389d5ac70f0Sopenharmony_ci *size = tplg->bin_size; 390d5ac70f0Sopenharmony_ci tplg->bin = NULL; 391d5ac70f0Sopenharmony_ci tplg->bin_size = tplg->bin_pos = 0; 392d5ac70f0Sopenharmony_ci return 0; 393d5ac70f0Sopenharmony_ci} 394d5ac70f0Sopenharmony_ci 395d5ac70f0Sopenharmony_ciint snd_tplg_set_manifest_data(snd_tplg_t *tplg, const void *data, int len) 396d5ac70f0Sopenharmony_ci{ 397d5ac70f0Sopenharmony_ci struct tplg_elem *elem; 398d5ac70f0Sopenharmony_ci 399d5ac70f0Sopenharmony_ci elem = tplg_elem_type_lookup(tplg, SND_TPLG_TYPE_MANIFEST); 400d5ac70f0Sopenharmony_ci if (elem == NULL) { 401d5ac70f0Sopenharmony_ci elem = tplg_elem_new_common(tplg, NULL, "manifest", 402d5ac70f0Sopenharmony_ci SND_TPLG_TYPE_MANIFEST); 403d5ac70f0Sopenharmony_ci if (!elem) 404d5ac70f0Sopenharmony_ci return -ENOMEM; 405d5ac70f0Sopenharmony_ci tplg->manifest.size = elem->size; 406d5ac70f0Sopenharmony_ci } 407d5ac70f0Sopenharmony_ci 408d5ac70f0Sopenharmony_ci if (len <= 0) 409d5ac70f0Sopenharmony_ci return 0; 410d5ac70f0Sopenharmony_ci 411d5ac70f0Sopenharmony_ci return tplg_add_data_bytes(tplg, elem, NULL, data, len); 412d5ac70f0Sopenharmony_ci} 413d5ac70f0Sopenharmony_ci 414d5ac70f0Sopenharmony_ciint snd_tplg_set_version(snd_tplg_t *tplg, unsigned int version) 415d5ac70f0Sopenharmony_ci{ 416d5ac70f0Sopenharmony_ci tplg->version = version; 417d5ac70f0Sopenharmony_ci 418d5ac70f0Sopenharmony_ci return 0; 419d5ac70f0Sopenharmony_ci} 420d5ac70f0Sopenharmony_ci 421d5ac70f0Sopenharmony_civoid snd_tplg_verbose(snd_tplg_t *tplg, int verbose) 422d5ac70f0Sopenharmony_ci{ 423d5ac70f0Sopenharmony_ci tplg->verbose = verbose; 424d5ac70f0Sopenharmony_ci} 425d5ac70f0Sopenharmony_ci 426d5ac70f0Sopenharmony_cistatic bool is_little_endian(void) 427d5ac70f0Sopenharmony_ci{ 428d5ac70f0Sopenharmony_ci#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ && __SIZEOF_INT__ == 4 429d5ac70f0Sopenharmony_ci return true; 430d5ac70f0Sopenharmony_ci#endif 431d5ac70f0Sopenharmony_ci return false; 432d5ac70f0Sopenharmony_ci} 433d5ac70f0Sopenharmony_ci 434d5ac70f0Sopenharmony_cisnd_tplg_t *snd_tplg_create(int flags) 435d5ac70f0Sopenharmony_ci{ 436d5ac70f0Sopenharmony_ci snd_tplg_t *tplg; 437d5ac70f0Sopenharmony_ci 438d5ac70f0Sopenharmony_ci if (!is_little_endian()) { 439d5ac70f0Sopenharmony_ci SNDERR("cannot support big-endian machines"); 440d5ac70f0Sopenharmony_ci return NULL; 441d5ac70f0Sopenharmony_ci } 442d5ac70f0Sopenharmony_ci 443d5ac70f0Sopenharmony_ci tplg = calloc(1, sizeof(snd_tplg_t)); 444d5ac70f0Sopenharmony_ci if (!tplg) 445d5ac70f0Sopenharmony_ci return NULL; 446d5ac70f0Sopenharmony_ci 447d5ac70f0Sopenharmony_ci tplg->verbose = !!(flags & SND_TPLG_CREATE_VERBOSE); 448d5ac70f0Sopenharmony_ci tplg->dapm_sort = (flags & SND_TPLG_CREATE_DAPM_NOSORT) == 0; 449d5ac70f0Sopenharmony_ci 450d5ac70f0Sopenharmony_ci tplg->manifest.size = sizeof(struct snd_soc_tplg_manifest); 451d5ac70f0Sopenharmony_ci 452d5ac70f0Sopenharmony_ci INIT_LIST_HEAD(&tplg->tlv_list); 453d5ac70f0Sopenharmony_ci INIT_LIST_HEAD(&tplg->widget_list); 454d5ac70f0Sopenharmony_ci INIT_LIST_HEAD(&tplg->pcm_list); 455d5ac70f0Sopenharmony_ci INIT_LIST_HEAD(&tplg->dai_list); 456d5ac70f0Sopenharmony_ci INIT_LIST_HEAD(&tplg->be_list); 457d5ac70f0Sopenharmony_ci INIT_LIST_HEAD(&tplg->cc_list); 458d5ac70f0Sopenharmony_ci INIT_LIST_HEAD(&tplg->route_list); 459d5ac70f0Sopenharmony_ci INIT_LIST_HEAD(&tplg->pdata_list); 460d5ac70f0Sopenharmony_ci INIT_LIST_HEAD(&tplg->manifest_list); 461d5ac70f0Sopenharmony_ci INIT_LIST_HEAD(&tplg->text_list); 462d5ac70f0Sopenharmony_ci INIT_LIST_HEAD(&tplg->pcm_config_list); 463d5ac70f0Sopenharmony_ci INIT_LIST_HEAD(&tplg->pcm_caps_list); 464d5ac70f0Sopenharmony_ci INIT_LIST_HEAD(&tplg->mixer_list); 465d5ac70f0Sopenharmony_ci INIT_LIST_HEAD(&tplg->enum_list); 466d5ac70f0Sopenharmony_ci INIT_LIST_HEAD(&tplg->bytes_ext_list); 467d5ac70f0Sopenharmony_ci INIT_LIST_HEAD(&tplg->token_list); 468d5ac70f0Sopenharmony_ci INIT_LIST_HEAD(&tplg->tuple_list); 469d5ac70f0Sopenharmony_ci INIT_LIST_HEAD(&tplg->hw_cfg_list); 470d5ac70f0Sopenharmony_ci 471d5ac70f0Sopenharmony_ci return tplg; 472d5ac70f0Sopenharmony_ci} 473d5ac70f0Sopenharmony_ci 474d5ac70f0Sopenharmony_cisnd_tplg_t *snd_tplg_new(void) 475d5ac70f0Sopenharmony_ci{ 476d5ac70f0Sopenharmony_ci return snd_tplg_create(0); 477d5ac70f0Sopenharmony_ci} 478d5ac70f0Sopenharmony_ci 479d5ac70f0Sopenharmony_civoid snd_tplg_free(snd_tplg_t *tplg) 480d5ac70f0Sopenharmony_ci{ 481d5ac70f0Sopenharmony_ci free(tplg->bin); 482d5ac70f0Sopenharmony_ci free(tplg->manifest_pdata); 483d5ac70f0Sopenharmony_ci 484d5ac70f0Sopenharmony_ci tplg_elem_free_list(&tplg->tlv_list); 485d5ac70f0Sopenharmony_ci tplg_elem_free_list(&tplg->widget_list); 486d5ac70f0Sopenharmony_ci tplg_elem_free_list(&tplg->pcm_list); 487d5ac70f0Sopenharmony_ci tplg_elem_free_list(&tplg->dai_list); 488d5ac70f0Sopenharmony_ci tplg_elem_free_list(&tplg->be_list); 489d5ac70f0Sopenharmony_ci tplg_elem_free_list(&tplg->cc_list); 490d5ac70f0Sopenharmony_ci tplg_elem_free_list(&tplg->route_list); 491d5ac70f0Sopenharmony_ci tplg_elem_free_list(&tplg->pdata_list); 492d5ac70f0Sopenharmony_ci tplg_elem_free_list(&tplg->manifest_list); 493d5ac70f0Sopenharmony_ci tplg_elem_free_list(&tplg->text_list); 494d5ac70f0Sopenharmony_ci tplg_elem_free_list(&tplg->pcm_config_list); 495d5ac70f0Sopenharmony_ci tplg_elem_free_list(&tplg->pcm_caps_list); 496d5ac70f0Sopenharmony_ci tplg_elem_free_list(&tplg->mixer_list); 497d5ac70f0Sopenharmony_ci tplg_elem_free_list(&tplg->enum_list); 498d5ac70f0Sopenharmony_ci tplg_elem_free_list(&tplg->bytes_ext_list); 499d5ac70f0Sopenharmony_ci tplg_elem_free_list(&tplg->token_list); 500d5ac70f0Sopenharmony_ci tplg_elem_free_list(&tplg->tuple_list); 501d5ac70f0Sopenharmony_ci tplg_elem_free_list(&tplg->hw_cfg_list); 502d5ac70f0Sopenharmony_ci 503d5ac70f0Sopenharmony_ci free(tplg); 504d5ac70f0Sopenharmony_ci} 505d5ac70f0Sopenharmony_ci 506d5ac70f0Sopenharmony_ciconst char *snd_tplg_version(void) 507d5ac70f0Sopenharmony_ci{ 508d5ac70f0Sopenharmony_ci return SND_LIB_VERSION_STR; 509d5ac70f0Sopenharmony_ci} 510