From cde9070d9970eef1f7ec2360586c802a16230ad8 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Fri, 10 May 2024 07:43:50 +0000
Subject: [PATCH] rtl88x2CE_WiFi_linux driver

---
 kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/bcmxtlv.c |  494 ++++++++++++++++++++++++++++++++++++------------------
 1 files changed, 328 insertions(+), 166 deletions(-)

diff --git a/kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/bcmxtlv.c b/kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/bcmxtlv.c
index f300cb1..4fe00a8 100644
--- a/kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/bcmxtlv.c
+++ b/kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/bcmxtlv.c
@@ -1,15 +1,16 @@
-/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Driver O/S-independent utility routines
  *
- * Copyright (C) 1999-2019, Broadcom Corporation
- * 
+ * Portions of this code are copyright (c) 2022 Cypress Semiconductor Corporation
+ *
+ * Copyright (C) 1999-2017, Broadcom Corporation
+ *
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
  * under the terms of the GNU General Public License version 2 (the "GPL"),
  * available at http://www.broadcom.com/licenses/GPLv2.php, with the
  * following added to such license:
- * 
+ *
  *      As a special exception, the copyright holders of this software give you
  * permission to link this software with independent modules, and to copy and
  * distribute the resulting executable under terms of your choice, provided that
@@ -17,7 +18,7 @@
  * the license of that module.  An independent module is a module which is not
  * derived from this software.  The special exception does not apply to any
  * modifications of the software.
- * 
+ *
  *      Notwithstanding the above, under no circumstances may you combine this
  * software in any way with any other Broadcom software provided under a license
  * other than the GPL, without Broadcom's express prior written consent.
@@ -25,7 +26,7 @@
  *
  * <<Broadcom-WL-IPTag/Open:>>
  *
- * $Id: bcmxtlv.c 603083 2015-11-30 23:40:43Z $
+ * $Id: bcmxtlv.c 700655 2017-05-20 06:09:06Z $
  */
 
 #include <bcm_cfg.h>
@@ -38,40 +39,110 @@
 #ifdef BCMDRIVER
 #include <osl.h>
 #else /* !BCMDRIVER */
-	#include <stdlib.h> /* AS!!! */
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
 #ifndef ASSERT
 #define ASSERT(exp)
-#endif
-INLINE void* MALLOCZ(void *o, size_t s) { BCM_REFERENCE(o); return calloc(1, s); }
-INLINE void MFREE(void *o, void *p, size_t s) { BCM_REFERENCE(o); BCM_REFERENCE(s); free(p); }
+#endif // endif
 #endif /* !BCMDRIVER */
 
+#include <bcmtlv.h>
 #include <bcmendian.h>
 #include <bcmutils.h>
 
-static INLINE int bcm_xtlv_size_for_data(int dlen, bcm_xtlv_opts_t opts)
+int
+bcm_xtlv_hdr_size(bcm_xtlv_opts_t opts)
 {
-	return ((opts & BCM_XTLV_OPTION_ALIGN32) ? ALIGN_SIZE(dlen + BCM_XTLV_HDR_SIZE, 4)
-		: (dlen + BCM_XTLV_HDR_SIZE));
+	int len = (int)OFFSETOF(bcm_xtlv_t, data); /* nominal */
+	if (opts & BCM_XTLV_OPTION_LENU8) --len;
+	if (opts & BCM_XTLV_OPTION_IDU8) --len;
+
+	return len;
+}
+
+bool
+bcm_valid_xtlv(const bcm_xtlv_t *elt, int buf_len, bcm_xtlv_opts_t opts)
+{
+	return elt != NULL &&
+		buf_len >= bcm_xtlv_hdr_size(opts) &&
+		buf_len  >= bcm_xtlv_size(elt, opts);
+}
+
+int
+bcm_xtlv_size_for_data(int dlen, bcm_xtlv_opts_t opts)
+{
+	int hsz;
+
+	hsz = bcm_xtlv_hdr_size(opts);
+	return ((opts & BCM_XTLV_OPTION_ALIGN32) ? ALIGN_SIZE(dlen + hsz, 4)
+		: (dlen + hsz));
+}
+
+int
+bcm_xtlv_size(const bcm_xtlv_t *elt, bcm_xtlv_opts_t opts)
+{
+	int size;	/* size including header, data, and any pad */
+	int len;	/* length wthout padding */
+
+	len = BCM_XTLV_LEN_EX(elt, opts);
+	size = bcm_xtlv_size_for_data(len, opts);
+	return size;
+}
+
+int
+bcm_xtlv_len(const bcm_xtlv_t *elt, bcm_xtlv_opts_t opts)
+{
+	const uint8 *lenp;
+	int len;
+
+	lenp = (const uint8 *)&elt->len; /* nominal */
+	if (opts & BCM_XTLV_OPTION_IDU8) {
+		--lenp;
+	}
+
+	if (opts & BCM_XTLV_OPTION_LENU8) {
+		len = *lenp;
+	} else if (opts & BCM_XTLV_OPTION_LENBE) {
+		len = (uint32)hton16(elt->len);
+	} else {
+		len = ltoh16_ua(lenp);
+	}
+
+	return len;
+}
+
+int
+bcm_xtlv_id(const bcm_xtlv_t *elt, bcm_xtlv_opts_t opts)
+{
+	int id = 0;
+	if (opts & BCM_XTLV_OPTION_IDU8) {
+		id =  *(const uint8 *)elt;
+	} else if (opts & BCM_XTLV_OPTION_IDBE) {
+		id = (uint32)hton16(elt->id);
+	} else {
+		id = ltoh16_ua((const uint8 *)elt);
+	}
+
+	return id;
 }
 
 bcm_xtlv_t *
