41d8532b5f
Signed-off-by: Dragoslav Zaric <dragoslav.zaric.kd@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
130 lines
5.3 KiB
C
130 lines
5.3 KiB
C
/*
|
|
* 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 */
|
|
newBuf = zfwBufAllocate(dev, 24+2+subframeLen);
|
|
if (newBuf != 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;
|
|
}
|