| /* |
| * 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; |
| } |