-bcm_next_xtlv(bcm_xtlv_t *elt, int *buflen, bcm_xtlv_opts_t opts)
+bcm_next_xtlv(const bcm_xtlv_t *elt, int *buflen, bcm_xtlv_opts_t opts)
 {
 	int sz;
 	/* advance to next elt */
-	sz = BCM_XTLV_SIZE(elt, opts);
-	elt = (bcm_xtlv_t*)((uint8 *)elt + sz);
+	sz = BCM_XTLV_SIZE_EX(elt, opts);
+	elt = (const bcm_xtlv_t*)((const uint8 *)elt + sz);
 	*buflen -= sz;
 
 	/* validate next elt */
 	if (!bcm_valid_xtlv(elt, *buflen, opts))
 		return NULL;
 
-	return elt;
+	GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
+	return (bcm_xtlv_t *)(elt);
+	GCC_DIAGNOSTIC_POP();
 }
 
 int
@@ -90,99 +161,191 @@
 uint16
 bcm_xtlv_buf_len(bcm_xtlvbuf_t *tbuf)
 {
-	if (tbuf == NULL) return 0;
-	return (uint16)(tbuf->buf - tbuf->head);
+	uint16 len;
+
+	if (tbuf)
+		len = (uint16)(tbuf->buf - tbuf->head);
+	else
+		len = 0;
+
+	return len;
 }
+
 uint16
 bcm_xtlv_buf_rlen(bcm_xtlvbuf_t *tbuf)
 {
-	if (tbuf == NULL) return 0;
-	return tbuf->size - bcm_xtlv_buf_len(tbuf);
+	uint16 rlen;
+	if (tbuf)
+		rlen = tbuf->size - bcm_xtlv_buf_len(tbuf);
+	else
+		rlen = 0;
+
+	return rlen;
 }
+
 uint8 *
 bcm_xtlv_buf(bcm_xtlvbuf_t *tbuf)
 {
-	if (tbuf == NULL) return NULL;
-	return tbuf->buf;
+	return tbuf ? tbuf->buf : NULL;
 }
+
 uint8 *
 bcm_xtlv_head(bcm_xtlvbuf_t *tbuf)
 {
-	if (tbuf == NULL) return NULL;
-	return tbuf->head;
+	return tbuf ? tbuf->head : NULL;
 }
