topology: Add support for vendor tuples
v2 cover topology: Add support for vendor tuples
From: Mengdong Lin <[email protected]>
This series addes support for vendor tuples to topology, to avoid importing binary data blob from other files.
Backward compatibility of ABI is not impacted. A kernel patch is also submitted "ASoC: topology: ABI - Define types for vendor tuples".
The 1st patch is small code cleanup.
The 2nd patch is a preparation, since tuples will need the type-specific free handler.
History:
v2: add check on string length, use strtol() to get hex value,
and fix memory leak.
Mengdong Lin (7):
topology: Use the generic pointer to free an element's object
topology: Define a free handler for the element
topology: Add doc for vendor tuples
topology: ABI - Define types for vendor tuples
topology: Add support for vendor tokens
topology: Add support for parsing vendor tuples
topology: Build data objects with tuples
include/sound/asoc.h | 42 +++- include/topology.h | 79 +++++++- src/topology/data.c | 496 +++++++++++++++++++++++++++++++++++++++++++++- src/topology/elem.c | 15 +- src/topology/parser.c | 24 +++ src/topology/tplg_local.h | 47 +++++ 6 files changed, 695 insertions(+), 8 deletions(-)
Signature · 1 line
2.5.0
PATCH v2 1/7 topology: Use the generic pointer to free an element's object
From: Mengdong Lin <[email protected]>
The element is a wrapper for different types of objects.So use the generic pointer 'obj' instead of the type-specific pointer to free the object.
src/topology/elem.c +2 -2
@@ -83,8 +83,8 @@ void tplg_elem_free(struct tplg_elem *elem)/* free struct snd_tplg_ object, * the union pointers share the same address */ -if (elem->mixer_ctrl) -free (elem->mixer_ctrl); +if (elem->obj) +free (elem->obj);free (elem); }
Signature · 1 line
2.5.0
PATCH v2 2/7 topology: Define a free handler for the element
In reply to [email protected]From: Mengdong Lin <[email protected]>
This handler is defined for type-specific destruction of an element.
src/topology/elem.c +5 -1
@@ -83,8 +83,12 @@ void tplg_elem_free(struct tplg_elem *elem)/* free struct snd_tplg_ object, * the union pointers share the same address */ -if (elem->obj) +if (elem->obj) { +if (elem->free) + elem->free (elem->obj); +free (elem->obj); + }free (elem); }
src/topology/tplg_local.h +2 -0
@@ -127,6 +127,8 @@ struct tplg_elem {*/ struct list_head ref_list;struct list_head list;/* list of all elements with same type */ + +void (*free)(void *obj); };struct map_elem {
Signature · 1 line
2.5.0
PATCH v2 3/7 topology: Add doc for vendor tuples
In reply to [email protected]From: Mengdong Lin <[email protected]>
Describe how to define vendor tokens and tuples in the text conf file.
include/topology.h +73 -4
@@ -203,12 +203,77 @@ extern "C" {* bytes "0x12,0x34,0x56,0x78" * shorts "0x1122,0x3344,0x5566,0x7788" * words "0xaabbccdd,0x11223344,0x66aa77bb,0xefef1234" +* tuples "section id of the vendor tuples" * }; * </pre> -* The file, bytes, shorts and words keywords are all mutually exclusive as -* the private data should only be taken from one source. The private data can -* either be read from a separate file or defined in the topology file using -* the bytes, shorts or words keywords. +* The file, bytes, shorts, words and tuples keywords are all mutually +* exclusive as the private data should only be taken from one source. +* The private data can either be read from a separate file or defined in +* the topology file using the bytes, shorts, words or tuples keywords. +* The keyword tuples is to define vendor specific tuples. Please refer to +* section Vendor Tokens and Vendor tuples. +* +* <h6>Vendor Tokens</h6> +* A vendor token list is defined as a new section. Each token element is +* a pair of string ID and integer value. And both the ID and value are +* vendor-specific. +* +* <pre> +* SectionVendorTokens."id of the vendor tokens" { +* comment "optional comments" +* VENDOR_TOKEN_ID1 "1" +* VENDOR_TOKEN_ID2 "2" +* VENDOR_TOKEN_ID3 "3" +* ... +* } +* </pre> +* +* <h6>Vendor Tuples</h6> +* Vendor tuples are defined as a new section. It contains a reference to +* a vendor token list and several tuple arrays. +* All arrays share a vendor token list, defined by the tokens keyword. +* Each tuple array is for a specific type, defined by the string following +* the tuples keyword. Supported types are: string, uuid, bool, byte, +* short and word. +* +* <pre> +* SectionVendorTuples."id of the vendor tuples" { +* tokens "id of the vendor tokens" +* +* tuples."string" { +* VENDOR_TOKEN_ID1 "character string" +* ... +* } +* +* tuples."uuid" { +* VENDOR_TOKEN_ID2 "16 character uuid" +* ... +* } +* +* tuples."bool" { +* VENDOR_TOKEN_ID3 "true/false" +* ... +* } +* +* tuples."byte" { +* VENDOR_TOKEN_ID4 "0x11" +* VENDOR_TOKEN_ID5 "0x22" +* ... +* } +* +* tuples."short" { +* VENDOR_TOKEN_ID6 "0x1122" +* VENDOR_TOKEN_ID7 "0x3344" +* ... +* } +* +* tuples."word" { +* VENDOR_TOKEN_ID8 "0x11223344" +* VENDOR_TOKEN_ID9 "0x55667788" +* ... +* } +* } +* </pre> * * <h5>Mixer Controls</h5> * A mixer control is defined as a new section that can include channel mapping,
@@ -389,6 +454,10 @@ extern "C" {* fields are the same for widgets as they are for controls whilst the other * fields map on very closely to the driver widget fields. * +* <h5>Widget Private Data</h5> +* Widget can have private data. For the format of the private data, please +* refer to section Control Private Data. +* * <h4>PCM Capabilities</h4> * Topology can also define the capabilities of FE and BE PCMs. Capabilities * can be defined with the following section :-
Signature · 1 line
2.5.0
PATCH v2 4/7 topology: ABI - Define types for vendor tuples
In reply to [email protected]From: Mengdong Lin <[email protected]>
Tuples, a pair of token and value, can be used to define vendor specific data, for controls and widgets. This can avoid importing binary data blob from other files.
Vendor specific tuple arrays will be embeded in the private data buffer of a control or widget object. To be backward compatible, union is used to define the tuple arrays in the existing private data ABI object 'struct snd_soc_tplg_private'.
Vendors need to make sure the token values defined by the topology conf file match those defined by their driver.
Now supported tuple types are uuid, string, bool, byte, short and word.
include/sound/asoc.h +41 -1
@@ -107,6 +107,14 @@#define SND_SOC_TPLG_STREAM_PLAYBACK 0#define SND_SOC_TPLG_STREAM_CAPTURE 1 +/* vendor tuple types */ +#define SND_SOC_TPLG_TUPLE_TYPE_UUID 0 +#define SND_SOC_TPLG_TUPLE_TYPE_STRING 1 +#define SND_SOC_TPLG_TUPLE_TYPE_BOOL 2 +#define SND_SOC_TPLG_TUPLE_TYPE_BYTE 3 +#define SND_SOC_TPLG_TUPLE_TYPE_WORD 4 +#define SND_SOC_TPLG_TUPLE_TYPE_SHORT 5 +/* * Block Header. * This header precedes all object and object arrays below.
@@ -123,6 +131,35 @@ struct snd_soc_tplg_hdr {__le32 count;/* number of elements in block */ } __attribute__((packed)); +/* vendor tuple for uuid */ +struct snd_soc_tplg_vendor_uuid_elem { +__le32 token; +char uuid[16 ]; +} __attribute__((packed)); + +/* vendor tuple for a bool/byte/short/word value */ +struct snd_soc_tplg_vendor_value_elem { +__le32 token; +__le32 value; +} __attribute__((packed)); + +/* vendor tuple for string */ +struct snd_soc_tplg_vendor_string_elem { +__le32 token; +char string[SNDRV_CTL_ELEM_ID_NAME_MAXLEN ]; +} __attribute__((packed)); + +struct snd_soc_tplg_vendor_array { +__le32 size;/* size in bytes of the array, including all elements */ +__le32 type;/* SND_SOC_TPLG_TUPLE_TYPE_ */ +__le32 num_elems;/* number of elements in array */ +union { +struct snd_soc_tplg_vendor_uuid_elem uuid[0 ]; +struct snd_soc_tplg_vendor_value_elem value[0 ]; +struct snd_soc_tplg_vendor_string_elem string[0 ]; + }; +} __attribute__((packed)); +/* * Private data. * All topology objects may have private data that can be used by the driver or
@@ -130,7 +167,10 @@ struct snd_soc_tplg_hdr {*/ struct snd_soc_tplg_private {__le32 size;/* in bytes of private data */ -char data[0 ]; +union { +char data[0 ]; +struct snd_soc_tplg_vendor_array array[0 ]; + }; } __attribute__((packed));/*
Signature · 1 line
2.5.0
PATCH v2 5/7 topology: Add support for vendor tokens
In reply to [email protected]From: Mengdong Lin <[email protected]>
Vendor can define a token list in SectionVendorTokens. Each token element is a pair of string ID and integer value. And both the ID and value are vendor-specific.
include/topology.h +1 -0
@@ -578,6 +578,7 @@ enum snd_tplg_type {SND_TPLG_TYPE_BE ,/*!< BE DAI link */ SND_TPLG_TYPE_CC ,/*!< Hostless codec <-> codec link */ SND_TPLG_TYPE_MANIFEST ,/*!< Topology manifest */ + SND_TPLG_TYPE_TOKEN, /*!< Vendor tokens */ };/**
src/topology/data.c +50 -0
56 lines not on this page · raw message
src/topology/elem.c +3 -0
@@ -193,6 +193,9 @@ struct tplg_elem* tplg_elem_new_common(snd_tplg_t *tplg,list_add_tail (&elem->list, &tplg->cc_list); obj_size =sizeof (struct snd_soc_tplg_link_config );break ; +case SND_TPLG_TYPE_TOKEN : +list_add_tail (&elem->list, &tplg->token_list); +break ;default :free (elem);return NULL ;
src/topology/parser.c +10 -0
@@ -173,6 +173,14 @@ static int tplg_parse_config(snd_tplg_t *tplg, snd_config_t *cfg)continue ; } +if (strcmp (id,"SectionVendorTokens" ) ==0 ) { + err =tplg_parse_compound (tplg, n, tplg_parse_tokens, +NULL ); +if (err <0 ) +return err; +continue ; + } +SNDERR ("error: unknown section %s\n" , id); }return 0 ;
@@ -407,6 +415,7 @@ snd_tplg_t *snd_tplg_new(void)INIT_LIST_HEAD (&tplg->mixer_list);INIT_LIST_HEAD (&tplg->enum_list);INIT_LIST_HEAD (&tplg->bytes_ext_list); +INIT_LIST_HEAD (&tplg->token_list);return tplg; }
@@ -426,6 +435,7 @@ void snd_tplg_free(snd_tplg_t *tplg)tplg_elem_free_list (&tplg->mixer_list);tplg_elem_free_list (&tplg->enum_list);tplg_elem_free_list (&tplg->bytes_ext_list); +tplg_elem_free_list (&tplg->token_list);free (tplg); }
src/topology/tplg_local.h +15 -0
@@ -69,6 +69,7 @@ struct snd_tplg {struct list_head route_list;struct list_head text_list;struct list_head pdata_list; +struct list_head token_list;struct list_head pcm_config_list;struct list_head pcm_caps_list;
@@ -86,6 +87,16 @@ struct tplg_ref {struct list_head list; }; +/* element for vendor tokens */ +struct tplg_token { +char id[SNDRV_CTL_ELEM_ID_NAME_MAXLEN ]; +unsigned int value; +}; + +struct tplg_vendor_tokens { +unsigned int num_tokens; +struct tplg_token token[0 ]; +};/* topology element */ struct tplg_elem {
@@ -118,6 +129,7 @@ struct tplg_elem {/* these do not map to UAPI structs but are internal only */ struct snd_soc_tplg_ctl_tlv *tlv;struct snd_soc_tplg_private *data; +struct tplg_vendor_tokens *tokens; };/* an element may refer to other elements:
@@ -151,6 +163,9 @@ int tplg_parse_text(snd_tplg_t *tplg, snd_config_t *cfg,int tplg_parse_data (snd_tplg_t *tplg,snd_config_t *cfg, void *private ATTRIBUTE_UNUSED); +int tplg_parse_tokens (snd_tplg_t *tplg,snd_config_t *cfg, + void *private ATTRIBUTE_UNUSED); +int tplg_parse_control_bytes (snd_tplg_t *tplg, snd_config_t *cfg, void *private ATTRIBUTE_UNUSED);
Signature · 1 line
2.5.0
PATCH v2 6/7 topology: Add support for parsing vendor tuples
In reply to [email protected]From: Mengdong Lin <[email protected]>
Vendor can define several tuple arrays in 'SectionVendorTuples', as well as the reference to a vendor token list object.
A later patche will copy vendor tuples in ABI format to the private buffer of its parent data object in the building phase.
include/topology.h +1 -0
@@ -579,6 +579,7 @@ enum snd_tplg_type {SND_TPLG_TYPE_CC ,/*!< Hostless codec <-> codec link */ SND_TPLG_TYPE_MANIFEST ,/*!< Topology manifest */ SND_TPLG_TYPE_TOKEN ,/*!< Vendor tokens */ + SND_TPLG_TYPE_TUPLE, /*!< Vendor tuples */ };/**
src/topology/data.c +232 -1
254 lines not on this page · raw message
src/topology/elem.c +4 -0
@@ -196,6 +196,10 @@ struct tplg_elem* tplg_elem_new_common(snd_tplg_t *tplg,case SND_TPLG_TYPE_TOKEN :list_add_tail (&elem->list, &tplg->token_list);break ; +case SND_TPLG_TYPE_TUPLE : +list_add_tail (&elem->list, &tplg->tuple_list); + elem->free = tplg_free_tuples; +break ;default :free (elem);return NULL ;
src/topology/parser.c +10 -0
@@ -181,6 +181,14 @@ static int tplg_parse_config(snd_tplg_t *tplg, snd_config_t *cfg)continue ; } +if (strcmp (id,"SectionVendorTuples" ) ==0 ) { + err =tplg_parse_compound (tplg, n, tplg_parse_tuples, +NULL ); +if (err <0 ) +return err; +continue ; + } +SNDERR ("error: unknown section %s\n" , id); }return 0 ;
@@ -416,6 +424,7 @@ snd_tplg_t *snd_tplg_new(void)INIT_LIST_HEAD (&tplg->enum_list);INIT_LIST_HEAD (&tplg->bytes_ext_list);INIT_LIST_HEAD (&tplg->token_list); +INIT_LIST_HEAD (&tplg->tuple_list);return tplg; }
@@ -436,6 +445,7 @@ void snd_tplg_free(snd_tplg_t *tplg)tplg_elem_free_list (&tplg->enum_list);tplg_elem_free_list (&tplg->bytes_ext_list);tplg_elem_free_list (&tplg->token_list); +tplg_elem_free_list (&tplg->tuple_list);free (tplg); }
src/topology/tplg_local.h +29 -0
@@ -70,6 +70,7 @@ struct snd_tplg {struct list_head text_list;struct list_head pdata_list;struct list_head token_list; +struct list_head tuple_list;struct list_head pcm_config_list;struct list_head pcm_caps_list;
@@ -97,6 +98,28 @@ struct tplg_vendor_tokens {unsigned int num_tokens;struct tplg_token token[0 ]; }; + +/* element for vendor tuples */ +struct tplg_tuple { +char token[SNDRV_CTL_ELEM_ID_NAME_MAXLEN ]; +union { +char string[SNDRV_CTL_ELEM_ID_NAME_MAXLEN ]; +char uuid[16 ]; +unsigned int value; + }; +}; + +struct tplg_tuple_set { +unsigned int type;/* uuid, bool, byte, short, word, string*/ +unsigned int num_tuples; +struct tplg_tuple tuple[0 ]; +}; + +struct tplg_vendor_tuples { +unsigned int num_sets; +struct tplg_tuple_set **set; +}; +/* topology element */ struct tplg_elem {
@@ -130,6 +153,7 @@ struct tplg_elem {struct snd_soc_tplg_ctl_tlv *tlv;struct snd_soc_tplg_private *data;struct tplg_vendor_tokens *tokens; +struct tplg_vendor_tuples *tuples; };/* an element may refer to other elements:
@@ -166,6 +190,11 @@ int tplg_parse_data(snd_tplg_t *tplg, snd_config_t *cfg,int tplg_parse_tokens (snd_tplg_t *tplg,snd_config_t *cfg, void *private ATTRIBUTE_UNUSED); +int tplg_parse_tuples (snd_tplg_t *tplg,snd_config_t *cfg, + void *private ATTRIBUTE_UNUSED); + +void tplg_free_tuples (void *obj); +int tplg_parse_control_bytes (snd_tplg_t *tplg, snd_config_t *cfg, void *private ATTRIBUTE_UNUSED);
Signature · 1 line
2.5.0
Re: [PATCH v2 6/7] topology: Add support for parsing vendor tuples
src/topology/data.c static int tplg_parse_data_hex(snd_config_t *cfg, struct tplg_elem *elem, · line 323
Quoted 10 lines · On Wed, 30 Mar 2016 09:11:17 +0200, [email protected] wrote:
src/topology/data.c +9
-0+switch (type) { +case SND_SOC_TPLG_TUPLE_TYPE_UUID : + len =strlen (value); +if (len >16 || len ==0 ) { +SNDERR ("error: tuple %s: invalid uuid\n" , id); + goto err; + } + +memcpy (tuple->uuid, value,16 );
This may still overflow :)
How about simply using elem_copy_text()?
src/topology/data.c static int tplg_parse_data_hex(snd_config_t *cfg, struct tplg_elem *elem, · line 345
Quoted 7 lines
src/topology/data.c +7
-0+case SND_SOC_TPLG_TUPLE_TYPE_BYTE : +case SND_SOC_TPLG_TUPLE_TYPE_SHORT : +case SND_SOC_TPLG_TUPLE_TYPE_WORD : + tuple_val =strtol (value,NULL ,0 ); +if (tuple_val ==LONG_MIN || tuple_val ==LONG_MAX + || (type ==SND_SOC_TPLG_TUPLE_TYPE_WORD + && tuple_val > 0xffffffff)
Is the check correct on 32bit architecture?
src/topology/data.c static int tplg_parse_data_hex(snd_config_t *cfg, struct tplg_elem *elem, · line 349
Quoted 4 lines
src/topology/data.c +4
-0+ || (type == SND_SOC_TPLG_TUPLE_TYPE_SHORT + && tuple_val > 0xffff) + || (type == SND_SOC_TPLG_TUPLE_TYPE_BYTE + && tuple_val > 0xff)) {
Also, what about negative values?
Takashi
Re: [PATCH v2 6/7] topology: Add support for parsing vendor tuples
Quoted 15 lines · Takashi Iwai
src/topology/data.c static int tplg_parse_data_hex(snd_config_t *cfg, struct tplg_elem *elem, · line 323
Quoted 10 lines · On Wed, 30 Mar 2016 09:11:17 +0200, [email protected] wrote:
src/topology/data.c +9
-0+switch (type) { +case SND_SOC_TPLG_TUPLE_TYPE_UUID : + len =strlen (value); +if (len >16 || len ==0 ) { +SNDERR ("error: tuple %s: invalid uuid\n" , id); + goto err; + } + +memcpy (tuple->uuid, value,16 );This may still overflow :)
How about simply usingelem_copy_text()?
Sorry for the late reply.
Would you mind me using uuid_parse() here?
It can convert an input UUID string into the binary representation.
An UUID string link "1b4e28ba-2fa1-11d2-883f-b9a761bde3fb" is user friendly for the text conf file. But this will add dependency on libuuid.
Quoted 10 lines
src/topology/data.c static int tplg_parse_data_hex(snd_config_t *cfg, struct tplg_elem *elem, · line 345
Quoted 8 lines
src/topology/data.c +7
-0+case SND_SOC_TPLG_TUPLE_TYPE_BYTE : +case SND_SOC_TPLG_TUPLE_TYPE_SHORT : +case SND_SOC_TPLG_TUPLE_TYPE_WORD : + tuple_val =strtol (value,NULL ,0 ); +if (tuple_val ==LONG_MIN || tuple_val ==LONG_MAX + || (type ==SND_SOC_TPLG_TUPLE_TYPE_WORD + && tuple_val > 0xffffffff)Is the check correct on 32bit architecture?
I'll test on 32 bit machine and will use UINT/USHRT/UCHAR_MAX for range here.
Quoted 6 lines
src/topology/data.c static int tplg_parse_data_hex(snd_config_t *cfg, struct tplg_elem *elem, · line 349
Quoted 4 lines
src/topology/data.c +4
-0+ || (type == SND_SOC_TPLG_TUPLE_TYPE_SHORT + && tuple_val > 0xffff) + || (type == SND_SOC_TPLG_TUPLE_TYPE_BYTE + && tuple_val > 0xff)) {Also, what about negative values?
I will add check, we don't expect to have negative value here.
Thanks again for your review.
Regards
Mengdong
Quoted 7 lines
Takashi
_______________________________________________
Alsa-devel mailing list
[email protected]
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
Re: [PATCH v2 6/7] topology: Add support for parsing vendor tuples
Quoted 20 lines · Mengdong Lin
Quoted 15 lines · Takashi Iwai
src/topology/data.c static int tplg_parse_data_hex(snd_config_t *cfg, struct tplg_elem *elem, · line 323
Quoted 10 lines · On Wed, 30 Mar 2016 09:11:17 +0200, [email protected] wrote:
src/topology/data.c +9
-0+switch (type) { +case SND_SOC_TPLG_TUPLE_TYPE_UUID : + len =strlen (value); +if (len >16 || len ==0 ) { +SNDERR ("error: tuple %s: invalid uuid\n" , id); + goto err; + } + +memcpy (tuple->uuid, value,16 );This may still overflow :)
How about simply usingelem_copy_text()?
Quoted 7 lines
Sorry for the late reply.
Would you mind me using
uuid_parse()here?
It can convert an input UUID string into the binary representation.An UUID string link "1b4e28ba-2fa1-11d2-883f-b9a761bde3fb" is user friendly for the text conf file. But this will add dependency on libuuid.
Additional dependency is no-go, especially when the required change is so trivial. It's just a string copy, after all.
thanks,
Takashi
Re: [PATCH v2 6/7] topology: Add support for parsing vendor tuples
Quoted 24 lines · Takashi Iwai
Quoted 22 lines · Mengdong Lin
Quoted 15 lines · Takashi Iwai
src/topology/data.c static int tplg_parse_data_hex(snd_config_t *cfg, struct tplg_elem *elem, · line 323
Quoted 10 lines · On Wed, 30 Mar 2016 09:11:17 +0200, [email protected] wrote:
src/topology/data.c +9
-0+switch (type) { +case SND_SOC_TPLG_TUPLE_TYPE_UUID : + len =strlen (value); +if (len >16 || len ==0 ) { +SNDERR ("error: tuple %s: invalid uuid\n" , id); + goto err; + } + +memcpy (tuple->uuid, value,16 );This may still overflow :)
How about simply usingelem_copy_text()?Sorry for the late reply.
Quoted 9 lines
Quoted 5 lines
Would you mind me using
uuid_parse()here?
It can convert an input UUID string into the binary representation.An UUID string link "1b4e28ba-2fa1-11d2-883f-b9a761bde3fb" is user friendly for the text conf file. But this will add dependency on libuuid.
Additional dependency is no-go, especially when the required change is so trivial. It's just a string copy, after all.
Maybe we can just use strncpy(dest, src, 16), assuming the strncpy will not try to write a "\0" at dest[16] that may cause overflow?
The user need to define uuid without "-" in the UUID string in the text conf file.
Now the uuid value in ABI is 16-character array:
/* vendor tuple for uuid */
struct snd_soc_tplg_vendor_uuid_elem {
__le32 token;
char uuid[16];
} __attribute__((packed));The last byte of UUID may not be zero.
Thanks
Mengdong
Re: [PATCH v2 6/7] topology: Add support for parsing vendor tuples
Quoted 33 lines · Mengdong Lin
Quoted 30 lines · Takashi Iwai
Quoted 27 lines · Mengdong Lin
Quoted 15 lines · Takashi Iwai
src/topology/data.c static int tplg_parse_data_hex(snd_config_t *cfg, struct tplg_elem *elem, · line 323
Quoted 10 lines · On Wed, 30 Mar 2016 09:11:17 +0200, [email protected] wrote:
src/topology/data.c +9
-0+switch (type) { +case SND_SOC_TPLG_TUPLE_TYPE_UUID : + len =strlen (value); +if (len >16 || len ==0 ) { +SNDERR ("error: tuple %s: invalid uuid\n" , id); + goto err; + } + +memcpy (tuple->uuid, value,16 );This may still overflow :)
How about simply usingelem_copy_text()?Sorry for the late reply.
Would you mind me using
uuid_parse()here?
It can convert an input UUID string into the binary representation.An UUID string link "1b4e28ba-2fa1-11d2-883f-b9a761bde3fb" is user friendly for the text conf file. But this will add dependency on libuuid.
Quoted 6 lines
Quoted 3 lines
Additional dependency is no-go, especially when the required change is so trivial. It's just a string copy, after all.
Maybe we can just use
strncpy(dest, src, 16), assuming the strncpy will not try to write a "\0" at dest[16] that may cause overflow?
You seem to think of things more complicated than needed.
Just reread your code. What if a shorter string value is passed there to memcpy() call? That's what I suggested as an overflow.
Takashi
Re: [PATCH v2 6/7] topology: Add support for parsing vendor tuples
Quoted 51 lines
-----Original Message-----
From: [email protected] [mailto:[email protected]] On Behalf Of Takashi Iwai
Sent: Tuesday, April 05, 2016 5:38 PM
To: Mengdong Lin
Cc: [email protected]; Koul, Vinod; Lin, Mengdong; [email protected]; Ughreja, Rakesh A; Girdwood, Liam R; Shah, Hardik T; Prusty, Subhransu S
Subject: Re: [alsa-devel] [PATCH v2 6/7] topology: Add support for parsing vendor tuplesQuoted 10 lines · Mengdong Lin
Quoted 7 lines · Takashi Iwai
Quoted 5 lines · Mengdong Lin
Quoted 1 line · Takashi Iwai
On Wed, 30 Mar 2016 09:11:17 +0200,
Quoted 27 lines
Quoted 26 lines
Quoted 15 lines
Quoted 14 lines
src/topology/data.c static int tplg_parse_data_hex(snd_config_t *cfg, struct tplg_elem *elem, · line 323
Quoted 10 lines · wrote:
src/topology/data.c +9
-0+switch (type) { +case SND_SOC_TPLG_TUPLE_TYPE_UUID : + len =strlen (value); +if (len >16 || len ==0 ) { +SNDERR ("error: tuple %s: invalid uuid\n" , id); + goto err; + } + +memcpy (tuple->uuid, value,16 );This may still overflow :)
How about simply usingelem_copy_text()?Quoted 7 lines
Sorry for the late reply.
Would you mind me using
uuid_parse()here?
It can convert an input UUID string into the binary representation.An UUID string link "1b4e28ba-2fa1-11d2-883f-b9a761bde3fb" is user friendly for the text conf file. But this will add dependency on libuuid.
Additional dependency is no-go, especially when the required change is so trivial. It's just a string copy, after all.
Quoted 7 lines
Quoted 2 lines
Maybe we can just use
strncpy(dest, src, 16), assuming the strncpy will not try to write a "\0" at dest[16] that may cause overflow?You seem to think of things more complicated than needed.
Just reread your code. What if a shorter string value is passed there to
memcpy()call? That's what I suggested as an overflow.
I misunderstood your point and overlooked this bug.
I should have checked the string length at first and then use the length in the memcpy.
Thanks again
Mengdong
PATCH v2 7/7 topology: Build data objects with tuples
In reply to [email protected]From: Mengdong Lin <[email protected]>
For data objects with tuples, the parser will bind the vendor tuples and tokens, copy the tuples to the private buffer of its parent data object. Then later the builder will export the vendor tuples as private binary data for the control or widgets objects.
src/topology/data.c +213 -0
@@ -253,6 +253,198 @@ static int tplg_parse_data_hex(snd_config_t *cfg, struct tplg_elem *elem,return ret; } +/* get the token integer value from its id */ +static int get_token_value (const char *token_id, +struct tplg_vendor_tokens *tokens) +{ +int i; + +for (i =0 ; i < tokens->num_tokens; i++) { +if (strcmp (token_id, tokens->token[i].id) ==0 ) +return tokens->token[i].value; + } + +SNDERR ("error: cannot find token id '%s'\n" , token_id); +return -1 ; +} + +/* get the vendor tokens referred by the vendor tuples */ +static struct tplg_elem *get_tokens (snd_tplg_t *tplg,struct tplg_elem *elem) +{ +struct tplg_ref *ref; +struct list_head *base, *pos; +int err =0 ; + + base = &elem->ref_list; +list_for_each (pos, base) { + + ref = list_entry(pos, struct tplg_ref, list); + +if (!ref->id || ref->type !=SND_TPLG_TYPE_TOKEN ) +continue ; + +if (!ref->elem) { + ref->elem =tplg_elem_lookup (&tplg->token_list, + ref->id,SND_TPLG_TYPE_TOKEN ); + } + +return ref->elem; + } + +return NULL ; +} + +/* check if a data element has tuples */ +static bool has_tuples (struct tplg_elem *elem) +{ +struct tplg_ref *ref; +struct list_head *base, *pos; +int err =0 ; + + base = &elem->ref_list; +list_for_each (pos, base) { + + ref = list_entry(pos, struct tplg_ref, list); +if (ref->id && ref->type ==SND_TPLG_TYPE_TUPLE ) +return true; + } + +return false; +} + +/* get size of a tuple element from its type */ +static unsigned int get_tuple_size (int type) +{ +switch (type) { + +case SND_SOC_TPLG_TUPLE_TYPE_UUID : +return sizeof (struct snd_soc_tplg_vendor_uuid_elem ); + +case SND_SOC_TPLG_TUPLE_TYPE_STRING : +return sizeof (struct snd_soc_tplg_vendor_string_elem ); + +default : +return sizeof (struct snd_soc_tplg_vendor_value_elem ); + } +} + +/* fill a data element's private buffer with its tuples */ +static int copy_tuples (struct tplg_elem *elem, +struct tplg_vendor_tuples *tuples,struct tplg_vendor_tokens *tokens) +{ +struct snd_soc_tplg_private *priv = elem->data; +struct tplg_tuple_set *tuple_set; +struct tplg_tuple *tuple; +struct snd_soc_tplg_vendor_array *array; +struct snd_soc_tplg_vendor_uuid_elem *uuid; +struct snd_soc_tplg_vendor_string_elem *string; +struct snd_soc_tplg_vendor_value_elem *value; +int set_size, size, off; +int i, j, token_val; + +if (priv) { +SNDERR ("error: %s has more data than tuples\n" , elem->id); +return -EINVAL ; + } + + size =0 ; +for (i =0 ; i < tuples->num_sets ; i++) { + tuple_set = tuples->set[i]; + set_size =sizeof (struct snd_soc_tplg_vendor_array ) + +get_tuple_size (tuple_set->type) + * tuple_set->num_tuples; + size += set_size; +if (size >TPLG_MAX_PRIV_SIZE ) { +SNDERR ("error: data too big %d\n" , size); +return -EINVAL ; + } + +if (priv !=NULL ) + priv =realloc (priv,sizeof (*priv) + size); +else + priv =calloc (1 ,sizeof (*priv) + size); +if (!priv) +return -ENOMEM ; + + off = priv->size; + priv->size = size; + + array = (struct snd_soc_tplg_vendor_array *)(priv->data + off); + array->size = set_size; + array->type = tuple_set->type; + array->num_elems = tuple_set->num_tuples; + +/* fill the private data buffer */ +for (j =0 ; j < tuple_set->num_tuples; j++) { + tuple = &tuple_set->tuple[j]; + token_val =get_token_value (tuple->token, tokens); +if (token_val <0 ) +return -EINVAL ; + +switch (tuple_set->type) { +case SND_SOC_TPLG_TUPLE_TYPE_UUID : + uuid = &array->uuid[j]; + uuid->token = token_val; +memcpy (uuid->uuid, tuple->uuid,16 ); +break ; + +case SND_SOC_TPLG_TUPLE_TYPE_STRING : + string = &array->string[j]; + string->token = token_val; +elem_copy_text (string->string, tuple->string, +SNDRV_CTL_ELEM_ID_NAME_MAXLEN ); +break ; + +default : + value = &array->value[j]; + value->token = token_val; + value->value = tuple->value; +break ; + } + } + } + + elem->data = priv; +return 0 ; +} + +/* build a data element from its tuples */ +static int build_tuples (snd_tplg_t *tplg,struct tplg_elem *elem) +{ +struct tplg_ref *ref; +struct list_head *base, *pos; +struct tplg_elem *tuples, *tokens; + + base = &elem->ref_list; +list_for_each (pos, base) { + + ref = list_entry(pos, struct tplg_ref, list); + +if (!ref->id || ref->type !=SND_TPLG_TYPE_TUPLE ) +continue ; + +tplg_dbg ("look up tuples %s\n" , ref->id); + +if (!ref->elem) + ref->elem =tplg_elem_lookup (&tplg->tuple_list, + ref->id,SND_TPLG_TYPE_TUPLE ); + tuples = ref->elem; +if (!tuples) +return -EINVAL ; + +tplg_dbg ("found tuples %s\n" , tuples->id); + tokens =get_tokens (tplg, tuples); +if (!tokens) +return -EINVAL ; + +tplg_dbg ("found tokens %s\n" , tokens->id); +/* a data object can only have one tuples object */ +return copy_tuples (elem, tuples->tuples, tokens->tokens); + } + +return 0 ; +} +static int parse_tuple_set (snd_tplg_t *tplg,snd_config_t *cfg,struct tplg_tuple_set **s) {
@@ -676,3 +868,24 @@ int tplg_copy_data(struct tplg_elem *elem, struct tplg_elem *ref)memcpy (priv->data, ref->data->data, priv_data_size);return 0 ; } + +/* check data objects and build those with tuples */ +int tplg_build_data (snd_tplg_t *tplg) +{ +struct list_head *base, *pos; +struct tplg_elem *elem; +int err =0 ; + + base = &tplg->pdata_list; +list_for_each (pos, base) { + + elem = list_entry(pos, struct tplg_elem, list); +if (has_tuples (elem)) { + err =build_tuples (tplg, elem); +if (err <0 ) +return err; + } + } + +return 0 ; +}
src/topology/parser.c +4 -0
@@ -242,6 +242,10 @@ static int tplg_build_integ(snd_tplg_t *tplg) {int err; + err =tplg_build_data (tplg); +if (err <0 ) +return err; + err =tplg_build_controls (tplg);if (err <0 )return err;
src/topology/tplg_local.h +1 -0
@@ -222,6 +222,7 @@ int tplg_parse_be(snd_tplg_t *tplg,int tplg_parse_cc (snd_tplg_t *tplg, snd_config_t *cfg, void *private ATTRIBUTE_UNUSED); +int tplg_build_data (snd_tplg_t *tplg);int tplg_build_controls (snd_tplg_t *tplg);int tplg_build_widgets (snd_tplg_t *tplg);int tplg_build_routes (snd_tplg_t *tplg);
Signature · 1 line
2.5.0