aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/otus/80211core/amsdu.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/otus/80211core/amsdu.c')
-rw-r--r--drivers/staging/otus/80211core/amsdu.c134
1 files changed, 134 insertions, 0 deletions
diff --git a/drivers/staging/otus/80211core/amsdu.c b/drivers/staging/otus/80211core/amsdu.c
new file mode 100644
index 000000000000..c9123d58b82f
--- /dev/null
+++ b/drivers/staging/otus/80211core/amsdu.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "cprecomp.h"
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfGetAmsduSubFrame */
+/* Get a subframe from a-MSDU. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* buf : A-MSDU frame buffer */
+/* offset : offset of subframe in the A-MSDU */
+/* */
+/* OUTPUTS */
+/* NULL or subframe */
+/* */
+/* AUTHOR */
+/* Stephen Chen Atheros Communications, INC. 2007.2 */
+/* */
+/************************************************************************/
+zbuf_t* zfGetAmsduSubFrame(zdev_t* dev, zbuf_t* buf, u16_t* offset)
+{
+ u16_t subframeLen;
+ u16_t amsduLen = zfwBufGetSize(dev, buf);
+ zbuf_t* newBuf;
+
+ ZM_PERFORMANCE_RX_AMSDU(dev, buf, amsduLen);
+
+ /* Verify A-MSDU length */
+ if (amsduLen < (*offset + 14))
+ {
+ return NULL;
+ }
+
+ /* Locate A-MSDU subframe by offset and verify subframe length */
+ subframeLen = (zmw_buf_readb(dev, buf, *offset + 12) << 8) +
+ zmw_buf_readb(dev, buf, *offset + 13);
+ if (subframeLen == 0)
+ {
+ return NULL;
+ }
+
+ /* Verify A-MSDU subframe length */
+ if ((*offset+14+subframeLen) <= amsduLen)
+ {
+ /* Allocate a new buffer */
+ if ((newBuf = zfwBufAllocate(dev, 24+2+subframeLen)) != NULL)
+ {
+#ifdef ZM_ENABLE_NATIVE_WIFI
+ /* Copy and convert subframe to wlan frame format */
+ /* SHALL NOT INCLUDE QOS and AMSDU header. Ray 20070807 For Vista */
+ zfRxBufferCopy(dev, newBuf, buf, 0, 0, 24);
+ zfRxBufferCopy(dev, newBuf, buf, 24, *offset+14, subframeLen);
+ zfwBufSetSize(dev, newBuf, 24+subframeLen);
+#else
+ /* Copy subframe to new buffer */
+ zfRxBufferCopy(dev, newBuf, buf, 0, *offset, 14+subframeLen);
+ zfwBufSetSize(dev, newBuf, 14+subframeLen);
+#endif
+ /* Update offset */
+ *offset += (((14+subframeLen)+3) & 0xfffc);
+
+ /* Return buffer pointer */
+ return newBuf;
+ }
+ }
+ return NULL;
+}
+
+
+/************************************************************************/
+/* */
+/* FUNCTION DESCRIPTION zfDeAmsdu */
+/* De-AMSDU. */
+/* */
+/* INPUTS */
+/* dev : device pointer */
+/* buf : A-MSDU frame buffer */
+/* vap : VAP port */
+/* */
+/* OUTPUTS */
+/* None */
+/* */
+/* AUTHOR */
+/* Stephen Chen Atheros Communications, INC. 2007.2 */
+/* */
+/************************************************************************/
+void zfDeAmsdu(zdev_t* dev, zbuf_t* buf, u16_t vap, u8_t encryMode)
+{
+ u16_t offset = ZM_SIZE_OF_WLAN_DATA_HEADER+ZM_SIZE_OF_QOS_CTRL;
+ zbuf_t* subframeBuf;
+ zmw_get_wlan_dev(dev);
+
+ ZM_BUFFER_TRACE(dev, buf)
+
+ if (encryMode == ZM_AES || encryMode == ZM_TKIP)
+ {
+ offset += (ZM_SIZE_OF_IV + ZM_SIZE_OF_EXT_IV);
+ }
+ else if (encryMode == ZM_WEP64 || encryMode == ZM_WEP128)
+ {
+ offset += ZM_SIZE_OF_IV;
+ }
+
+ /* Repeatly calling zfGetAmsduSubFrame() until NULL returned */
+ while ((subframeBuf = zfGetAmsduSubFrame(dev, buf, &offset)) != NULL)
+ {
+ wd->commTally.NotifyNDISRxFrmCnt++;
+ if (wd->zfcbRecvEth != NULL)
+ {
+ wd->zfcbRecvEth(dev, subframeBuf, (u8_t)vap);
+ ZM_PERFORMANCE_RX_MSDU(dev, wd->tick);
+ }
+ }
+ zfwBufFree(dev, buf, 0);
+
+ return;
+}