+
+void
+bcm_xtlv_pack_xtlv(bcm_xtlv_t *xtlv, uint16 type, uint16 len, const uint8 *data,
+	bcm_xtlv_opts_t opts)
+{
+	uint8 *data_buf;
+	bcm_xtlv_opts_t mask = BCM_XTLV_OPTION_IDU8 | BCM_XTLV_OPTION_LENU8;
+
+	if (!(opts & mask)) {		/* default */
+		uint8 *idp = (uint8 *)xtlv;
+		uint8 *lenp = idp + sizeof(xtlv->id);
+		htol16_ua_store(type, idp);
+		htol16_ua_store(len, lenp);
+		data_buf = lenp + sizeof(uint16);
+	} else if ((opts & mask) == mask) { /* u8 id and u8 len */
+		uint8 *idp = (uint8 *)xtlv;
+		uint8 *lenp = idp + 1;
+		*idp = (uint8)type;
+		*lenp = (uint8)len;
+		data_buf = lenp + sizeof(uint8);
+	} else if (opts & BCM_XTLV_OPTION_IDU8) { /* u8 id, u16 len */
+		uint8 *idp = (uint8 *)xtlv;
+		uint8 *lenp = idp + 1;
+		*idp = (uint8)type;
+		htol16_ua_store(len, lenp);
+		data_buf = lenp + sizeof(uint16);
+	} else if (opts & BCM_XTLV_OPTION_LENU8) { /* u16 id, u8 len */
+		uint8 *idp = (uint8 *)xtlv;
+		uint8 *lenp = idp + sizeof(uint16);
+		htol16_ua_store(type, idp);
+		*lenp = (uint8)len;
+		data_buf = lenp + sizeof(uint8);
+	} else {
+		bool Unexpected_xtlv_option = TRUE;
+		BCM_REFERENCE(Unexpected_xtlv_option);
+		ASSERT(!Unexpected_xtlv_option);
+		return;
+	}
+
+	if (opts & BCM_XTLV_OPTION_LENU8) {
+		ASSERT(len <= 0x00ff);
+		len &= 0xff;
+	}
+
+	if (data != NULL)
+		memcpy(data_buf, data, len);
+}
+
+/* xtlv header is always packed in LE order */
+void
+bcm_xtlv_unpack_xtlv(const bcm_xtlv_t *xtlv, uint16 *type, uint16 *len,
+	const uint8 **data, bcm_xtlv_opts_t opts)
+{
+	if (type)
+		*type = (uint16)bcm_xtlv_id(xtlv, opts);
+	if (len)
+		*len = (uint16)bcm_xtlv_len(xtlv, opts);
+	if (data)
+		*data = (const uint8 *)xtlv + BCM_XTLV_HDR_SIZE_EX(opts);
+}
+
 int
-bcm_xtlv_put_data(bcm_xtlvbuf_t *tbuf, uint16 type, const void *data, uint16 dlen)
+bcm_xtlv_put_data(bcm_xtlvbuf_t *tbuf, uint16 type, const uint8 *data, int n)
 {
 	bcm_xtlv_t *xtlv;
 	int size;
 
 	if (tbuf == NULL)
 		return BCME_BADARG;
-	size = bcm_xtlv_size_for_data(dlen, tbuf->opts);
+
+	size = bcm_xtlv_size_for_data(n, tbuf->opts);
 	if (bcm_xtlv_buf_rlen(tbuf) < size)
 		return BCME_NOMEM;
+
 	xtlv = (bcm_xtlv_t *)bcm_xtlv_buf(tbuf);
-	xtlv->id = htol16(type);
-	xtlv->len = htol16(dlen);
-	memcpy(xtlv->data, data, dlen);
-	tbuf->buf += size;
+	bcm_xtlv_pack_xtlv(xtlv, type, (uint16)n, data, tbuf->opts);
+	tbuf->buf += size; /* note: data may be NULL, reserves space */
 	return BCME_OK;
 }
