From 297b60346df8beafee954a0fd7c2d64f33f3b9bc Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Sat, 11 May 2024 01:44:05 +0000
Subject: [PATCH] rtl8211F_led_control
---
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