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