Commit | Line | Data |
---|---|---|
4bd43f50 LR |
1 | /* |
2 | * Copyright (c) 2007-2008 Atheros Communications Inc. | |
3 | * | |
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. | |
7 | * | |
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. | |
15 | */ | |
16 | ||
17 | #include "cprecomp.h" | |
18 | ||
19 | ||
20 | /************************************************************************/ | |
21 | /* */ | |
22 | /* FUNCTION DESCRIPTION zfGetAmsduSubFrame */ | |
23 | /* Get a subframe from a-MSDU. */ | |
24 | /* */ | |
25 | /* INPUTS */ | |
26 | /* dev : device pointer */ | |
27 | /* buf : A-MSDU frame buffer */ | |
28 | /* offset : offset of subframe in the A-MSDU */ | |
29 | /* */ | |
30 | /* OUTPUTS */ | |
31 | /* NULL or subframe */ | |
32 | /* */ | |
33 | /* AUTHOR */ | |
34 | /* Stephen Chen Atheros Communications, INC. 2007.2 */ | |
35 | /* */ | |
36 | /************************************************************************/ | |
41d8532b | 37 | zbuf_t *zfGetAmsduSubFrame(zdev_t *dev, zbuf_t *buf, u16_t *offset) |
4bd43f50 | 38 | { |
41d8532b DZ |
39 | u16_t subframeLen; |
40 | u16_t amsduLen = zfwBufGetSize(dev, buf); | |
41 | zbuf_t *newBuf; | |
42 | ||
43 | ZM_PERFORMANCE_RX_AMSDU(dev, buf, amsduLen); | |
44 | ||
45 | /* Verify A-MSDU length */ | |
46 | if (amsduLen < (*offset + 14)) | |
47 | return NULL; | |
48 | ||
49 | /* Locate A-MSDU subframe by offset and verify subframe length */ | |
50 | subframeLen = (zmw_buf_readb(dev, buf, *offset + 12) << 8) + | |
51 | zmw_buf_readb(dev, buf, *offset + 13); | |
52 | ||
53 | if (subframeLen == 0) | |
54 | return NULL; | |
55 | ||
56 | /* Verify A-MSDU subframe length */ | |
57 | if ((*offset+14+subframeLen) <= amsduLen) { | |
58 | /* Allocate a new buffer */ | |
59 | newBuf = zfwBufAllocate(dev, 24+2+subframeLen); | |
60 | if (newBuf != NULL) { | |
61 | #ifdef ZM_ENABLE_NATIVE_WIFI | |
62 | /* Copy and convert subframe to wlan frame format | |
63 | * SHALL NOT INCLUDE QOS and AMSDU header. | |
64 | * Ray 20070807 For Vista | |
65 | */ | |
66 | zfRxBufferCopy(dev, newBuf, buf, 0, 0, 24); | |
67 | zfRxBufferCopy(dev, newBuf, buf, 24, *offset+14, | |
68 | subframeLen); | |
69 | zfwBufSetSize(dev, newBuf, 24+subframeLen); | |
70 | #else | |
71 | /* Copy subframe to new buffer */ | |
72 | zfRxBufferCopy(dev, newBuf, buf, 0, *offset, | |
73 | 14+subframeLen); | |
74 | zfwBufSetSize(dev, newBuf, 14+subframeLen); | |
75 | #endif | |
76 | /* Update offset */ | |
77 | *offset += (((14+subframeLen)+3) & 0xfffc); | |
78 | ||
79 | /* Return buffer pointer */ | |
80 | return newBuf; | |
81 | } | |
82 | } | |
83 | return NULL; | |
4bd43f50 LR |
84 | } |
85 | ||
86 | ||
87 | /************************************************************************/ | |
88 | /* */ | |
89 | /* FUNCTION DESCRIPTION zfDeAmsdu */ | |
90 | /* De-AMSDU. */ | |
91 | /* */ | |
92 | /* INPUTS */ | |
93 | /* dev : device pointer */ | |
94 | /* buf : A-MSDU frame buffer */ | |
95 | /* vap : VAP port */ | |
96 | /* */ | |
97 | /* OUTPUTS */ | |
98 | /* None */ | |
99 | /* */ | |
100 | /* AUTHOR */ | |
101 | /* Stephen Chen Atheros Communications, INC. 2007.2 */ | |
102 | /* */ | |
103 | /************************************************************************/ | |
41d8532b | 104 | void zfDeAmsdu(zdev_t *dev, zbuf_t *buf, u16_t vap, u8_t encryMode) |
4bd43f50 | 105 | { |
41d8532b DZ |
106 | u16_t offset = ZM_SIZE_OF_WLAN_DATA_HEADER+ZM_SIZE_OF_QOS_CTRL; |
107 | zbuf_t *subframeBuf; | |
108 | zmw_get_wlan_dev(dev); | |
109 | ||
110 | ZM_BUFFER_TRACE(dev, buf) | |
111 | ||
112 | if (encryMode == ZM_AES || encryMode == ZM_TKIP) | |
113 | offset += (ZM_SIZE_OF_IV + ZM_SIZE_OF_EXT_IV); | |
114 | else if (encryMode == ZM_WEP64 || encryMode == ZM_WEP128) | |
115 | offset += ZM_SIZE_OF_IV; | |
116 | ||
117 | ||
118 | /* Repeatly calling zfGetAmsduSubFrame() until NULL returned */ | |
119 | while ((subframeBuf = zfGetAmsduSubFrame(dev, buf, &offset)) != NULL) { | |
120 | wd->commTally.NotifyNDISRxFrmCnt++; | |
121 | if (wd->zfcbRecvEth != NULL) { | |
122 | wd->zfcbRecvEth(dev, subframeBuf, (u8_t)vap); | |
123 | ZM_PERFORMANCE_RX_MSDU(dev, wd->tick); | |
124 | } | |
125 | } | |
126 | zfwBufFree(dev, buf, 0); | |
127 | ||
128 | return; | |
4bd43f50 | 129 | } |