1 /*
2 Copyright(c) 2014-2015 Intel Corporation
3 All rights reserved.
4
5 This library is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as
7 published by the Free Software Foundation; either version 2.1 of
8 the License, or (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
14
15 Authors: Mengdong Lin <mengdong.lin@intel.com>
16 Yao Jin <yao.jin@intel.com>
17 Liam Girdwood <liam.r.girdwood@linux.intel.com>
18 */
19
20 #include "tplg_local.h"
21 #include <ctype.h>
22
23 #define UUID_FORMAT "\
24 %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:\
25 %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x"
26
27 /* Get private data buffer of an element */
get_priv_data(struct tplg_elem *elem)28 struct snd_soc_tplg_private *get_priv_data(struct tplg_elem *elem)
29 {
30 struct snd_soc_tplg_private *priv = NULL;
31
32 switch (elem->type) {
33 case SND_TPLG_TYPE_MANIFEST:
34 priv = &elem->manifest->priv;
35 break;
36
37 case SND_TPLG_TYPE_MIXER:
38 priv = &elem->mixer_ctrl->priv;
39 break;
40
41 case SND_TPLG_TYPE_ENUM:
42 priv = &elem->enum_ctrl->priv;
43 break;
44
45 case SND_TPLG_TYPE_BYTES:
46 priv = &elem->bytes_ext->priv;
47 break;
48
49 case SND_TPLG_TYPE_DAPM_WIDGET:
50 priv = &elem->widget->priv;
51 break;
52
53 case SND_TPLG_TYPE_DAI:
54 priv = &elem->dai->priv;
55 break;
56 case SND_TPLG_TYPE_BE:
57 priv = &elem->link->priv;
58 break;
59 case SND_TPLG_TYPE_PCM:
60 priv = &elem->pcm->priv;
61 break;
62 default:
63 SNDERR("'%s': no support for private data for type %d",
64 elem->id, elem->type);
65 }
66
67 return priv;
68 }
69
70 /* Parse references for the element, either a single data section
71 * or a list of data sections.
72 */
tplg_parse_refs(snd_config_t *cfg, struct tplg_elem *elem, unsigned int type)73 int tplg_parse_refs(snd_config_t *cfg, struct tplg_elem *elem,
74 unsigned int type)
75 {
76 snd_config_type_t cfg_type;
77 snd_config_iterator_t i, next;
78 snd_config_t *n;
79 const char *val = NULL;
80 int err, count;
81
82 cfg_type = snd_config_get_type(cfg);
83
84 /* refer to a single data section */
85 if (cfg_type == SND_CONFIG_TYPE_STRING) {
86 if (snd_config_get_string(cfg, &val) < 0)
87 return -EINVAL;
88
89 tplg_dbg("\tref data: %s", val);
90 err = tplg_ref_add(elem, type, val);
91 if (err < 0)
92 return err;
93 return 1;
94 }
95
96 if (cfg_type != SND_CONFIG_TYPE_COMPOUND) {
97 SNDERR("compound type expected for %s", elem->id);
98 return -EINVAL;
99 }
100
101 /* refer to a list of data sections */
102 count = 0;
103 snd_config_for_each(i, next, cfg) {
104 const char *val;
105
106 n = snd_config_iterator_entry(i);
107 if (snd_config_get_string(n, &val) < 0)
108 continue;
109
110 tplg_dbg("\tref data: %s", val);
111 err = tplg_ref_add(elem, type, val);
112 if (err < 0)
113 return err;
114 count++;
115 }
116
117 return count;
118 }
119
120 /* save references */
tplg_save_refs(snd_tplg_t *tplg ATTRIBUTE_UNUSED, struct tplg_elem *elem, unsigned int type, const char *id, struct tplg_buf *dst, const char *pfx)121 int tplg_save_refs(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
122 struct tplg_elem *elem, unsigned int type,
123 const char *id, struct tplg_buf *dst,
124 const char *pfx)
125 {
126 struct tplg_ref *ref, *last;
127 struct list_head *pos;
128 int err, count;
129
130 count = 0;
131 last = NULL;
132 list_for_each(pos, &elem->ref_list) {
133 ref = list_entry(pos, struct tplg_ref, list);
134 if (ref->type == type) {
135 last = ref;
136 count++;
137 }
138 }
139
140 if (count == 0)
141 return 0;
142
143 if (count == 1)
144 return tplg_save_printf(dst, pfx, "%s '%s'\n", id, last->id);
145
146 err = tplg_save_printf(dst, pfx, "%s [\n", id);
147 if (err < 0)
148 return err;
149 list_for_each(pos, &elem->ref_list) {
150 ref = list_entry(pos, struct tplg_ref, list);
151 if (ref->type == type) {
152 err = tplg_save_printf(dst, pfx, "\t'%s'\n", ref->id);
153 if (err < 0)
154 return err;
155 }
156 }
157
158 return tplg_save_printf(dst, pfx, "]\n");
159 }
160
161 /* Get Private data from a file. */
tplg_parse_data_file(snd_config_t *cfg, struct tplg_elem *elem)162 static int tplg_parse_data_file(snd_config_t *cfg, struct tplg_elem *elem)
163 {
164 struct snd_soc_tplg_private *priv = NULL;
165 const char *value = NULL;
166 char filename[PATH_MAX];
167 char *env = getenv(ALSA_CONFIG_TPLG_VAR);
168 FILE *fp;
169 size_t size, bytes_read;
170 int ret = 0;
171
172 tplg_dbg("data DataFile: %s", elem->id);
173
174 if (snd_config_get_string(cfg, &value) < 0)
175 return -EINVAL;
176
177 /* prepend alsa config directory to path */
178 if (env)
179 snprintf(filename, sizeof(filename), "%s/%s", env, value);
180 else
181 snprintf(filename, sizeof(filename), "%s/topology/%s",
182 snd_config_topdir(), value);
183
184 fp = fopen(filename, "r");
185 if (fp == NULL) {
186 SNDERR("invalid data file path '%s'", filename);
187 return -errno;
188 }
189
190 fseek(fp, 0L, SEEK_END);
191 size = ftell(fp);
192 fseek(fp, 0L, SEEK_SET);
193 if (size <= 0) {
194 SNDERR("invalid data file size %zu", size);
195 ret = -EINVAL;
196 goto err;
197 }
198 if (size > TPLG_MAX_PRIV_SIZE) {
199 SNDERR("data file too big %zu", size);
200 ret = -EINVAL;
201 goto err;
202 }
203
204 priv = calloc(1, sizeof(*priv) + size);
205 if (!priv) {
206 ret = -ENOMEM;
207 goto err;
208 }
209
210 bytes_read = fread(&priv->data, 1, size, fp);
211 if (bytes_read != size) {
212 ret = -errno;
213 goto err;
214 }
215
216 elem->data = priv;
217 priv->size = size;
218 elem->size = sizeof(*priv) + size;
219
220 if (fclose(fp) == EOF) {
221 SNDERR("Cannot close data file.");
222 return -errno;
223 }
224 return 0;
225
226 err:
227 fclose(fp);
228 if (priv)
229 free(priv);
230 return ret;
231 }
232
dump_priv_data(struct tplg_elem *elem ATTRIBUTE_UNUSED)233 static void dump_priv_data(struct tplg_elem *elem ATTRIBUTE_UNUSED)
234 {
235 #ifdef TPLG_DEBUG
236 struct snd_soc_tplg_private *priv = elem->data;
237 unsigned char *p = (unsigned char *)priv->data;
238 char buf[128], buf2[8];
239 unsigned int i;
240
241 tplg_dbg(" elem size = %d, priv data size = %d",
242 elem->size, priv->size);
243
244 buf[0] = '\0';
245 for (i = 0; i < priv->size; i++) {
246 if (i > 0 && (i % 16) == 0) {
247 tplg_dbg("%s", buf);
248 buf[0] = '\0';
249 }
250
251 snprintf(buf2, sizeof(buf2), " %02x", *p++);
252 strcat(buf, buf2);
253 }
254
255 if (buf[0])
256 tplg_dbg("%s", buf);
257 #endif
258 }
259
check_nibble(unsigned char c)260 static inline int check_nibble(unsigned char c)
261 {
262 return (c >= '0' && c <= '9') ||
263 (c >= 'a' && c <= 'f') ||
264 (c >= 'A' && c <= 'F');
265 }
266
267 /* get number of hex value elements in CSV list */
get_hex_num(const char *str)268 static int get_hex_num(const char *str)
269 {
270 int delims, values, len = strlen(str);
271 const char *s, *end = str + len;
272
273 /* check "aa:bb:00" syntax */
274 s = str;
275 delims = values = 0;
276 while (s < end) {
277 /* skip white space */
278 if (isspace(*s)) {
279 s++;
280 continue;
281 }
282 /* find delimeters */
283 if (*s == ':') {
284 delims++;
285 s++;
286 continue;
287 }
288 /* check 00 hexadecimal value */
289 if (s + 1 <= end) {
290 if (check_nibble(s[0]) && check_nibble(s[1])) {
291 values++;
292 } else {
293 goto format2;
294 }
295 s++;
296 }
297 s++;
298 }
299 goto end;
300
301 format2:
302 /* we expect "0x0, 0x0, 0x0" */
303 s = str;
304 delims = values = 0;
305 while (s < end) {
306
307 /* skip white space */
308 if (isspace(*s)) {
309 s++;
310 continue;
311 }
312
313 /* find delimeters */
314 if (*s == ',') {
315 delims++;
316 s++;
317 continue;
318 }
319
320 /* find 0x[0-9] values */
321 if (*s == '0' && s + 2 <= end) {
322 if (s[1] == 'x' && check_nibble(s[2])) {
323 if (check_nibble(s[3]))
324 s++;
325 values++;
326 s += 2;
327 }
328 }
329
330 s++;
331 }
332
333 end:
334 /* there should always be one less comma than value */
335 if (values - 1 != delims)
336 return -EINVAL;
337
338 return values;
339 }
340
341 /* get uuid from a string made by 16 characters separated by commas */
get_uuid(const char *str, unsigned char *uuid_le)342 static int get_uuid(const char *str, unsigned char *uuid_le)
343 {
344 unsigned long int val;
345 char *tmp, *s = NULL;
346 int values = 0, ret = 0;
347
348 tmp = strdup(str);
349 if (tmp == NULL)
350 return -ENOMEM;
351
352 if (strchr(tmp, ':') == NULL)
353 goto data2;
354
355 s = strtok(tmp, ":");
356 while (s != NULL) {
357 errno = 0;
358 val = strtoul(s, NULL, 16);
359 if ((errno == ERANGE && val == ULONG_MAX)
360 || (errno != 0 && val == 0)
361 || (val > UCHAR_MAX)) {
362 SNDERR("invalid value for uuid");
363 ret = -EINVAL;
364 goto out;
365 }
366
367 *(uuid_le + values) = (unsigned char)val;
368
369 values++;
370 if (values >= 16)
371 break;
372
373 s = strtok(NULL, ":");
374 }
375 goto out;
376
377 data2:
378 s = strtok(tmp, ",");
379
380 while (s != NULL) {
381 errno = 0;
382 val = strtoul(s, NULL, 0);
383 if ((errno == ERANGE && val == ULONG_MAX)
384 || (errno != 0 && val == 0)
385 || (val > UCHAR_MAX)) {
386 SNDERR("invalid value for uuid");
387 ret = -EINVAL;
388 goto out;
389 }
390
391 *(uuid_le + values) = (unsigned char)val;
392
393 values++;
394 if (values >= 16)
395 break;
396
397 s = strtok(NULL, ",");
398 }
399
400 if (values < 16) {
401 SNDERR("less than 16 integers for uuid");
402 ret = -EINVAL;
403 }
404
405 out:
406 free(tmp);
407 return ret;
408 }
409
write_hex(char *buf, char *str, int width)410 static int write_hex(char *buf, char *str, int width)
411 {
412 long val;
413 void *p = &val;
414
415 errno = 0;
416 if (safe_strtol_base(str, &val, 16) < 0)
417 return -EINVAL;
418
419 switch (width) {
420 case 1:
421 *(unsigned char *)buf = *(unsigned char *)p;
422 break;
423 case 2:
424 *(unsigned short *)buf = *(unsigned short *)p;
425 break;
426 case 4:
427 *(unsigned int *)buf = *(unsigned int *)p;
428 break;
429 default:
430 return -EINVAL;
431 }
432
433 return 0;
434 }
435
copy_data_hex(char *data, int off, const char *str, int width)436 static int copy_data_hex(char *data, int off, const char *str, int width)
437 {
438 char *tmp, *s = NULL, *p = data;
439 int ret;
440
441 tmp = strdup(str);
442 if (tmp == NULL)
443 return -ENOMEM;
444
445 p += off;
446 s = strtok(tmp, ",:");
447
448 while (s != NULL) {
449 ret = write_hex(p, s, width);
450 if (ret < 0) {
451 free(tmp);
452 return ret;
453 }
454
455 s = strtok(NULL, ",:");
456 p += width;
457 }
458
459 free(tmp);
460 return 0;
461 }
462
tplg_parse_data_hex(snd_config_t *cfg, struct tplg_elem *elem, int width)463 static int tplg_parse_data_hex(snd_config_t *cfg, struct tplg_elem *elem,
464 int width)
465 {
466 struct snd_soc_tplg_private *priv;
467 const char *value = NULL;
468 int size, esize, off, num;
469 int ret;
470
471 tplg_dbg(" data: %s", elem->id);
472
473 if (snd_config_get_string(cfg, &value) < 0)
474 return -EINVAL;
475
476 num = get_hex_num(value);
477 if (num <= 0) {
478 SNDERR("malformed hex variable list %s", value);
479 return -EINVAL;
480 }
481
482 size = num * width;
483 priv = elem->data;
484
485 if (size > TPLG_MAX_PRIV_SIZE) {
486 SNDERR("data too big %d", size);
487 return -EINVAL;
488 }
489
490 if (priv != NULL) {
491 off = priv->size;
492 esize = elem->size + size;
493 priv = realloc(priv, esize);
494 } else {
495 off = 0;
496 esize = sizeof(*priv) + size;
497 priv = calloc(1, esize);
498 }
499
500 if (!priv)
501 return -ENOMEM;
502
503 elem->data = priv;
504 priv->size += size;
505 elem->size = esize;
506
507 ret = copy_data_hex(priv->data, off, value, width);
508
509 dump_priv_data(elem);
510 return ret;
511 }
512
513 /* get the token integer value from its id */
get_token_value(const char *token_id, struct tplg_vendor_tokens *tokens)514 static int get_token_value(const char *token_id,
515 struct tplg_vendor_tokens *tokens)
516 {
517 unsigned int i;
518
519 for (i = 0; i < tokens->num_tokens; i++) {
520 if (strcmp(token_id, tokens->token[i].id) == 0)
521 return tokens->token[i].value;
522 }
523
524 SNDERR("cannot find token id '%s'", token_id);
525 return -1;
526 }
527
528 /* get the vendor tokens referred by the vendor tuples */
get_tokens(snd_tplg_t *tplg, struct tplg_elem *elem)529 static struct tplg_elem *get_tokens(snd_tplg_t *tplg, struct tplg_elem *elem)
530 {
531 struct tplg_ref *ref;
532 struct list_head *base, *pos;
533
534 base = &elem->ref_list;
535 list_for_each(pos, base) {
536
537 ref = list_entry(pos, struct tplg_ref, list);
538
539 if (ref->type != SND_TPLG_TYPE_TOKEN)
540 continue;
541
542 if (!ref->elem) {
543 ref->elem = tplg_elem_lookup(&tplg->token_list,
544 ref->id, SND_TPLG_TYPE_TOKEN, elem->index);
545 }
546
547 return ref->elem;
548 }
549
550 return NULL;
551 }
552
553 /* check if a data element has tuples */
has_tuples(struct tplg_elem *elem)554 static bool has_tuples(struct tplg_elem *elem)
555 {
556 struct tplg_ref *ref;
557 struct list_head *base, *pos;
558
559 base = &elem->ref_list;
560 list_for_each(pos, base) {
561
562 ref = list_entry(pos, struct tplg_ref, list);
563 if (ref->type == SND_TPLG_TYPE_TUPLE)
564 return true;
565 }
566
567 return false;
568 }
569
570 /* get size of a tuple element from its type */
tplg_get_tuple_size(int type)571 unsigned int tplg_get_tuple_size(int type)
572 {
573 switch (type) {
574
575 case SND_SOC_TPLG_TUPLE_TYPE_UUID:
576 return sizeof(struct snd_soc_tplg_vendor_uuid_elem);
577
578 case SND_SOC_TPLG_TUPLE_TYPE_STRING:
579 return sizeof(struct snd_soc_tplg_vendor_string_elem);
580
581 default:
582 return sizeof(struct snd_soc_tplg_vendor_value_elem);
583 }
584 }
585
586 /* Add a tuples object to the private buffer of its parent data element */
copy_tuples(struct tplg_elem *elem, struct tplg_vendor_tuples *tuples, struct tplg_vendor_tokens *tokens)587 static int copy_tuples(struct tplg_elem *elem,
588 struct tplg_vendor_tuples *tuples,
589 struct tplg_vendor_tokens *tokens)
590 {
591 struct snd_soc_tplg_private *priv = elem->data, *priv2;
592 struct tplg_tuple_set *tuple_set;
593 struct tplg_tuple *tuple;
594 struct snd_soc_tplg_vendor_array *array;
595 struct snd_soc_tplg_vendor_uuid_elem *uuid;
596 struct snd_soc_tplg_vendor_string_elem *string;
597 struct snd_soc_tplg_vendor_value_elem *value;
598 int set_size, size, off;
599 unsigned int i, j;
600 int token_val;
601
602 size = priv ? priv->size : 0; /* original private data size */
603
604 /* scan each tuples set (one set per type) */
605 for (i = 0; i < tuples->num_sets ; i++) {
606 tuple_set = tuples->set[i];
607 set_size = sizeof(struct snd_soc_tplg_vendor_array)
608 + tplg_get_tuple_size(tuple_set->type)
609 * tuple_set->num_tuples;
610 size += set_size;
611 if (size > TPLG_MAX_PRIV_SIZE) {
612 SNDERR("data too big %d", size);
613 return -EINVAL;
614 }
615
616 if (priv != NULL) {
617 priv2 = realloc(priv, sizeof(*priv) + size);
618 if (priv2 == NULL) {
619 free(priv);
620 priv = NULL;
621 } else {
622 priv = priv2;
623 }
624 } else {
625 priv = calloc(1, sizeof(*priv) + size);
626 }
627 if (!priv)
628 return -ENOMEM;
629
630 off = priv->size;
631 priv->size = size; /* update private data size */
632 elem->data = priv;
633
634 array = (struct snd_soc_tplg_vendor_array *)(priv->data + off);
635 memset(array, 0, set_size);
636 array->size = set_size;
637 array->type = tuple_set->type;
638 array->num_elems = tuple_set->num_tuples;
639
640 /* fill the private data buffer */
641 for (j = 0; j < tuple_set->num_tuples; j++) {
642 tuple = &tuple_set->tuple[j];
643 token_val = get_token_value(tuple->token, tokens);
644 if (token_val < 0)
645 return -EINVAL;
646
647 switch (tuple_set->type) {
648 case SND_SOC_TPLG_TUPLE_TYPE_UUID:
649 uuid = &array->uuid[j];
650 uuid->token = token_val;
651 memcpy(uuid->uuid, tuple->uuid, 16);
652 break;
653
654 case SND_SOC_TPLG_TUPLE_TYPE_STRING:
655 string = &array->string[j];
656 string->token = token_val;
657 snd_strlcpy(string->string, tuple->string,
658 SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
659 break;
660
661 default:
662 value = &array->value[j];
663 value->token = token_val;
664 value->value = tuple->value;
665 break;
666 }
667 }
668 }
669
670 return 0;
671 }
672
673 /* build a data element from its tuples */
build_tuples(snd_tplg_t *tplg, struct tplg_elem *elem)674 static int build_tuples(snd_tplg_t *tplg, struct tplg_elem *elem)
675 {
676 struct tplg_ref *ref;
677 struct list_head *base, *pos;
678 struct tplg_elem *tuples, *tokens;
679 int err;
680
681 base = &elem->ref_list;
682 list_for_each(pos, base) {
683
684 ref = list_entry(pos, struct tplg_ref, list);
685
686 if (ref->type != SND_TPLG_TYPE_TUPLE)
687 continue;
688
689 tplg_dbg("tuples '%s' used by data '%s'", ref->id, elem->id);
690
691 if (!ref->elem)
692 ref->elem = tplg_elem_lookup(&tplg->tuple_list,
693 ref->id, SND_TPLG_TYPE_TUPLE, elem->index);
694 tuples = ref->elem;
695 if (!tuples) {
696 SNDERR("cannot find tuples %s", ref->id);
697 return -EINVAL;
698 }
699
700 tokens = get_tokens(tplg, tuples);
701 if (!tokens) {
702 SNDERR("cannot find token for %s", ref->id);
703 return -EINVAL;
704 }
705
706 /* a data object can have multiple tuples objects */
707 err = copy_tuples(elem, tuples->tuples, tokens->tokens);
708 if (err < 0)
709 return err;
710 }
711
712 return 0;
713 }
714
715 #ifndef DOC_HIDDEN
716 struct tuple_type {
717 unsigned int type;
718 const char *name;
719 unsigned int size;
720 };
721 #endif /* DOC_HIDDEN */
722
723 static struct tuple_type tuple_types[] = {
724 {
725 .type = SND_SOC_TPLG_TUPLE_TYPE_UUID,
726 .name = "uuid",
727 .size = 4,
728 },
729 {
730 .type = SND_SOC_TPLG_TUPLE_TYPE_STRING,
731 .name = "string",
732 .size = 6,
733 },
734 {
735 .type = SND_SOC_TPLG_TUPLE_TYPE_BOOL,
736 .name = "bool",
737 .size = 4,
738 },
739 {
740 .type = SND_SOC_TPLG_TUPLE_TYPE_BYTE,
741 .name = "byte",
742 .size = 4,
743 },
744 {
745 .type = SND_SOC_TPLG_TUPLE_TYPE_SHORT,
746 .name = "short",
747 .size = 5,
748 },
749 {
750 .type = SND_SOC_TPLG_TUPLE_TYPE_WORD,
751 .name = "word",
752 .size = 4
753 },
754 };
755
get_tuple_type(const char *name)756 static int get_tuple_type(const char *name)
757 {
758 struct tuple_type *t;
759 unsigned int i;
760
761 /* skip initial index for sorting */
762 while ((*name >= '0' && *name <= '9') || *name == '_')
763 name++;
764 for (i = 0; i < ARRAY_SIZE(tuple_types); i++) {
765 t = &tuple_types[i];
766 if (strncasecmp(t->name, name, t->size) == 0)
767 return t->type;
768 }
769 return -EINVAL;
770 }
771
get_tuple_type_name(unsigned int type)772 static const char *get_tuple_type_name(unsigned int type)
773 {
774 unsigned int i;
775
776 for (i = 0; i < ARRAY_SIZE(tuple_types); i++)
777 if (tuple_types[i].type == type)
778 return tuple_types[i].name;
779 return NULL;
780 }
781
parse_tuple_set(snd_config_t *cfg, struct tplg_tuple_set **s)782 static int parse_tuple_set(snd_config_t *cfg,
783 struct tplg_tuple_set **s)
784 {
785 snd_config_iterator_t i, next;
786 snd_config_t *n;
787 const char *id, *value;
788 struct tplg_tuple_set *set;
789 unsigned int num_tuples = 0;
790 struct tplg_tuple *tuple;
791 unsigned int tuple_val;
792 int type, ival;
793
794 snd_config_get_id(cfg, &id);
795
796 type = get_tuple_type(id);
797 if (type < 0) {
798 SNDERR("invalid tuple type '%s'", id);
799 return type;
800 }
801
802 snd_config_for_each(i, next, cfg)
803 num_tuples++;
804 if (!num_tuples)
805 return 0;
806
807 tplg_dbg("\t %d %s tuples:", num_tuples, id);
808 set = calloc(1, sizeof(*set) + num_tuples * sizeof(struct tplg_tuple));
809 if (!set)
810 return -ENOMEM;
811
812 set->type = type;
813
814 snd_config_for_each(i, next, cfg) {
815
816 n = snd_config_iterator_entry(i);
817
818 /* get id */
819 if (snd_config_get_id(n, &id) < 0)
820 continue;
821
822 tuple = &set->tuple[set->num_tuples];
823 snd_strlcpy(tuple->token, id,
824 SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
825
826 switch (type) {
827 case SND_SOC_TPLG_TUPLE_TYPE_UUID:
828 if (snd_config_get_string(n, &value) < 0)
829 continue;
830 if (get_uuid(value, tuple->uuid) < 0)
831 goto err;
832 break;
833
834 case SND_SOC_TPLG_TUPLE_TYPE_STRING:
835 if (snd_config_get_string(n, &value) < 0)
836 continue;
837 snd_strlcpy(tuple->string, value,
838 SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
839 tplg_dbg("\t\t%s = %s", tuple->token, tuple->string);
840 break;
841
842 case SND_SOC_TPLG_TUPLE_TYPE_BOOL:
843 ival = snd_config_get_bool(n);
844 if (ival < 0)
845 continue;
846 tuple->value = ival;
847 tplg_dbg("\t\t%s = %d", tuple->token, tuple->value);
848 break;
849
850 case SND_SOC_TPLG_TUPLE_TYPE_BYTE:
851 case SND_SOC_TPLG_TUPLE_TYPE_SHORT:
852 case SND_SOC_TPLG_TUPLE_TYPE_WORD:
853 ival = tplg_get_unsigned(n, &tuple_val, 0);
854 if (ival < 0) {
855 SNDERR("tuple %s: %s", id, snd_strerror(ival));
856 goto err;
857 }
858
859 if (/* (type == SND_SOC_TPLG_TUPLE_TYPE_WORD
860 && tuple_val > UINT_MAX) || */
861 (type == SND_SOC_TPLG_TUPLE_TYPE_SHORT
862 && tuple_val > USHRT_MAX) ||
863 (type == SND_SOC_TPLG_TUPLE_TYPE_BYTE
864 && tuple_val > UCHAR_MAX)) {
865 SNDERR("tuple %s: invalid value", id);
866 goto err;
867 }
868
869 tuple->value = tuple_val;
870 tplg_dbg("\t\t%s = 0x%x", tuple->token, tuple->value);
871 break;
872
873 default:
874 break;
875 }
876
877 set->num_tuples++;
878 }
879
880 *s = set;
881 return 0;
882
883 err:
884 free(set);
885 return -EINVAL;
886 }
887
888 /* save tuple set */
tplg_save_tuple_set(struct tplg_vendor_tuples *tuples, unsigned int set_index, struct tplg_buf *dst, const char *pfx)889 static int tplg_save_tuple_set(struct tplg_vendor_tuples *tuples,
890 unsigned int set_index,
891 struct tplg_buf *dst, const char *pfx)
892 {
893 struct tplg_tuple_set *set;
894 struct tplg_tuple *tuple;
895 const char *s, *fmt;
896 char buf[32];
897 unsigned int i;
898 int err;
899
900 set = tuples->set[set_index];
901 if (set->num_tuples == 0)
902 return 0;
903 s = get_tuple_type_name(set->type);
904 if (s == NULL)
905 return -EINVAL;
906 if (tuples->num_sets < 10)
907 fmt = "%u_";
908 else if (tuples->num_sets < 100)
909 fmt = "%02u_";
910 else if (tuples->num_sets < 1000)
911 fmt = "%03u_";
912 else
913 return -EINVAL;
914 if (set->num_tuples > 1) {
915 snprintf(buf, sizeof(buf), "tuples.%s%%s {\n", fmt);
916 err = tplg_save_printf(dst, NULL, buf, set_index, s);
917 if (err < 0)
918 return err;
919 }
920 for (i = 0; i < set->num_tuples; i++) {
921 tuple = &set->tuple[i];
922 if (set->num_tuples == 1) {
923 snprintf(buf, sizeof(buf), "tuples.%s%%s.'%%s' ", fmt);
924 err = tplg_save_printf(dst, NULL, buf,
925 set_index, s, tuple->token);
926 } else {
927 err = tplg_save_printf(dst, pfx, "\t'%s' ",
928 tuple->token);
929 }
930 if (err < 0)
931 return err;
932 switch (set->type) {
933 case SND_SOC_TPLG_TUPLE_TYPE_UUID:
934 err = tplg_save_printf(dst, NULL, "'" UUID_FORMAT "'\n",
935 tuple->uuid[0], tuple->uuid[1],
936 tuple->uuid[2], tuple->uuid[3],
937 tuple->uuid[4], tuple->uuid[5],
938 tuple->uuid[6], tuple->uuid[7],
939 tuple->uuid[8], tuple->uuid[9],
940 tuple->uuid[10], tuple->uuid[11],
941 tuple->uuid[12], tuple->uuid[13],
942 tuple->uuid[14], tuple->uuid[15]);
943 break;
944 case SND_SOC_TPLG_TUPLE_TYPE_STRING:
945 err = tplg_save_printf(dst, NULL, "'%s'\n",
946 tuple->string);
947 break;
948 case SND_SOC_TPLG_TUPLE_TYPE_BOOL:
949 case SND_SOC_TPLG_TUPLE_TYPE_BYTE:
950 case SND_SOC_TPLG_TUPLE_TYPE_SHORT:
951 err = tplg_save_printf(dst, NULL, "%u\n", tuple->value);
952 break;
953 case SND_SOC_TPLG_TUPLE_TYPE_WORD:
954 tplg_nice_value_format(buf, sizeof(buf), tuple->value);
955 err = tplg_save_printf(dst, NULL, "%s\n", buf);
956 break;
957 default:
958 return -EINVAL;
959 }
960 if (err < 0)
961 return err;
962 }
963 if (set->num_tuples > 1)
964 return tplg_save_printf(dst, pfx, "}\n");
965 return 0;
966 }
967
parse_tuple_sets(snd_config_t *cfg, struct tplg_vendor_tuples *tuples)968 static int parse_tuple_sets(snd_config_t *cfg,
969 struct tplg_vendor_tuples *tuples)
970 {
971 snd_config_iterator_t i, next;
972 snd_config_t *n;
973 const char *id;
974 unsigned int num_tuple_sets = 0;
975 int err;
976
977 if (snd_config_get_type(cfg) != SND_CONFIG_TYPE_COMPOUND) {
978 if (snd_config_get_id(cfg, &id) >= 0)
979 SNDERR("compound type expected for %s", id);
980 return -EINVAL;
981 }
982
983 snd_config_for_each(i, next, cfg) {
984 num_tuple_sets++;
985 }
986
987 if (!num_tuple_sets)
988 return 0;
989
990 tuples->set = calloc(1, num_tuple_sets * sizeof(void *));
991 if (!tuples->set)
992 return -ENOMEM;
993
994 snd_config_for_each(i, next, cfg) {
995 n = snd_config_iterator_entry(i);
996 if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) {
997 SNDERR("compound type expected for %s, is %d",
998 id, snd_config_get_type(n));
999 return -EINVAL;
1000 }
1001
1002 err = parse_tuple_set(n, &tuples->set[tuples->num_sets]);
1003 if (err < 0)
1004 return err;
1005
1006 /* overlook empty tuple sets */
1007 if (tuples->set[tuples->num_sets])
1008 tuples->num_sets++;
1009 }
1010
1011 return 0;
1012 }
1013
1014 /* save tuple sets */
tplg_save_tuple_sets(snd_tplg_t *tplg ATTRIBUTE_UNUSED, struct tplg_elem *elem, struct tplg_buf *dst, const char *pfx)1015 int tplg_save_tuple_sets(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
1016 struct tplg_elem *elem,
1017 struct tplg_buf *dst, const char *pfx)
1018 {
1019 struct tplg_vendor_tuples *tuples = elem->tuples;
1020 unsigned int i;
1021 int err = 0;
1022
1023 for (i = 0; i < tuples->num_sets; i++) {
1024 err = tplg_save_printf(dst, pfx, "");
1025 if (err < 0)
1026 break;
1027 err = tplg_save_tuple_set(tuples, i, dst, pfx);
1028 if (err < 0)
1029 break;
1030 }
1031 return err;
1032 }
1033
1034 /* Parse vendor tokens
1035 */
tplg_parse_tokens(snd_tplg_t *tplg, snd_config_t *cfg, void *private ATTRIBUTE_UNUSED)1036 int tplg_parse_tokens(snd_tplg_t *tplg, snd_config_t *cfg,
1037 void *private ATTRIBUTE_UNUSED)
1038 {
1039 snd_config_iterator_t i, next;
1040 snd_config_t *n;
1041 const char *id;
1042 struct tplg_elem *elem;
1043 struct tplg_vendor_tokens *tokens;
1044 int num_tokens = 0, value;
1045
1046 elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_TOKEN);
1047 if (!elem)
1048 return -ENOMEM;
1049
1050 snd_config_for_each(i, next, cfg) {
1051 num_tokens++;
1052 }
1053
1054 if (!num_tokens)
1055 return 0;
1056
1057 tplg_dbg(" Vendor tokens: %s, %d tokens", elem->id, num_tokens);
1058
1059 tokens = calloc(1, sizeof(*tokens)
1060 + num_tokens * sizeof(struct tplg_token));
1061 if (!tokens)
1062 return -ENOMEM;
1063 elem->tokens = tokens;
1064
1065 snd_config_for_each(i, next, cfg) {
1066
1067 n = snd_config_iterator_entry(i);
1068 if (snd_config_get_id(n, &id) < 0)
1069 continue;
1070
1071 if (tplg_get_integer(n, &value, 0))
1072 continue;
1073
1074 snd_strlcpy(tokens->token[tokens->num_tokens].id, id,
1075 SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
1076 tokens->token[tokens->num_tokens].value = value;
1077 tplg_dbg("\t\t %s : %d", tokens->token[tokens->num_tokens].id,
1078 tokens->token[tokens->num_tokens].value);
1079 tokens->num_tokens++;
1080 }
1081
1082 return 0;
1083 }
1084
1085 /* save vendor tokens */
tplg_save_tokens(snd_tplg_t *tplg ATTRIBUTE_UNUSED, struct tplg_elem *elem, struct tplg_buf *dst, const char *pfx)1086 int tplg_save_tokens(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
1087 struct tplg_elem *elem,
1088 struct tplg_buf *dst, const char *pfx)
1089 {
1090 struct tplg_vendor_tokens *tokens = elem->tokens;
1091 unsigned int i;
1092 int err;
1093
1094 if (!tokens || tokens->num_tokens == 0)
1095 return 0;
1096
1097 err = tplg_save_printf(dst, NULL, "'%s' {\n", elem->id);
1098 if (err < 0)
1099 return err;
1100 for (i = 0; err >= 0 && i < tokens->num_tokens; i++)
1101 err = tplg_save_printf(dst, pfx, "\t'%s' %u\n",
1102 tokens->token[i].id,
1103 tokens->token[i].value);
1104 err = tplg_save_printf(dst, pfx, "}\n");
1105 if (err < 0)
1106 return err;
1107 return 0;
1108 }
1109
1110 /* Parse vendor tuples.
1111 */
tplg_parse_tuples(snd_tplg_t *tplg, snd_config_t *cfg, void *private ATTRIBUTE_UNUSED)1112 int tplg_parse_tuples(snd_tplg_t *tplg, snd_config_t *cfg,
1113 void *private ATTRIBUTE_UNUSED)
1114 {
1115 snd_config_iterator_t i, next;
1116 snd_config_t *n;
1117 const char *id, *value;
1118 struct tplg_elem *elem;
1119 struct tplg_vendor_tuples *tuples;
1120 int err;
1121
1122 elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_TUPLE);
1123 if (!elem)
1124 return -ENOMEM;
1125
1126 tplg_dbg(" Vendor Tuples: %s", elem->id);
1127
1128 tuples = calloc(1, sizeof(*tuples));
1129 if (!tuples)
1130 return -ENOMEM;
1131 elem->tuples = tuples;
1132
1133 snd_config_for_each(i, next, cfg) {
1134
1135 n = snd_config_iterator_entry(i);
1136 if (snd_config_get_id(n, &id) < 0)
1137 continue;
1138
1139 if (strcmp(id, "tokens") == 0) {
1140 if (snd_config_get_string(n, &value) < 0)
1141 return -EINVAL;
1142 tplg_ref_add(elem, SND_TPLG_TYPE_TOKEN, value);
1143 tplg_dbg("\t refer to vendor tokens: %s", value);
1144 }
1145
1146 if (strcmp(id, "tuples") == 0) {
1147 err = parse_tuple_sets(n, tuples);
1148 if (err < 0)
1149 return err;
1150 }
1151 }
1152
1153 return 0;
1154 }
1155
1156 /* save vendor tuples */
tplg_save_tuples(snd_tplg_t *tplg ATTRIBUTE_UNUSED, struct tplg_elem *elem, struct tplg_buf *dst, const char *pfx)1157 int tplg_save_tuples(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
1158 struct tplg_elem *elem,
1159 struct tplg_buf *dst, const char *pfx)
1160 {
1161 char pfx2[16];
1162 int err;
1163
1164 if (!elem->tuples)
1165 return 0;
1166
1167 err = tplg_save_printf(dst, NULL, "'%s' {\n", elem->id);
1168 snprintf(pfx2, sizeof(pfx2), "%s\t", pfx ?: "");
1169 if (err >= 0)
1170 err = tplg_save_refs(tplg, elem, SND_TPLG_TYPE_TOKEN,
1171 "tokens", dst, pfx2);
1172 if (err >= 0)
1173 err = tplg_save_tuple_sets(tplg, elem, dst, pfx2);
1174 if (err >= 0)
1175 err = tplg_save_printf(dst, pfx, "}\n");
1176 return 0;
1177 }
1178
1179 /* Free handler of tuples */
tplg_free_tuples(void *obj)1180 void tplg_free_tuples(void *obj)
1181 {
1182 struct tplg_vendor_tuples *tuples = (struct tplg_vendor_tuples *)obj;
1183 unsigned int i;
1184
1185 if (!tuples || !tuples->set)
1186 return;
1187
1188 for (i = 0; i < tuples->num_sets; i++)
1189 free(tuples->set[i]);
1190
1191 free(tuples->set);
1192 }
1193
1194 /* Parse manifest's data references
1195 */
tplg_parse_manifest_data(snd_tplg_t *tplg, snd_config_t *cfg, void *private ATTRIBUTE_UNUSED)1196 int tplg_parse_manifest_data(snd_tplg_t *tplg, snd_config_t *cfg,
1197 void *private ATTRIBUTE_UNUSED)
1198 {
1199 struct snd_soc_tplg_manifest *manifest;
1200 struct tplg_elem *elem;
1201 snd_config_iterator_t i, next;
1202 snd_config_t *n;
1203 const char *id;
1204 int err;
1205
1206 if (!list_empty(&tplg->manifest_list)) {
1207 SNDERR("already has manifest data");
1208 return -EINVAL;
1209 }
1210
1211 elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_MANIFEST);
1212 if (!elem)
1213 return -ENOMEM;
1214
1215 manifest = elem->manifest;
1216 manifest->size = elem->size;
1217
1218 tplg_dbg(" Manifest: %s", elem->id);
1219
1220 snd_config_for_each(i, next, cfg) {
1221 n = snd_config_iterator_entry(i);
1222 if (snd_config_get_id(n, &id) < 0)
1223 continue;
1224
1225 /* skip comments */
1226 if (strcmp(id, "comment") == 0)
1227 continue;
1228 if (id[0] == '#')
1229 continue;
1230
1231
1232 if (strcmp(id, "data") == 0) {
1233 err = tplg_parse_refs(n, elem, SND_TPLG_TYPE_DATA);
1234 if (err < 0)
1235 return err;
1236 continue;
1237 }
1238 }
1239
1240 return 0;
1241 }
1242
1243 /* save manifest data */
tplg_save_manifest_data(snd_tplg_t *tplg ATTRIBUTE_UNUSED, struct tplg_elem *elem, struct tplg_buf *dst, const char *pfx)1244 int tplg_save_manifest_data(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
1245 struct tplg_elem *elem, struct tplg_buf *dst,
1246 const char *pfx)
1247 {
1248 struct list_head *pos;
1249 struct tplg_ref *ref;
1250 int err, index, count;
1251
1252 /* for each ref in this manifest elem */
1253 count = 0;
1254 list_for_each(pos, &elem->ref_list) {
1255 ref = list_entry(pos, struct tplg_ref, list);
1256 if (ref->type != SND_TPLG_TYPE_DATA)
1257 continue;
1258 count++;
1259 }
1260 if (count == 0)
1261 return tplg_save_printf(dst, NULL,
1262 "'%s'.comment 'empty'\n", elem->id);
1263 if (count > 1) {
1264 err = tplg_save_printf(dst, NULL, "'%s'.data [\n", elem->id);
1265 if (err < 0)
1266 return err;
1267 }
1268 index = 0;
1269 list_for_each(pos, &elem->ref_list) {
1270 ref = list_entry(pos, struct tplg_ref, list);
1271 if (ref->type != SND_TPLG_TYPE_DATA)
1272 continue;
1273 if (count == 1) {
1274 err = tplg_save_printf(dst, NULL, "'%s'.data.%u '%s'\n",
1275 elem->id, index, ref->id);
1276 } else {
1277 err = tplg_save_printf(dst, pfx, "\t'%s'\n", ref->id);
1278 }
1279 if (err < 0)
1280 return err;
1281 index++;
1282 }
1283 if (count > 1) {
1284 err = tplg_save_printf(dst, pfx, "]\n");
1285 if (err < 0)
1286 return err;
1287 }
1288 return 0;
1289 }
1290
1291 /* merge private data of manifest */
tplg_build_manifest_data(snd_tplg_t *tplg)1292 int tplg_build_manifest_data(snd_tplg_t *tplg)
1293 {
1294 struct list_head *base, *pos;
1295 struct tplg_elem *elem = NULL;
1296 struct tplg_ref *ref;
1297 struct snd_soc_tplg_manifest *manifest;
1298 int err = 0;
1299
1300 base = &tplg->manifest_list;
1301 list_for_each(pos, base) {
1302
1303 elem = list_entry(pos, struct tplg_elem, list);
1304 break;
1305 }
1306
1307 if (!elem) /* no manifest data */
1308 return 0;
1309
1310 base = &elem->ref_list;
1311
1312 /* for each ref in this manifest elem */
1313 list_for_each(pos, base) {
1314
1315 ref = list_entry(pos, struct tplg_ref, list);
1316 if (ref->elem)
1317 continue;
1318
1319 if (ref->type == SND_TPLG_TYPE_DATA) {
1320 err = tplg_copy_data(tplg, elem, ref);
1321 if (err < 0)
1322 return err;
1323 }
1324 }
1325
1326 manifest = elem->manifest;
1327 if (!manifest->priv.size) /* no manifest data */
1328 return 0;
1329
1330 tplg->manifest_pdata = malloc(manifest->priv.size);
1331 if (!tplg->manifest_pdata)
1332 return -ENOMEM;
1333
1334 tplg->manifest.priv.size = manifest->priv.size;
1335 memcpy(tplg->manifest_pdata, manifest->priv.data, manifest->priv.size);
1336 return 0;
1337 }
1338
1339 /* Parse Private data.
1340 *
1341 * Object private data can either be from file or defined as bytes, shorts,
1342 * words, tuples.
1343 */
tplg_parse_data(snd_tplg_t *tplg, snd_config_t *cfg, void *private ATTRIBUTE_UNUSED)1344 int tplg_parse_data(snd_tplg_t *tplg, snd_config_t *cfg,
1345 void *private ATTRIBUTE_UNUSED)
1346 {
1347 snd_config_iterator_t i, next;
1348 snd_config_t *n;
1349 const char *id;
1350 int err = 0, ival;
1351 struct tplg_elem *elem;
1352
1353 elem = tplg_elem_new_common(tplg, cfg, NULL, SND_TPLG_TYPE_DATA);
1354 if (!elem)
1355 return -ENOMEM;
1356
1357 snd_config_for_each(i, next, cfg) {
1358
1359 n = snd_config_iterator_entry(i);
1360 if (snd_config_get_id(n, &id) < 0) {
1361 continue;
1362 }
1363
1364 if (strcmp(id, "file") == 0) {
1365 err = tplg_parse_data_file(n, elem);
1366 if (err < 0) {
1367 SNDERR("failed to parse data file");
1368 return err;
1369 }
1370 continue;
1371 }
1372
1373 if (strcmp(id, "bytes") == 0) {
1374 err = tplg_parse_data_hex(n, elem, 1);
1375 if (err < 0) {
1376 SNDERR("failed to parse data bytes");
1377 return err;
1378 }
1379 continue;
1380 }
1381
1382 if (strcmp(id, "shorts") == 0) {
1383 err = tplg_parse_data_hex(n, elem, 2);
1384 if (err < 0) {
1385 SNDERR("failed to parse data shorts");
1386 return err;
1387 }
1388 continue;
1389 }
1390
1391 if (strcmp(id, "words") == 0) {
1392 err = tplg_parse_data_hex(n, elem, 4);
1393 if (err < 0) {
1394 SNDERR("failed to parse data words");
1395 return err;
1396 }
1397 continue;
1398 }
1399
1400 if (strcmp(id, "tuples") == 0) {
1401 err = tplg_parse_refs(n, elem, SND_TPLG_TYPE_TUPLE);
1402 if (err < 0)
1403 return err;
1404 continue;
1405 }
1406
1407 if (strcmp(id, "type") == 0) {
1408 if (tplg_get_integer(n, &ival, 0))
1409 return -EINVAL;
1410
1411 elem->vendor_type = ival;
1412 tplg_dbg("\t%s: %d", id, elem->index);
1413 continue;
1414 }
1415 }
1416
1417 return err;
1418 }
1419
1420 /* save data element */
tplg_save_data(snd_tplg_t *tplg ATTRIBUTE_UNUSED, struct tplg_elem *elem, struct tplg_buf *dst, const char *pfx)1421 int tplg_save_data(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
1422 struct tplg_elem *elem,
1423 struct tplg_buf *dst, const char *pfx)
1424 {
1425 struct snd_soc_tplg_private *priv = elem->data;
1426 struct list_head *pos;
1427 struct tplg_ref *ref;
1428 char pfx2[16];
1429 unsigned int i, count;
1430 int err;
1431
1432 count = 0;
1433 if (priv && priv->size > 0)
1434 count++;
1435 list_for_each(pos, &elem->ref_list) {
1436 ref = list_entry(pos, struct tplg_ref, list);
1437 if (ref->type == SND_TPLG_TYPE_TUPLE)
1438 count++;
1439 }
1440 if (elem->vendor_type > 0)
1441 count++;
1442
1443 if (count > 1) {
1444 err = tplg_save_printf(dst, NULL, "'%s' {\n", elem->id);
1445 if (err >= 0)
1446 err = tplg_save_printf(dst, NULL, "");
1447 } else {
1448 err = tplg_save_printf(dst, NULL, "'%s'.", elem->id);
1449 }
1450 if (err >= 0 && priv && priv->size > 0) {
1451 if (count > 1) {
1452 err = tplg_save_printf(dst, pfx, "");
1453 if (err < 0)
1454 return err;
1455 }
1456 if (priv->size > 8) {
1457 err = tplg_save_printf(dst, NULL, "bytes\n");
1458 if (err >= 0)
1459 err = tplg_save_printf(dst, pfx, "\t'");
1460 } else {
1461 err = tplg_save_printf(dst, NULL, "bytes '");
1462 }
1463 if (err < 0)
1464 return err;
1465 for (i = 0; i < priv->size; i++) {
1466 if (i > 0 && (i % 8) == 0) {
1467 err = tplg_save_printf(dst, NULL, ":\n");
1468 if (err < 0)
1469 return err;
1470 err = tplg_save_printf(dst, pfx, "\t ");
1471 if (err < 0)
1472 return err;
1473 }
1474 err = tplg_save_printf(dst, NULL, "%s%02x",
1475 (i % 8) == 0 ? "" : ":",
1476 (unsigned char)priv->data[i]);
1477 if (err < 0)
1478 return err;
1479 }
1480 err = tplg_save_printf(dst, NULL, "'\n");
1481 }
1482 snprintf(pfx2, sizeof(pfx2), "%s\t", pfx ?: "");
1483 if (err >= 0)
1484 err = tplg_save_refs(tplg, elem, SND_TPLG_TYPE_TUPLE,
1485 "tuples", dst,
1486 count > 1 ? pfx2 : NULL);
1487 if (err >= 0 && elem->vendor_type > 0)
1488 err = tplg_save_printf(dst, pfx, "type %u",
1489 elem->vendor_type);
1490 if (err >= 0 && count > 1)
1491 err = tplg_save_printf(dst, pfx, "}\n");
1492 return err;
1493 }
1494
1495 /* Find a referenced data element and copy its data to the parent
1496 * element's private data buffer.
1497 * An element can refer to multiple data sections. Data of these sections
1498 * will be merged in the their reference order.
1499 */
tplg_copy_data(snd_tplg_t *tplg, struct tplg_elem *elem, struct tplg_ref *ref)1500 int tplg_copy_data(snd_tplg_t *tplg, struct tplg_elem *elem,
1501 struct tplg_ref *ref)
1502 {
1503 struct tplg_elem *ref_elem;
1504 struct snd_soc_tplg_private *priv, *old_priv;
1505 int priv_data_size, old_priv_data_size;
1506 void *obj;
1507
1508 ref_elem = tplg_elem_lookup(&tplg->pdata_list,
1509 ref->id, SND_TPLG_TYPE_DATA, elem->index);
1510 if (!ref_elem) {
1511 SNDERR("cannot find data '%s' referenced by"
1512 " element '%s'", ref->id, elem->id);
1513 return -EINVAL;
1514 }
1515
1516 tplg_dbg("Data '%s' used by '%s'", ref->id, elem->id);
1517 /* overlook empty private data */
1518 if (!ref_elem->data || !ref_elem->data->size) {
1519 ref->elem = ref_elem;
1520 return 0;
1521 }
1522
1523 old_priv = get_priv_data(elem);
1524 if (!old_priv)
1525 return -EINVAL;
1526 old_priv_data_size = old_priv->size;
1527
1528 priv_data_size = ref_elem->data->size;
1529 obj = realloc(elem->obj,
1530 elem->size + priv_data_size);
1531 if (!obj)
1532 return -ENOMEM;
1533 elem->obj = obj;
1534
1535 priv = get_priv_data(elem);
1536 if (!priv)
1537 return -EINVAL;
1538
1539 /* merge the new data block */
1540 elem->size += priv_data_size;
1541 priv->size = priv_data_size + old_priv_data_size;
1542 ref_elem->compound_elem = 1;
1543 memcpy(priv->data + old_priv_data_size,
1544 ref_elem->data->data, priv_data_size);
1545
1546 ref->elem = ref_elem;
1547 return 0;
1548 }
1549
1550 /* check data objects and build those with tuples */
tplg_build_data(snd_tplg_t *tplg)1551 int tplg_build_data(snd_tplg_t *tplg)
1552 {
1553 struct list_head *base, *pos;
1554 struct tplg_elem *elem;
1555 int err = 0;
1556
1557 base = &tplg->pdata_list;
1558 list_for_each(pos, base) {
1559
1560 elem = list_entry(pos, struct tplg_elem, list);
1561 if (has_tuples(elem)) {
1562 err = build_tuples(tplg, elem);
1563 if (err < 0)
1564 return err;
1565 }
1566 }
1567
1568 return 0;
1569 }
1570
1571 /* decode manifest data */
tplg_decode_manifest_data(snd_tplg_t *tplg, size_t pos, struct snd_soc_tplg_hdr *hdr, void *bin, size_t size)1572 int tplg_decode_manifest_data(snd_tplg_t *tplg,
1573 size_t pos,
1574 struct snd_soc_tplg_hdr *hdr,
1575 void *bin, size_t size)
1576 {
1577 struct snd_soc_tplg_manifest *m = bin;
1578 struct tplg_elem *elem;
1579 size_t off;
1580
1581 if (hdr->index != 0) {
1582 SNDERR("manifest - wrong index %d", hdr->index);
1583 return -EINVAL;
1584 }
1585
1586 if (sizeof(*m) > size) {
1587 SNDERR("manifest - wrong size %zd (minimal %zd)",
1588 size, sizeof(*m));
1589 return -EINVAL;
1590 }
1591
1592 if (m->size != sizeof(*m)) {
1593 SNDERR("manifest - wrong sructure size %d", m->size);
1594 return -EINVAL;
1595 }
1596
1597 off = offsetof(struct snd_soc_tplg_manifest, priv);
1598 if (off + m->priv.size > size) {
1599 SNDERR("manifest - wrong private size %d", m->priv.size);
1600 return -EINVAL;
1601 }
1602
1603 tplg->manifest = *m;
1604
1605 bin += off;
1606 size -= off;
1607 pos += off;
1608
1609 elem = tplg_elem_new_common(tplg, NULL, "manifest",
1610 SND_TPLG_TYPE_MANIFEST);
1611 if (!elem)
1612 return -ENOMEM;
1613
1614 tplg_log(tplg, 'D', pos, "manifest: private size %zd", size);
1615 return tplg_add_data(tplg, elem, bin, size);
1616 }
1617
tplg_add_token(snd_tplg_t *tplg, struct tplg_elem *parent, unsigned int token, char str_ref[SNDRV_CTL_ELEM_ID_NAME_MAXLEN])1618 int tplg_add_token(snd_tplg_t *tplg, struct tplg_elem *parent,
1619 unsigned int token,
1620 char str_ref[SNDRV_CTL_ELEM_ID_NAME_MAXLEN])
1621 {
1622 struct tplg_elem *elem;
1623 struct tplg_token *t;
1624 struct tplg_vendor_tokens *tokens;
1625 unsigned int i;
1626 size_t size;
1627
1628 elem = tplg_elem_lookup(&tplg->token_list, parent->id,
1629 SND_TPLG_TYPE_TOKEN, parent->index);
1630 if (elem == NULL) {
1631 elem = tplg_elem_new_common(tplg, NULL, parent->id,
1632 SND_TPLG_TYPE_TOKEN);
1633 if (!elem)
1634 return -ENOMEM;
1635 }
1636
1637 tokens = elem->tokens;
1638 if (tokens) {
1639 for (i = 0; i < tokens->num_tokens; i++) {
1640 t = &tokens->token[i];
1641 if (t->value == token)
1642 goto found;
1643 }
1644 size = sizeof(*tokens) +
1645 (tokens->num_tokens + 1) * sizeof(struct tplg_token);
1646 tokens = realloc(tokens, size);
1647 } else {
1648 size = sizeof(*tokens) + 1 * sizeof(struct tplg_token);
1649 tokens = calloc(1, size);
1650 }
1651
1652 if (!tokens)
1653 return -ENOMEM;
1654
1655 memset(&tokens->token[tokens->num_tokens], 0, sizeof(struct tplg_token));
1656 elem->tokens = tokens;
1657 t = &tokens->token[tokens->num_tokens];
1658 tokens->num_tokens++;
1659 snprintf(t->id, sizeof(t->id), "token%u", token);
1660 t->value = token;
1661 found:
1662 snd_strlcpy(str_ref, t->id, SNDRV_CTL_ELEM_ID_NAME_MAXLEN);
1663 return 0;
1664 }
1665
tplg_verify_tuple_set(snd_tplg_t *tplg, size_t pos, const void *bin, size_t size)1666 static int tplg_verify_tuple_set(snd_tplg_t *tplg, size_t pos,
1667 const void *bin, size_t size)
1668 {
1669 const struct snd_soc_tplg_vendor_array *va;
1670 unsigned int j;
1671
1672 va = bin;
1673 if (size < sizeof(*va) || size < va->size) {
1674 tplg_log(tplg, 'A', pos, "tuple set verify: wrong size %zd", size);
1675 return -EINVAL;
1676 }
1677
1678 switch (va->type) {
1679 case SND_SOC_TPLG_TUPLE_TYPE_UUID:
1680 case SND_SOC_TPLG_TUPLE_TYPE_STRING:
1681 case SND_SOC_TPLG_TUPLE_TYPE_BOOL:
1682 case SND_SOC_TPLG_TUPLE_TYPE_BYTE:
1683 case SND_SOC_TPLG_TUPLE_TYPE_WORD:
1684 case SND_SOC_TPLG_TUPLE_TYPE_SHORT:
1685 break;
1686 default:
1687 tplg_log(tplg, 'A', pos, "tuple set verify: unknown array type %d", va->type);
1688 return -EINVAL;
1689 }
1690
1691 j = tplg_get_tuple_size(va->type) * va->num_elems;
1692 if (j + sizeof(*va) != va->size) {
1693 tplg_log(tplg, 'A', pos, "tuple set verify: wrong vendor array size %d "
1694 "(expected %d for %d count %d)",
1695 va->size, j + sizeof(*va), va->type, va->num_elems);
1696 return -EINVAL;
1697 }
1698
1699 if (va->num_elems > 4096) {
1700 tplg_log(tplg, 'A', pos, "tuple set verify: tuples overflow %d", va->num_elems);
1701 return -EINVAL;
1702 }
1703
1704 return 0;
1705 }
1706
tplg_decode_tuple_set(snd_tplg_t *tplg, size_t pos, struct tplg_elem *parent, struct tplg_tuple_set **_set, const void *bin, size_t size)1707 static int tplg_decode_tuple_set(snd_tplg_t *tplg,
1708 size_t pos,
1709 struct tplg_elem *parent,
1710 struct tplg_tuple_set **_set,
1711 const void *bin, size_t size)
1712 {
1713 const struct snd_soc_tplg_vendor_array *va;
1714 struct tplg_tuple_set *set;
1715 struct tplg_tuple *tuple;
1716 unsigned int j;
1717 int err;
1718
1719 va = bin;
1720 if (size < sizeof(*va) || size < va->size) {
1721 SNDERR("tuples: wrong size %zd", size);
1722 return -EINVAL;
1723 }
1724
1725 switch (va->type) {
1726 case SND_SOC_TPLG_TUPLE_TYPE_UUID:
1727 case SND_SOC_TPLG_TUPLE_TYPE_STRING:
1728 case SND_SOC_TPLG_TUPLE_TYPE_BOOL:
1729 case SND_SOC_TPLG_TUPLE_TYPE_BYTE:
1730 case SND_SOC_TPLG_TUPLE_TYPE_WORD:
1731 case SND_SOC_TPLG_TUPLE_TYPE_SHORT:
1732 break;
1733 default:
1734 SNDERR("tuples: unknown array type %d", va->type);
1735 return -EINVAL;
1736 }
1737
1738 j = tplg_get_tuple_size(va->type) * va->num_elems;
1739 if (j + sizeof(*va) != va->size) {
1740 SNDERR("tuples: wrong vendor array size %d "
1741 "(expected %d for %d count %d)",
1742 va->size, j + sizeof(*va), va->type, va->num_elems);
1743 return -EINVAL;
1744 }
1745
1746 if (va->num_elems > 4096) {
1747 SNDERR("tuples: tuples overflow %d", va->num_elems);
1748 return -EINVAL;
1749 }
1750
1751 set = calloc(1, sizeof(*set) + va->num_elems * sizeof(struct tplg_tuple));
1752 if (!set)
1753 return -ENOMEM;
1754
1755 set->type = va->type;
1756 set->num_tuples = va->num_elems;
1757
1758 tplg_log(tplg, 'A', pos, "tuple set: type %d (%s) tuples %d size %d", set->type,
1759 get_tuple_type_name(set->type), set->num_tuples, va->size);
1760 for (j = 0; j < set->num_tuples; j++) {
1761 tuple = &set->tuple[j];
1762 switch (va->type) {
1763 case SND_SOC_TPLG_TUPLE_TYPE_UUID:
1764 err = tplg_add_token(tplg, parent, va->uuid[j].token,
1765 tuple->token);
1766 if (err < 0)
1767 goto retval;
1768 memcpy(tuple->uuid, va->uuid[j].uuid,
1769 sizeof(va->uuid[j].uuid));
1770 break;
1771 case SND_SOC_TPLG_TUPLE_TYPE_STRING:
1772 err = tplg_add_token(tplg, parent, va->string[j].token,
1773 tuple->token);
1774 if (err < 0)
1775 goto retval;
1776 snd_strlcpy(tuple->string, va->string[j].string,
1777 sizeof(tuple->string));
1778 break;
1779 case SND_SOC_TPLG_TUPLE_TYPE_BOOL:
1780 case SND_SOC_TPLG_TUPLE_TYPE_BYTE:
1781 case SND_SOC_TPLG_TUPLE_TYPE_WORD:
1782 case SND_SOC_TPLG_TUPLE_TYPE_SHORT:
1783 err = tplg_add_token(tplg, parent, va->value[j].token,
1784 tuple->token);
1785 if (err < 0)
1786 goto retval;
1787 tuple->value = va->value[j].value;
1788 break;
1789 }
1790 }
1791
1792 *_set = set;
1793 return 0;
1794
1795 retval:
1796 free(set);
1797 return err;
1798 }
1799
1800 /* verify tuples from the binary input */
tplg_verify_tuples(snd_tplg_t *tplg, size_t pos, const void *bin, size_t size)1801 static int tplg_verify_tuples(snd_tplg_t *tplg, size_t pos,
1802 const void *bin, size_t size)
1803 {
1804 const struct snd_soc_tplg_vendor_array *va;
1805 int err;
1806
1807 if (size < sizeof(*va)) {
1808 tplg_log(tplg, 'A', pos, "tuples: small size %zd", size);
1809 return -EINVAL;
1810 }
1811
1812 next:
1813 va = bin;
1814 if (size < sizeof(*va)) {
1815 tplg_log(tplg, 'A', pos, "tuples: unexpected vendor arry size %zd", size);
1816 return -EINVAL;
1817 }
1818
1819 err = tplg_verify_tuple_set(tplg, pos, va, va->size);
1820 if (err < 0)
1821 return err;
1822
1823 bin += va->size;
1824 size -= va->size;
1825 pos += va->size;
1826 if (size > 0)
1827 goto next;
1828
1829 return 0;
1830 }
1831
1832 /* add tuples from the binary input */
tplg_decode_tuples(snd_tplg_t *tplg, size_t pos, struct tplg_elem *parent, struct tplg_vendor_tuples *tuples, const void *bin, size_t size)1833 static int tplg_decode_tuples(snd_tplg_t *tplg,
1834 size_t pos,
1835 struct tplg_elem *parent,
1836 struct tplg_vendor_tuples *tuples,
1837 const void *bin, size_t size)
1838 {
1839 const struct snd_soc_tplg_vendor_array *va;
1840 struct tplg_tuple_set *set;
1841 int err;
1842
1843 if (size < sizeof(*va)) {
1844 SNDERR("tuples: small size %zd", size);
1845 return -EINVAL;
1846 }
1847
1848 next:
1849 va = bin;
1850 if (size < sizeof(*va)) {
1851 SNDERR("tuples: unexpected vendor arry size %zd", size);
1852 return -EINVAL;
1853 }
1854
1855 if (tuples->num_sets >= tuples->alloc_sets) {
1856 SNDERR("tuples: index overflow (%d)", tuples->num_sets);
1857 return -EINVAL;
1858 }
1859
1860 err = tplg_decode_tuple_set(tplg, pos, parent, &set, va, va->size);
1861 if (err < 0)
1862 return err;
1863 tuples->set[tuples->num_sets++] = set;
1864
1865 bin += va->size;
1866 size -= va->size;
1867 pos += va->size;
1868 if (size > 0)
1869 goto next;
1870
1871 return 0;
1872 }
1873
1874 /* decode private data */
tplg_add_data(snd_tplg_t *tplg, struct tplg_elem *parent, const void *bin, size_t size)1875 int tplg_add_data(snd_tplg_t *tplg,
1876 struct tplg_elem *parent,
1877 const void *bin, size_t size)
1878 {
1879 const struct snd_soc_tplg_private *tp;
1880 const struct snd_soc_tplg_vendor_array *va;
1881 struct tplg_elem *elem = NULL, *elem2 = NULL;
1882 struct tplg_vendor_tuples *tuples = NULL;
1883 char id[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
1884 char suffix[16];
1885 size_t pos = 0, off;
1886 int err, num_tuples = 0, block = 0;
1887
1888 if (size == 0)
1889 return 0;
1890
1891 off = offsetof(struct snd_soc_tplg_private, array);
1892
1893 next:
1894 tp = bin;
1895 if (off + size < tp->size) {
1896 SNDERR("data: unexpected element size %zd", size);
1897 return -EINVAL;
1898 }
1899
1900 if (tplg_verify_tuples(tplg, pos, tp->array, tp->size) < 0) {
1901 if (tuples) {
1902 err = tplg_ref_add(elem, SND_TPLG_TYPE_TOKEN, parent->id);
1903 if (err < 0)
1904 return err;
1905 err = tplg_ref_add(elem2, SND_TPLG_TYPE_TUPLE, id);
1906 if (err < 0)
1907 return err;
1908 err = tplg_ref_add(parent, SND_TPLG_TYPE_DATA, id);
1909 if (err < 0)
1910 return err;
1911 tuples = NULL;
1912 }
1913 tplg_log(tplg, 'A', pos, "add bytes: size %d", tp->size);
1914 snprintf(suffix, sizeof(suffix), "data%u", block++);
1915 err = tplg_add_data_bytes(tplg, parent, suffix, tp->array, tp->size);
1916 } else {
1917 if (!tuples) {
1918 snprintf(id, sizeof(id), "%.30s:tuple%d", parent->id, (block++) & 0xffff);
1919 elem = tplg_elem_new_common(tplg, NULL, id, SND_TPLG_TYPE_TUPLE);
1920 if (!elem)
1921 return -ENOMEM;
1922
1923 elem2 = tplg_elem_new_common(tplg, NULL, id, SND_TPLG_TYPE_DATA);
1924 if (!elem2)
1925 return -ENOMEM;
1926
1927 tuples = calloc(1, sizeof(*tuples));
1928 if (!tuples)
1929 return -ENOMEM;
1930 elem->tuples = tuples;
1931
1932 tuples->alloc_sets = (size / sizeof(*va)) + 1;
1933 tuples->set = calloc(1, tuples->alloc_sets * sizeof(void *));
1934 if (!tuples->set) {
1935 tuples->alloc_sets = 0;
1936 return -ENOMEM;
1937 }
1938 }
1939 tplg_log(tplg, 'A', pos, "decode tuples: size %d", tp->size);
1940 err = tplg_decode_tuples(tplg, pos, parent, tuples, tp->array, tp->size);
1941 num_tuples++;
1942 }
1943 if (err < 0)
1944 return err;
1945
1946 bin += off + tp->size;
1947 size -= off + tp->size;
1948 pos += off + tp->size;
1949 if (size > 0)
1950 goto next;
1951
1952 if (tuples && elem && elem2) {
1953 err = tplg_ref_add(elem, SND_TPLG_TYPE_TOKEN, parent->id);
1954 if (err < 0)
1955 return err;
1956 err = tplg_ref_add(elem2, SND_TPLG_TYPE_TUPLE, id);
1957 if (err < 0)
1958 return err;
1959 err = tplg_ref_add(parent, SND_TPLG_TYPE_DATA, id);
1960 if (err < 0)
1961 return err;
1962 }
1963
1964 return 0;
1965 }
1966
1967 /* add private data - bytes */
tplg_add_data_bytes(snd_tplg_t *tplg, struct tplg_elem *parent, const char *suffix, const void *bin, size_t size)1968 int tplg_add_data_bytes(snd_tplg_t *tplg, struct tplg_elem *parent,
1969 const char *suffix, const void *bin, size_t size)
1970 {
1971 struct snd_soc_tplg_private *priv;
1972 struct tplg_elem *elem;
1973 char id[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
1974
1975 if (suffix)
1976 snprintf(id, sizeof(id), "%.30s:%.12s", parent->id, suffix);
1977 else
1978 snd_strlcpy(id, parent->id, sizeof(id));
1979 elem = tplg_elem_new_common(tplg, NULL, id, SND_TPLG_TYPE_DATA);
1980 if (!elem)
1981 return -ENOMEM;
1982
1983 priv = malloc(sizeof(*priv) + size);
1984 if (!priv)
1985 return -ENOMEM;
1986 memcpy(priv->data, bin, size);
1987 priv->size = size;
1988 elem->data = priv;
1989
1990 return tplg_ref_add(parent, SND_TPLG_TYPE_DATA, id);
1991 }
1992
1993 /* decode data from the binary input */
tplg_decode_data(snd_tplg_t *tplg ATTRIBUTE_UNUSED, size_t pos ATTRIBUTE_UNUSED, struct snd_soc_tplg_hdr *hdr ATTRIBUTE_UNUSED, void *bin ATTRIBUTE_UNUSED, size_t size ATTRIBUTE_UNUSED)1994 int tplg_decode_data(snd_tplg_t *tplg ATTRIBUTE_UNUSED,
1995 size_t pos ATTRIBUTE_UNUSED,
1996 struct snd_soc_tplg_hdr *hdr ATTRIBUTE_UNUSED,
1997 void *bin ATTRIBUTE_UNUSED,
1998 size_t size ATTRIBUTE_UNUSED)
1999 {
2000 SNDERR("data type not expected");
2001 return -EINVAL;
2002 }
2003