2 * Copyright (c) 2007-2008 Atheros Communications Inc.
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 /************************************************************************/
22 /* FUNCTION DESCRIPTION zfGetAmsduSubFrame */
23 /* Get a subframe from a-MSDU. */
26 /* dev : device pointer */
27 /* buf : A-MSDU frame buffer */
28 /* offset : offset of subframe in the A-MSDU */
31 /* NULL or subframe */
34 /* Stephen Chen Atheros Communications, INC. 2007.2 */
36 /************************************************************************/
37 zbuf_t
* zfGetAmsduSubFrame(zdev_t
* dev
, zbuf_t
* buf
, u16_t
* offset
)
40 u16_t amsduLen
= zfwBufGetSize(dev
, buf
);
43 ZM_PERFORMANCE_RX_AMSDU(dev
, buf
, amsduLen
);
45 /* Verify A-MSDU length */
46 if (amsduLen
< (*offset
+ 14))
51 /* Locate A-MSDU subframe by offset and verify subframe length */
52 subframeLen
= (zmw_buf_readb(dev
, buf
, *offset
+ 12) << 8) +
53 zmw_buf_readb(dev
, buf
, *offset
+ 13);
59 /* Verify A-MSDU subframe length */
60 if ((*offset
+14+subframeLen
) <= amsduLen
)
62 /* Allocate a new buffer */
63 if ((newBuf
= zfwBufAllocate(dev
, 24+2+subframeLen
)) != NULL
)
65 #ifdef ZM_ENABLE_NATIVE_WIFI
66 /* Copy and convert subframe to wlan frame format */
67 /* SHALL NOT INCLUDE QOS and AMSDU header. Ray 20070807 For Vista */
68 zfRxBufferCopy(dev
, newBuf
, buf
, 0, 0, 24);
69 zfRxBufferCopy(dev
, newBuf
, buf
, 24, *offset
+14, subframeLen
);
70 zfwBufSetSize(dev
, newBuf
, 24+subframeLen
);
72 /* Copy subframe to new buffer */
73 zfRxBufferCopy(dev
, newBuf
, buf
, 0, *offset
, 14+subframeLen
);
74 zfwBufSetSize(dev
, newBuf
, 14+subframeLen
);
77 *offset
+= (((14+subframeLen
)+3) & 0xfffc);
79 /* Return buffer pointer */
87 /************************************************************************/
89 /* FUNCTION DESCRIPTION zfDeAmsdu */
93 /* dev : device pointer */
94 /* buf : A-MSDU frame buffer */
101 /* Stephen Chen Atheros Communications, INC. 2007.2 */
103 /************************************************************************/
104 void zfDeAmsdu(zdev_t
* dev
, zbuf_t
* buf
, u16_t vap
, u8_t encryMode
)
106 u16_t offset
= ZM_SIZE_OF_WLAN_DATA_HEADER
+ZM_SIZE_OF_QOS_CTRL
;
108 zmw_get_wlan_dev(dev
);
110 ZM_BUFFER_TRACE(dev
, buf
)
112 if (encryMode
== ZM_AES
|| encryMode
== ZM_TKIP
)
114 offset
+= (ZM_SIZE_OF_IV
+ ZM_SIZE_OF_EXT_IV
);
116 else if (encryMode
== ZM_WEP64
|| encryMode
== ZM_WEP128
)
118 offset
+= ZM_SIZE_OF_IV
;
121 /* Repeatly calling zfGetAmsduSubFrame() until NULL returned */
122 while ((subframeBuf
= zfGetAmsduSubFrame(dev
, buf
, &offset
)) != NULL
)
124 wd
->commTally
.NotifyNDISRxFrmCnt
++;
125 if (wd
->zfcbRecvEth
!= NULL
)
127 wd
->zfcbRecvEth(dev
, subframeBuf
, (u8_t
)vap
);
128 ZM_PERFORMANCE_RX_MSDU(dev
, wd
->tick
);
131 zfwBufFree(dev
, buf
, 0);