diff options
Diffstat (limited to 'drivers/staging/otus/80211core/amsdu.c')
-rw-r--r-- | drivers/staging/otus/80211core/amsdu.c | 134 |
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; +} |