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