-int
-bcm_xtlv_put_8(bcm_xtlvbuf_t *tbuf, uint16 type, const int8 data)
+
+static int
+bcm_xtlv_put_int(bcm_xtlvbuf_t *tbuf, uint16 type, const uint8 *data, int n, int int_sz)
 {
 	bcm_xtlv_t *xtlv;
-	int size;
+	int xtlv_len;
+	uint8 *xtlv_data;
+	int err = BCME_OK;
 
-	if (tbuf == NULL)
-		return BCME_BADARG;
-	size = bcm_xtlv_size_for_data(1, tbuf->opts);
-	if (bcm_xtlv_buf_rlen(tbuf) < size)
-		return BCME_NOMEM;
+	if (tbuf == NULL) {
+		err = BCME_BADARG;
+		goto done;
+	}
+
 	xtlv = (bcm_xtlv_t *)bcm_xtlv_buf(tbuf);
-	xtlv->id = htol16(type);
-	xtlv->len = htol16(sizeof(data));
-	xtlv->data[0] = data;
-	tbuf->buf += size;
-	return BCME_OK;
+
+	/* put type and length in xtlv and reserve data space */
+	xtlv_len = n * int_sz;
+	err = bcm_xtlv_put_data(tbuf, type, NULL, xtlv_len);
+	if (err != BCME_OK)
+		goto done;
+
+	xtlv_data = (uint8 *)xtlv + bcm_xtlv_hdr_size(tbuf->opts);
+
+	/* write data w/ little-endianness into buffer - single loop, aligned access */
+	for (; n != 0; --n, xtlv_data += int_sz, data += int_sz) {
+		switch (int_sz) {
+		case sizeof(uint8):
+			break;
+		case sizeof(uint16):
+			{
+				uint16 v =  load16_ua(data);
+				htol16_ua_store(v, xtlv_data);
+				break;
+			}
+		case sizeof(uint32):
+			{
+				uint32 v = load32_ua(data);
+				htol32_ua_store(v, xtlv_data);
+				break;
+			}
+		case sizeof(uint64):
+			{
+				uint64 v = load64_ua(data);
+				htol64_ua_store(v, xtlv_data);
+				break;
+			}
+		default:
+			err = BCME_UNSUPPORTED;
+			goto done;
+		}
+	}
+
+done:
+	return err;
 }
+
 int
-bcm_xtlv_put_16(bcm_xtlvbuf_t *tbuf, uint16 type, const int16 data)
+bcm_xtlv_put16(bcm_xtlvbuf_t *tbuf, uint16 type, const uint16 *data, int n)
 {
-	bcm_xtlv_t *xtlv;
-	int size;
-
-	if (tbuf == NULL)
-		return BCME_BADARG;
-	size = bcm_xtlv_size_for_data(2, tbuf->opts);
-	if (bcm_xtlv_buf_rlen(tbuf) < size)
-		return BCME_NOMEM;
-
-	xtlv = (bcm_xtlv_t *)bcm_xtlv_buf(tbuf);
-	xtlv->id = htol16(type);
-	xtlv->len = htol16(sizeof(data));
-	htol16_ua_store(data, xtlv->data);
-	tbuf->buf += size;
-	return BCME_OK;
+	return bcm_xtlv_put_int(tbuf, type, (const uint8 *)data, n, sizeof(uint16));
 }
