summaryrefslogtreecommitdiffstats
path: root/drivers/staging/otus/80211core/amsdu.c
blob: 0321288d107e880b68b39d0f4a71197b4767b961 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/*
 * 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;
}
OpenPOWER on IntegriCloud