xref: /OK3568_Linux_fs/external/rkwifibt/drivers/bcmdhd/include/bcmtlv.h (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * TLV and XTLV support
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Copyright (C) 2020, Broadcom.
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  *      Unless you and Broadcom execute a separate written software license
7*4882a593Smuzhiyun  * agreement governing use of this software, this software is licensed to you
8*4882a593Smuzhiyun  * under the terms of the GNU General Public License version 2 (the "GPL"),
9*4882a593Smuzhiyun  * available at http://www.broadcom.com/licenses/GPLv2.php, with the
10*4882a593Smuzhiyun  * following added to such license:
11*4882a593Smuzhiyun  *
12*4882a593Smuzhiyun  *      As a special exception, the copyright holders of this software give you
13*4882a593Smuzhiyun  * permission to link this software with independent modules, and to copy and
14*4882a593Smuzhiyun  * distribute the resulting executable under terms of your choice, provided that
15*4882a593Smuzhiyun  * you also meet, for each linked independent module, the terms and conditions of
16*4882a593Smuzhiyun  * the license of that module.  An independent module is a module which is not
17*4882a593Smuzhiyun  * derived from this software.  The special exception does not apply to any
18*4882a593Smuzhiyun  * modifications of the software.
19*4882a593Smuzhiyun  *
20*4882a593Smuzhiyun  *
21*4882a593Smuzhiyun  * <<Broadcom-WL-IPTag/Dual:>>
22*4882a593Smuzhiyun  */
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun #ifndef	_bcmtlv_h_
25*4882a593Smuzhiyun #define	_bcmtlv_h_
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun #include <typedefs.h>
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun #ifdef __cplusplus
30*4882a593Smuzhiyun extern "C" {
31*4882a593Smuzhiyun #endif /* __cplusplus */
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun /* begin tlvs - used in 802.11 IEs etc. */
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun /* type(aka id)/length/value buffer triple */
36*4882a593Smuzhiyun typedef struct bcm_tlv {
37*4882a593Smuzhiyun 	uint8	id;
38*4882a593Smuzhiyun 	uint8	len;
39*4882a593Smuzhiyun 	uint8	data[1];
40*4882a593Smuzhiyun } bcm_tlv_t;
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun /* size of tlv including data */
43*4882a593Smuzhiyun #define BCM_TLV_SIZE(_tlv) ((_tlv) ? (OFFSETOF(bcm_tlv_t, data) + (_tlv)->len) : 0u)
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun /* get next tlv - no length checks */
46*4882a593Smuzhiyun #define BCM_TLV_NEXT(_tlv) (bcm_tlv_t *)((uint8 *)(_tlv)+ BCM_TLV_SIZE(_tlv))
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun /* tlv length is restricted to 1 byte */
49*4882a593Smuzhiyun #define BCM_TLV_MAX_DATA_SIZE (255)
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun /* tlv header - two bytes */
52*4882a593Smuzhiyun #define BCM_TLV_HDR_SIZE (OFFSETOF(bcm_tlv_t, data))
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun /* Check that bcm_tlv_t fits into the given buffer len */
55*4882a593Smuzhiyun #define bcm_valid_tlv(elt, buflen)					\
56*4882a593Smuzhiyun 	((elt != NULL) &&						\
57*4882a593Smuzhiyun 	 ((buflen) >= (uint)BCM_TLV_HDR_SIZE) &&			\
58*4882a593Smuzhiyun 	 ((buflen) >= (uint)(BCM_TLV_HDR_SIZE + (elt)->len)))
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun /* type(aka id)/length/ext/value buffer */
61*4882a593Smuzhiyun typedef struct bcm_tlv_ext {
62*4882a593Smuzhiyun 	uint8	id;
63*4882a593Smuzhiyun 	uint8	len;
64*4882a593Smuzhiyun 	uint8	ext;
65*4882a593Smuzhiyun 	uint8	data[1];
66*4882a593Smuzhiyun } bcm_tlv_ext_t;
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun /* get next tlv_ext - no length checks */
69*4882a593Smuzhiyun #define BCM_TLV_EXT_NEXT(_tlv_ext) \
70*4882a593Smuzhiyun 	(bcm_tlv_ext_t *)((uint8 *)(_tlv_ext)+ BCM_TLV_EXT_SIZE(_tlv_ext))
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun /* tlv_ext length is restricted to 1 byte */
73*4882a593Smuzhiyun #define BCM_TLV_EXT_MAX_DATA_SIZE (254u)
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun /* tlv_ext header - three bytes */
76*4882a593Smuzhiyun #define BCM_TLV_EXT_HDR_SIZE (OFFSETOF(bcm_tlv_ext_t, data))
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun /* size of tlv_ext including data */
79*4882a593Smuzhiyun #define BCM_TLV_EXT_SIZE(_tlv_ext) (BCM_TLV_EXT_HDR_SIZE + (_tlv_ext)->len)
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun /* find the next tlv */
82*4882a593Smuzhiyun bcm_tlv_t *bcm_next_tlv(const  bcm_tlv_t *elt, uint *buflen);
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun /* move buffer/buflen up to the given tlv, or set to NULL/0 on error */
85*4882a593Smuzhiyun void bcm_tlv_buffer_advance_to(const bcm_tlv_t *elt, const uint8 **buffer, uint *buflen);
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun /* move buffer/buflen past the given tlv, or set to NULL/0 on error */
88*4882a593Smuzhiyun void bcm_tlv_buffer_advance_past(const bcm_tlv_t *elt, const uint8 **buffer, uint *buflen);
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun /* find the tlv for a given id */
91*4882a593Smuzhiyun bcm_tlv_t *bcm_parse_tlvs(const  void *buf, uint buflen, uint key);
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun /* advancement modes for bcm_parse_tlvs_advance() */
94*4882a593Smuzhiyun typedef enum {
95*4882a593Smuzhiyun 	BCM_TLV_ADVANCE_NONE = 0,  // do not adjust the buffer/buflen
96*4882a593Smuzhiyun 	BCM_TLV_ADVANCE_TO = 1,    // advance to the found tlv
97*4882a593Smuzhiyun 	BCM_TLV_ADVANCE_PAST = 2   // advance past the found tlv
98*4882a593Smuzhiyun } bcm_tlv_advance_mode_t;
99*4882a593Smuzhiyun 
100*4882a593Smuzhiyun /* Find an IE of a specific type from a buffer.
101*4882a593Smuzhiyun  * tlvs: buffer to search for IE
102*4882a593Smuzhiyun  * tlvs_len: buffer length
103*4882a593Smuzhiyun  * tag: IE tag
104*4882a593Smuzhiyun  * oui_len: length of the OUI
105*4882a593Smuzhiyun  * oui: Specific OUI to match
106*4882a593Smuzhiyun  * type: OUI type
107*4882a593Smuzhiyun  * Return the matched IE, else return null.
108*4882a593Smuzhiyun */
109*4882a593Smuzhiyun extern bcm_tlv_t *bcm_find_ie(const uint8 *tlvs, uint tlvs_len, uint8 tag,
110*4882a593Smuzhiyun 	uint8 oui_len, const char *oui, uint8 type);
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun /* search for a matching tlv id, and adjust the parse buffer pointer/length */
113*4882a593Smuzhiyun const bcm_tlv_t *bcm_parse_tlvs_advance(const uint8 **buf, uint *buflen, uint key,
114*4882a593Smuzhiyun 	bcm_tlv_advance_mode_t advance);
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun /*
117*4882a593Smuzhiyun  * Traverse tlvs and return pointer to the first tlv that
118*4882a593Smuzhiyun  * matches the key. Return NULL if not found or tlv len < min_bodylen
119*4882a593Smuzhiyun  */
120*4882a593Smuzhiyun bcm_tlv_t *bcm_parse_tlvs_min_bodylen(const  void *buf, uint buflen, uint key, uint min_bodylen);
121*4882a593Smuzhiyun 
122*4882a593Smuzhiyun /*
123*4882a593Smuzhiyun  * Traverse tlvs and return pointer to the first tlv that
124*4882a593Smuzhiyun  * matches the key. Return NULL if not found or tlv size > max_len or < min_len
125*4882a593Smuzhiyun  */
126*4882a593Smuzhiyun bcm_tlv_t *bcm_parse_tlvs_minmax_len(const  void *buf, uint buflen, uint key,
127*4882a593Smuzhiyun 	uint min_len, uint max_len);
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun /* parse tlvs for dot11 - same as parse_tlvs but supports 802.11 id extension */
130*4882a593Smuzhiyun bcm_tlv_t *bcm_parse_tlvs_dot11(const  void *buf, uint buflen, uint key, bool id_ext);
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun /* same as parse_tlvs, but stops when found id > key */
133*4882a593Smuzhiyun const  bcm_tlv_t *bcm_parse_ordered_tlvs(const  void *buf, uint buflen, uint key);
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun /* find a tlv with DOT11_MNG_PROPR_ID as id, and the given oui and type */
136*4882a593Smuzhiyun 	bcm_tlv_t *bcm_find_vendor_ie(const  void *tlvs, uint tlvs_len, const char *voui,
137*4882a593Smuzhiyun 	                              uint8 *type, uint type_len);
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun /* write tlv at dst and return next tlv ptr */
140*4882a593Smuzhiyun uint8 *bcm_write_tlv(int type, const void *data, uint datalen, uint8 *dst);
141*4882a593Smuzhiyun 
142*4882a593Smuzhiyun /* write tlv_ext at dst and return next tlv ptr */
143*4882a593Smuzhiyun uint8 *bcm_write_tlv_ext(uint8 type, uint8 ext, const void *data, uint8 datalen, uint8 *dst);
144*4882a593Smuzhiyun 
145*4882a593Smuzhiyun /* write tlv at dst if space permits and return next tlv ptr */
146*4882a593Smuzhiyun uint8 *bcm_write_tlv_safe(int type, const void *data, uint datalen, uint8 *dst,
147*4882a593Smuzhiyun 	uint dst_maxlen);
148*4882a593Smuzhiyun 
149*4882a593Smuzhiyun /* copy a tlv  and return next tlv ptr */
150*4882a593Smuzhiyun uint8 *bcm_copy_tlv(const void *src, uint8 *dst);
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun /* copy a tlv if space permits and return next tlv ptr */
153*4882a593Smuzhiyun uint8 *bcm_copy_tlv_safe(const void *src, uint8 *dst, uint dst_maxlen);
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun /* end tlvs */
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun /* begin xtlv - used for iovars, nan attributes etc. */
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun /* bcm type(id), length, value with w/16 bit id/len. The structure below
160*4882a593Smuzhiyun  * is nominal, and is used to support variable length id and type. See
161*4882a593Smuzhiyun  * xtlv options below.
162*4882a593Smuzhiyun  */
163*4882a593Smuzhiyun typedef struct bcm_xtlv {
164*4882a593Smuzhiyun 	uint16	id;
165*4882a593Smuzhiyun 	uint16	len;
166*4882a593Smuzhiyun 	uint8	data[1];
167*4882a593Smuzhiyun } bcm_xtlv_t;
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun /* xtlv options */
170*4882a593Smuzhiyun #define BCM_XTLV_OPTION_NONE	0x0000u
171*4882a593Smuzhiyun #define BCM_XTLV_OPTION_ALIGN32	0x0001u /* 32bit alignment of type.len.data */
172*4882a593Smuzhiyun #define BCM_XTLV_OPTION_IDU8	0x0002u /* shorter id */
173*4882a593Smuzhiyun #define BCM_XTLV_OPTION_LENU8	0x0004u /* shorted length */
174*4882a593Smuzhiyun #define BCM_XTLV_OPTION_IDBE	0x0008u /* big endian format id */
175*4882a593Smuzhiyun #define BCM_XTLV_OPTION_LENBE	0x0010u /* big endian format length */
176*4882a593Smuzhiyun typedef uint16 bcm_xtlv_opts_t;
177*4882a593Smuzhiyun 
178*4882a593Smuzhiyun /* header size. depends on options. Macros names ending w/ _EX are where
179*4882a593Smuzhiyun  * options are explcitly specified that may be less common. The ones
180*4882a593Smuzhiyun  * without use default values that correspond to ...OPTION_NONE
181*4882a593Smuzhiyun  */
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun /* xtlv header size depends on options */
184*4882a593Smuzhiyun #define BCM_XTLV_HDR_SIZE 4u
185*4882a593Smuzhiyun #define BCM_XTLV_HDR_SIZE_EX(_opts) bcm_xtlv_hdr_size(_opts)
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun /* note: xtlv len only stores the value's length without padding */
188*4882a593Smuzhiyun #define BCM_XTLV_LEN(_elt) ltoh16_ua(&(_elt)->len)
189*4882a593Smuzhiyun #define BCM_XTLV_LEN_EX(_elt, _opts) bcm_xtlv_len(_elt, _opts)
190*4882a593Smuzhiyun 
191*4882a593Smuzhiyun #define BCM_XTLV_ID(_elt) ltoh16_ua(&(_elt)->id)
192*4882a593Smuzhiyun #define BCM_XTLV_ID_EX(_elt, _opts) bcm_xtlv_id(_elt, _opts)
193*4882a593Smuzhiyun 
194*4882a593Smuzhiyun /* entire size of the XTLV including header, data, and optional padding */
195*4882a593Smuzhiyun #define BCM_XTLV_SIZE(elt, opts) bcm_xtlv_size(elt, opts)
196*4882a593Smuzhiyun #define BCM_XTLV_SIZE_EX(_elt, _opts) bcm_xtlv_size(_elt, _opts)
197*4882a593Smuzhiyun 
198*4882a593Smuzhiyun /* max xtlv data size */
199*4882a593Smuzhiyun #define BCM_XTLV_MAX_DATA_SIZE 65535u
200*4882a593Smuzhiyun #define BCM_XTLV_MAX_DATA_SIZE_EX(_opts) ((_opts & BCM_XTLV_OPTION_LENU8) ? \
201*4882a593Smuzhiyun 	255u : 65535u)
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun /* descriptor of xtlv data, packing(src) and unpacking(dst) support  */
204*4882a593Smuzhiyun typedef struct {
205*4882a593Smuzhiyun 	uint16	type;
206*4882a593Smuzhiyun 	uint16	len;
207*4882a593Smuzhiyun 	void	*ptr; /* ptr to memory location */
208*4882a593Smuzhiyun } xtlv_desc_t;
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun /* xtlv buffer - packing/unpacking support */
211*4882a593Smuzhiyun struct bcm_xtlvbuf {
212*4882a593Smuzhiyun 	bcm_xtlv_opts_t opts;
213*4882a593Smuzhiyun 	uint16 size;
214*4882a593Smuzhiyun 	uint8 *head; /* point to head of buffer */
215*4882a593Smuzhiyun 	uint8 *buf; /* current position of buffer */
216*4882a593Smuzhiyun 	/* allocated buffer may follow, but not necessarily */
217*4882a593Smuzhiyun };
218*4882a593Smuzhiyun typedef struct bcm_xtlvbuf bcm_xtlvbuf_t;
219*4882a593Smuzhiyun 
220*4882a593Smuzhiyun /* valid xtlv ? */
221*4882a593Smuzhiyun bool bcm_valid_xtlv(const bcm_xtlv_t *elt, int buf_len, bcm_xtlv_opts_t opts);
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun /* return the next xtlv element, and update buffer len (remaining). Buffer length
224*4882a593Smuzhiyun  * updated includes padding as specified by options
225*4882a593Smuzhiyun  */
226*4882a593Smuzhiyun bcm_xtlv_t *bcm_next_xtlv(const bcm_xtlv_t *elt, int *buf_len, bcm_xtlv_opts_t opts);
227*4882a593Smuzhiyun 
228*4882a593Smuzhiyun /* initialize an xtlv buffer. Use options specified for packing/unpacking using
229*4882a593Smuzhiyun  * the buffer. Caller is responsible for allocating both buffers.
230*4882a593Smuzhiyun  */
231*4882a593Smuzhiyun int bcm_xtlv_buf_init(bcm_xtlvbuf_t *tlv_buf, uint8 *buf, uint16 len,
232*4882a593Smuzhiyun 	bcm_xtlv_opts_t opts);
233*4882a593Smuzhiyun 
234*4882a593Smuzhiyun /* length of data in the xtlv buffer */
235*4882a593Smuzhiyun uint16 bcm_xtlv_buf_len(struct bcm_xtlvbuf *tbuf);
236*4882a593Smuzhiyun 
237*4882a593Smuzhiyun /* remaining space in the xtlv buffer */
238*4882a593Smuzhiyun uint16 bcm_xtlv_buf_rlen(struct bcm_xtlvbuf *tbuf);
239*4882a593Smuzhiyun 
240*4882a593Smuzhiyun /* write ptr */
241*4882a593Smuzhiyun uint8 *bcm_xtlv_buf(struct bcm_xtlvbuf *tbuf);
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun /* head */
244*4882a593Smuzhiyun uint8 *bcm_xtlv_head(struct bcm_xtlvbuf *tbuf);
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun /* put a data buffer into xtlv */
247*4882a593Smuzhiyun int bcm_xtlv_put_data(bcm_xtlvbuf_t *tbuf, uint16 type, const uint8 *data, int n);
248*4882a593Smuzhiyun 
249*4882a593Smuzhiyun /* put one or more u16 elts into xtlv */
250*4882a593Smuzhiyun int bcm_xtlv_put16(bcm_xtlvbuf_t *tbuf, uint16 type, const uint16 *data, int n);
251*4882a593Smuzhiyun 
252*4882a593Smuzhiyun /* put one or more u32 elts into xtlv */
253*4882a593Smuzhiyun int bcm_xtlv_put32(bcm_xtlvbuf_t *tbuf, uint16 type, const uint32 *data, int n);
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun /* put one or more u64 elts into xtlv */
256*4882a593Smuzhiyun int bcm_xtlv_put64(bcm_xtlvbuf_t *tbuf, uint16 type, const uint64 *data, int n);
257*4882a593Smuzhiyun 
258*4882a593Smuzhiyun /* note: there are no get equivalent of integer unpacking, becasuse bcmendian.h
259*4882a593Smuzhiyun  * can be used directly using pointers returned in the buffer being processed.
260*4882a593Smuzhiyun  */
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun /* unpack a single xtlv entry, advances buffer and copies data to dst_data on match
263*4882a593Smuzhiyun  * type and length match must be exact
264*4882a593Smuzhiyun  */
265*4882a593Smuzhiyun int bcm_unpack_xtlv_entry(const uint8 **buf, uint16 expected_type, uint16 expected_len,
266*4882a593Smuzhiyun 	uint8 *dst_data, bcm_xtlv_opts_t opts);
267*4882a593Smuzhiyun 
268*4882a593Smuzhiyun /* packs an xtlv into buffer, and advances buffer, decreements buffer length.
269*4882a593Smuzhiyun  * buffer length is checked and must be >= size of xtlv - otherwise BCME_BADLEN
270*4882a593Smuzhiyun  */
271*4882a593Smuzhiyun int bcm_pack_xtlv_entry(uint8 **buf, uint16 *buflen, uint16 type, uint16 len,
272*4882a593Smuzhiyun 	const uint8 *src_data, bcm_xtlv_opts_t opts);
273*4882a593Smuzhiyun 
274*4882a593Smuzhiyun /* accessors and lengths for element given options */
275*4882a593Smuzhiyun int bcm_xtlv_size(const bcm_xtlv_t *elt, bcm_xtlv_opts_t opts);
276*4882a593Smuzhiyun int bcm_xtlv_hdr_size(bcm_xtlv_opts_t opts);
277*4882a593Smuzhiyun int bcm_xtlv_len(const bcm_xtlv_t *elt, bcm_xtlv_opts_t opts);
278*4882a593Smuzhiyun int bcm_xtlv_id(const bcm_xtlv_t *elt, bcm_xtlv_opts_t opts);
279*4882a593Smuzhiyun int bcm_xtlv_size_for_data(int dlen, bcm_xtlv_opts_t opts);
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun /* compute size needed for number of tlvs whose total data len is given */
282*4882a593Smuzhiyun #define BCM_XTLV_SIZE_FOR_TLVS(_data_len, _num_tlvs, _opts) (\
283*4882a593Smuzhiyun 	bcm_xtlv_size_for_data(_data_len, _opts) + (\
284*4882a593Smuzhiyun 	(_num_tlvs) * BCM_XTLV_HDR_SIZE_EX(_opts)))
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun /* unsafe copy xtlv */
287*4882a593Smuzhiyun #define BCM_XTLV_BCOPY(_src, _dst, _opts) \
288*4882a593Smuzhiyun 	bcm_xtlv_bcopy(_src, _dst, BCM_XTLV_MAX_DATA_SIZE_EX(_opts), \
289*4882a593Smuzhiyun 		BCM_XTLV_MAX_DATA_SIZE_EX(_opts), _opts)
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun /* copy xtlv - note: src->dst bcopy order - to be compatible w/ tlv version */
292*4882a593Smuzhiyun bcm_xtlv_t* bcm_xtlv_bcopy(const bcm_xtlv_t *src, bcm_xtlv_t *dst,
293*4882a593Smuzhiyun 	int src_buf_len, int dst_buf_len, bcm_xtlv_opts_t opts);
294*4882a593Smuzhiyun 
295*4882a593Smuzhiyun /* callback for unpacking xtlv from a buffer into context. */
296*4882a593Smuzhiyun typedef int (bcm_xtlv_unpack_cbfn_t)(void *ctx, const uint8 *buf,
297*4882a593Smuzhiyun 	uint16 type, uint16 len);
298*4882a593Smuzhiyun 
299*4882a593Smuzhiyun /* unpack a tlv buffer using buffer, options, and callback */
300*4882a593Smuzhiyun int bcm_unpack_xtlv_buf(void *ctx, const uint8 *buf, uint16 buflen,
301*4882a593Smuzhiyun 	bcm_xtlv_opts_t opts, bcm_xtlv_unpack_cbfn_t *cbfn);
302*4882a593Smuzhiyun 
303*4882a593Smuzhiyun /* unpack a set of tlvs from the buffer using provided xtlv descriptors */
304*4882a593Smuzhiyun int bcm_unpack_xtlv_buf_to_mem(const uint8 *buf, int *buflen, xtlv_desc_t *items,
305*4882a593Smuzhiyun 	bcm_xtlv_opts_t opts);
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun /* pack a set of tlvs into buffer using provided xtlv descriptors */
308*4882a593Smuzhiyun int bcm_pack_xtlv_buf_from_mem(uint8 **buf, uint16 *buflen,
309*4882a593Smuzhiyun 	const xtlv_desc_t *items, bcm_xtlv_opts_t opts);
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun /* return data pointer and data length of a given id from xtlv buffer
312*4882a593Smuzhiyun  * data_len may be NULL
313*4882a593Smuzhiyun  */
314*4882a593Smuzhiyun const uint8* bcm_get_data_from_xtlv_buf(const uint8 *tlv_buf, uint16 buflen,
315*4882a593Smuzhiyun 	uint16 id, uint16 *datalen, bcm_xtlv_opts_t opts);
316*4882a593Smuzhiyun 
317*4882a593Smuzhiyun /* callback to return next tlv id and len to pack, if there is more tlvs to come and
318*4882a593Smuzhiyun  * options e.g. alignment
319*4882a593Smuzhiyun  */
320*4882a593Smuzhiyun typedef bool (*bcm_pack_xtlv_next_info_cbfn_t)(void *ctx, uint16 *tlv_id, uint16 *tlv_len);
321*4882a593Smuzhiyun 
322*4882a593Smuzhiyun /* callback to pack the tlv into length validated buffer */
323*4882a593Smuzhiyun typedef void (*bcm_pack_xtlv_pack_next_cbfn_t)(void *ctx,
324*4882a593Smuzhiyun 	uint16 tlv_id, uint16 tlv_len, uint8* buf);
325*4882a593Smuzhiyun 
326*4882a593Smuzhiyun /* pack a set of tlvs into buffer using get_next to interate */
327*4882a593Smuzhiyun int bcm_pack_xtlv_buf(void *ctx, uint8 *tlv_buf, uint16 buflen,
328*4882a593Smuzhiyun 	bcm_xtlv_opts_t opts, bcm_pack_xtlv_next_info_cbfn_t get_next,
329*4882a593Smuzhiyun 	bcm_pack_xtlv_pack_next_cbfn_t pack_next, int *outlen);
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun /* pack an xtlv. does not do any error checking. if data is not NULL
332*4882a593Smuzhiyun  * data of given length is copied  to buffer (xtlv)
333*4882a593Smuzhiyun  */
334*4882a593Smuzhiyun void bcm_xtlv_pack_xtlv(bcm_xtlv_t *xtlv, uint16 type, uint16 len,
335*4882a593Smuzhiyun 	const uint8 *data, bcm_xtlv_opts_t opts);
336*4882a593Smuzhiyun 
337*4882a593Smuzhiyun /* unpack an xtlv and return ptr to data, and data length */
338*4882a593Smuzhiyun void bcm_xtlv_unpack_xtlv(const bcm_xtlv_t *xtlv, uint16 *type, uint16 *len,
339*4882a593Smuzhiyun 	const uint8 **data, bcm_xtlv_opts_t opts);
340*4882a593Smuzhiyun 
341*4882a593Smuzhiyun /* end xtlvs */
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun /* length value pairs */
344*4882a593Smuzhiyun struct bcm_xlv {
345*4882a593Smuzhiyun 	uint16 len;
346*4882a593Smuzhiyun 	uint8 data[1];
347*4882a593Smuzhiyun };
348*4882a593Smuzhiyun typedef struct bcm_xlv bcm_xlv_t;
349*4882a593Smuzhiyun 
350*4882a593Smuzhiyun struct bcm_xlvp {
351*4882a593Smuzhiyun 	uint16 len;
352*4882a593Smuzhiyun 	uint8 *data;
353*4882a593Smuzhiyun };
354*4882a593Smuzhiyun typedef struct bcm_xlvp bcm_xlvp_t;
355*4882a593Smuzhiyun 
356*4882a593Smuzhiyun struct bcm_const_xlvp {
357*4882a593Smuzhiyun 	uint16 len;
358*4882a593Smuzhiyun 	const uint8 *data;
359*4882a593Smuzhiyun };
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun typedef struct bcm_const_xlvp bcm_const_xlvp_t;
362*4882a593Smuzhiyun 
363*4882a593Smuzhiyun struct bcm_const_ulvp {
364*4882a593Smuzhiyun 	uint32 len;
365*4882a593Smuzhiyun 	const uint8 *data;
366*4882a593Smuzhiyun };
367*4882a593Smuzhiyun 
368*4882a593Smuzhiyun typedef struct bcm_const_ulvp bcm_const_ulvp_t;
369*4882a593Smuzhiyun 
370*4882a593Smuzhiyun /* end length value pairs */
371*4882a593Smuzhiyun #ifdef __cplusplus
372*4882a593Smuzhiyun }
373*4882a593Smuzhiyun #endif /* __cplusplus */
374*4882a593Smuzhiyun 
375*4882a593Smuzhiyun #endif	/* _bcmtlv_h_ */
376