-int
-bcm_xtlv_put_32(bcm_xtlvbuf_t *tbuf, uint16 type, const int32 data)
-{
-	bcm_xtlv_t *xtlv;
-	int size;
 
-	if (tbuf == NULL)
-		return BCME_BADARG;
-	size = bcm_xtlv_size_for_data(4, tbuf->opts);
-	if (bcm_xtlv_buf_rlen(tbuf) < size)
-		return BCME_NOMEM;
-	xtlv = (bcm_xtlv_t *)bcm_xtlv_buf(tbuf);
-	xtlv->id = htol16(type);
-	xtlv->len = htol16(sizeof(data));
-	htol32_ua_store(data, xtlv->data);
-	tbuf->buf += size;
-	return BCME_OK;
+int
+bcm_xtlv_put32(bcm_xtlvbuf_t *tbuf, uint16 type, const uint32 *data, int n)
+{
+	return bcm_xtlv_put_int(tbuf, type, (const uint8 *)data, n, sizeof(uint32));
+}
+
+int
+bcm_xtlv_put64(bcm_xtlvbuf_t *tbuf, uint16 type, const uint64 *data, int n)
+{
+	return bcm_xtlv_put_int(tbuf, type, (const uint8 *)data, n, sizeof(uint64));
 }
 
 /*
@@ -192,65 +355,51 @@
  *  caller's resposible for dst space check
  */
 int
-bcm_unpack_xtlv_entry(uint8 **tlv_buf, uint16 xpct_type, uint16 xpct_len, void *dst,
-	bcm_xtlv_opts_t opts)
+bcm_unpack_xtlv_entry(const uint8 **tlv_buf, uint16 xpct_type, uint16 xpct_len,
+	uint8 *dst_data, bcm_xtlv_opts_t opts)
 {
-	bcm_xtlv_t *ptlv = (bcm_xtlv_t *)*tlv_buf;
+	const bcm_xtlv_t *ptlv = (const bcm_xtlv_t *)*tlv_buf;
 	uint16 len;
 	uint16 type;
+	const uint8 *data;
 
 	ASSERT(ptlv);
-	/* tlv headr is always packed in LE order */
-	len = ltoh16(ptlv->len);
-	type = ltoh16(ptlv->id);
-	if	(len == 0) {
-		/* z-len tlv headers: allow, but don't process */
-		printf("z-len, skip unpack\n");
-	} else  {
-		if ((type != xpct_type) ||
-			(len > xpct_len)) {
-			printf("xtlv_unpack Error: found[type:%d,len:%d] != xpct[type:%d,len:%d]\n",
-				type, len, xpct_type, xpct_len);
+
+	bcm_xtlv_unpack_xtlv(ptlv, &type, &len, &data, opts);
+	if (len) {
+		if ((type != xpct_type) || (len > xpct_len))
 			return BCME_BADARG;
-		}
-		/* copy tlv record to caller's buffer */
-		memcpy(dst, ptlv->data, ptlv->len);
+		if (dst_data && data)
+			memcpy(dst_data, data, len); /* copy data to dst */
 	}
-	*tlv_buf += BCM_XTLV_SIZE(ptlv, opts);
+
+	*tlv_buf += BCM_XTLV_SIZE_EX(ptlv, opts);
 	return BCME_OK;
 }
 
 /*
- *  packs user data into tlv record
- *  advances tlv pointer to next xtlv slot
+ *  packs user data into tlv record and advances tlv pointer to next xtlv slot
  *  buflen is used for tlv_buf space check
  */
 int
-bcm_pack_xtlv_entry(uint8 **tlv_buf, uint16 *buflen, uint16 type, uint16 len, void *src,
-	bcm_xtlv_opts_t opts)
+bcm_pack_xtlv_entry(uint8 **tlv_buf, uint16 *buflen, uint16 type, uint16 len,
+	const uint8 *src_data, bcm_xtlv_opts_t opts)
 {
 	bcm_xtlv_t *ptlv = (bcm_xtlv_t *)*tlv_buf;
 	int size;
 
 	ASSERT(ptlv);
-	ASSERT(src);
 
 	size = bcm_xtlv_size_for_data(len, opts);
 
 	/* copy data from tlv buffer to dst provided by user */
-	if (size > *buflen) {
-		printf("bcm_pack_xtlv_entry: no space tlv_buf: requested:%d, available:%d\n",
-			size, *buflen);
+	if (size > *buflen)
 		return BCME_BADLEN;
-	}
-	ptlv->id = htol16(type);
-	ptlv->len = htol16(len);
 
-	/* copy callers data */
-	memcpy(ptlv->data, src, len);
+	bcm_xtlv_pack_xtlv(ptlv, type, len, src_data, opts);
 
 	/* advance callers pointer to tlv buff */
-	*tlv_buf += size;
+	*tlv_buf = (uint8*)(*tlv_buf) + size;
 	/* decrement the len */
 	*buflen -= (uint16)size;
 	return BCME_OK;
@@ -261,34 +410,33 @@
  *  to set function one call per found tlv record
  */
 int
-bcm_unpack_xtlv_buf(void *ctx, uint8 *tlv_buf, uint16 buflen, bcm_xtlv_opts_t opts,
+bcm_unpack_xtlv_buf(void *ctx, const uint8 *tlv_buf, uint16 buflen, bcm_xtlv_opts_t opts,
 	bcm_xtlv_unpack_cbfn_t *cbfn)
 {
 	uint16 len;
 	uint16 type;
 	int res = BCME_OK;
 	int size;
-	bcm_xtlv_t *ptlv;
+	const bcm_xtlv_t *ptlv;
 	int sbuflen = buflen;
+	const uint8 *data;
+	int hdr_size;
 
 	ASSERT(!buflen || tlv_buf);
 	ASSERT(!buflen || cbfn);
 
-	while (sbuflen >= (int)BCM_XTLV_HDR_SIZE) {
-		ptlv = (bcm_xtlv_t *)tlv_buf;
+	hdr_size = BCM_XTLV_HDR_SIZE_EX(opts);
+	while (sbuflen >= hdr_size) {
+		ptlv = (const bcm_xtlv_t *)tlv_buf;
 
-		/* tlv header is always packed in LE order */
-		len = ltoh16(ptlv->len);
-		type = ltoh16(ptlv->id);
-
+		bcm_xtlv_unpack_xtlv(ptlv, &type, &len, &data, opts);
 		size = bcm_xtlv_size_for_data(len, opts);
 
 		sbuflen -= size;
-		/* check for possible buffer overrun */
-		if (sbuflen < 0)
+		if (sbuflen < 0) /* check for buffer overrun */
 			break;
 
-		if ((res = cbfn(ctx, ptlv->data, type, len)) != BCME_OK)
+		if ((res = cbfn(ctx, data, type, len)) != BCME_OK)
 			break;
 		tlv_buf += size;
 	}
@@ -296,7 +444,7 @@
 }
 
 int
-bcm_pack_xtlv_buf(void *ctx, void *tlv_buf, uint16 buflen, bcm_xtlv_opts_t opts,
+bcm_pack_xtlv_buf(void *ctx, uint8 *tlv_buf, uint16 buflen, bcm_xtlv_opts_t opts,
 	bcm_pack_xtlv_next_info_cbfn_t get_next, bcm_pack_xtlv_pack_next_cbfn_t pack_next,
 	int *outlen)
 {
@@ -308,24 +456,26 @@
 	uint8 *buf;
 	bool more;
 	int size;
+	int hdr_size;
 
 	ASSERT(get_next && pack_next);
 
-	buf = (uint8 *)tlv_buf;
+	buf = tlv_buf;
 	startp = buf;
 	endp = (uint8 *)buf + buflen;
 	more = TRUE;
+	hdr_size = BCM_XTLV_HDR_SIZE_EX(opts);
+
 	while (more && (buf < endp)) {
 		more = get_next(ctx, &tlv_id, &tlv_len);
 		size = bcm_xtlv_size_for_data(tlv_len, opts);
-		if ((buf + size) >= endp) {
+		if ((buf + size) > endp) {
 			res = BCME_BUFTOOSHORT;
 			goto done;
 		}
 
-		htol16_ua_store(tlv_id, buf);
-		htol16_ua_store(tlv_len, buf + sizeof(tlv_id));
-		pack_next(ctx, tlv_id, tlv_len, buf + BCM_XTLV_HDR_SIZE);
+		bcm_xtlv_pack_xtlv((bcm_xtlv_t *)buf, tlv_id, tlv_len, NULL, opts);
+		pack_next(ctx, tlv_id, tlv_len, buf + hdr_size);
 		buf += size;
 	}
 
@@ -343,20 +493,22 @@
  *  pack xtlv buffer from memory according to xtlv_desc_t
  */
 int
-bcm_pack_xtlv_buf_from_mem(void **tlv_buf, uint16 *buflen, xtlv_desc_t *items,
+bcm_pack_xtlv_buf_from_mem(uint8 **tlv_buf, uint16 *buflen, const xtlv_desc_t *items,
 	bcm_xtlv_opts_t opts)
 {
 	int res = BCME_OK;
-	uint8 *ptlv = (uint8 *)*tlv_buf;
+	uint8 *ptlv = *tlv_buf;
 
 	while (items->type != 0) {
-		if ((res = bcm_pack_xtlv_entry(&ptlv,
-			buflen, items->type,
-			items->len, items->ptr, opts) != BCME_OK)) {
-			break;
+		if (items->len && items->ptr) {
+			res = bcm_pack_xtlv_entry(&ptlv, buflen, items->type,
+				items->len, items->ptr, opts);
+			if (res != BCME_OK)
+				break;
 		}
 		items++;
 	}
+
 	*tlv_buf = ptlv; /* update the external pointer */
 	return res;
 }
@@ -366,7 +518,8 @@
  *
  */
 int
-bcm_unpack_xtlv_buf_to_mem(void *tlv_buf, int *buflen, xtlv_desc_t *items, bcm_xtlv_opts_t opts)
+bcm_unpack_xtlv_buf_to_mem(uint8 *tlv_buf, int *buflen, xtlv_desc_t *items,
+	bcm_xtlv_opts_t opts)
 {
 	int res = BCME_OK;
 	bcm_xtlv_t *elt;
@@ -380,14 +533,16 @@
 	for (; elt != NULL && res == BCME_OK; elt = bcm_next_xtlv(elt, buflen, opts)) {
 		/*  find matches in desc_t items  */
 		xtlv_desc_t *dst_desc = items;
-		uint16 len = ltoh16(elt->len);
+		uint16 len, type;
+		const uint8 *data;
 
+		bcm_xtlv_unpack_xtlv(elt, &type, &len, &data, opts);
 		while (dst_desc->type != 0) {
-			if (ltoh16(elt->id) == dst_desc->type) {
+			if (type == dst_desc->type) {
 				if (len != dst_desc->len) {
 					res = BCME_BADLEN;
 				} else {
-					memcpy(dst_desc->ptr, elt->data, len);
+					memcpy(dst_desc->ptr, data, len);
 				}
 				break;
 			}
@@ -403,60 +558,67 @@
 
 /*
  * return data pointer of a given ID from xtlv buffer.
- * If the specified xTLV ID is found, on return *data_len_out will contain
+ * If the specified xTLV ID is found, on return *datalen will contain
  * the the data length of the xTLV ID.
  */
-void *
-bcm_get_data_from_xtlv_buf(uint8 *tlv_buf, uint16 buflen, uint16 id,
-	uint16 *datalen_out, bcm_xtlv_opts_t opts)
+const uint8*
+bcm_get_data_from_xtlv_buf(const uint8 *tlv_buf, uint16 buflen, uint16 id,
+	uint16 *datalen, bcm_xtlv_opts_t opts)
 {
-	void *retptr = NULL;
+	const uint8 *retptr = NULL;
 	uint16 type, len;
 	int size;
-	bcm_xtlv_t *ptlv;
+	const bcm_xtlv_t *ptlv;
 	int sbuflen = buflen;
+	const uint8 *data;
+	int hdr_size;
+
+	hdr_size = BCM_XTLV_HDR_SIZE_EX(opts);
 
 	/* Init the datalength */
-	if (datalen_out) {
-		*datalen_out = 0;
+	if (datalen) {
+		*datalen = 0;
 	}
-	while (sbuflen >= (int)BCM_XTLV_HDR_SIZE) {
-		ptlv = (bcm_xtlv_t *)tlv_buf;
+	while (sbuflen >= hdr_size) {
+		ptlv = (const bcm_xtlv_t *)tlv_buf;
+		bcm_xtlv_unpack_xtlv(ptlv, &type, &len, &data, opts);
 
-		/* tlv header is always packed in LE order */
-		type = ltoh16(ptlv->id);
-		len = ltoh16(ptlv->len);
 		size = bcm_xtlv_size_for_data(len, opts);
-
 		sbuflen -= size;
-		/* check for possible buffer overrun */
-		if (sbuflen < 0) {
-			printf("%s %d: Invalid sbuflen %d\n",
-				__FUNCTION__, __LINE__, sbuflen);
+		if (sbuflen < 0) /* buffer overrun? */
 			break;
-		}
 
 		if (id == type) {
-			retptr = ptlv->data;
-			if (datalen_out) {
-				*datalen_out = len;
-			}
+			retptr = data;
+			if (datalen)
+				*datalen = len;
 			break;
 		}
+
 		tlv_buf += size;
 	}
 
 	return retptr;
 }
 
-int bcm_xtlv_size(const bcm_xtlv_t *elt, bcm_xtlv_opts_t opts)
+bcm_xtlv_t*
+bcm_xtlv_bcopy(const bcm_xtlv_t *src, bcm_xtlv_t *dst,
+	int src_buf_len, int dst_buf_len, bcm_xtlv_opts_t opts)
 {
-	int size; /* entire size of the XTLV including header, data, and optional padding */
-	int len; /* XTLV's value real length wthout padding */
+	bcm_xtlv_t *dst_next = NULL;
+	src =  (src && bcm_valid_xtlv(src, src_buf_len, opts)) ? src : NULL;
+	if (src && dst) {
+		uint16 type;
+		uint16 len;
+		const uint8 *data;
+		int size;
+		bcm_xtlv_unpack_xtlv(src, &type, &len, &data, opts);
+		size = bcm_xtlv_size_for_data(len, opts);
+		if (size <= dst_buf_len) {
+			bcm_xtlv_pack_xtlv(dst, type, len, data, opts);
+			dst_next = (bcm_xtlv_t *)((uint8 *)dst + size);
+		}
+	}
 
-	len = BCM_XTLV_LEN(elt);
-
-	size = bcm_xtlv_size_for_data(len, opts);
-
-	return size;
+	return dst_next;
 }

--
Gitblit v1.6.2