1 /*
2  * Copyright (c) 1996, 2005 VIA Networking Technologies, Inc.
3  * All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  *
20  * File: IEEE11h.c
21  *
22  * Purpose:
23  *
24  * Functions:
25  *
26  * Revision History:
27  *
28  * Author: Yiching Chen
29  *
30  * Date: Mar. 31, 2005
31  *
32  */
33 
34 #include "ttype.h"
35 #include "tmacro.h"
36 #include "tether.h"
37 #include "IEEE11h.h"
38 #include "device.h"
39 #include "wmgr.h"
40 #include "rxtx.h"
41 #include "channel.h"
42 
43 /*---------------------  Static Definitions -------------------------*/
44 static int          msglevel                = MSG_LEVEL_INFO;
45 
46 #pragma pack(1)
47 
48 typedef struct _WLAN_FRAME_ACTION {
49 	WLAN_80211HDR_A3    Header;
50 	unsigned char byCategory;
51 	unsigned char byAction;
52 	unsigned char abyVars[1];
53 } WLAN_FRAME_ACTION, *PWLAN_FRAME_ACTION;
54 
55 typedef struct _WLAN_FRAME_MSRREQ {
56 	WLAN_80211HDR_A3    Header;
57 	unsigned char byCategory;
58 	unsigned char byAction;
59 	unsigned char byDialogToken;
60 	WLAN_IE_MEASURE_REQ sMSRReqEIDs[1];
61 } WLAN_FRAME_MSRREQ, *PWLAN_FRAME_MSRREQ;
62 
63 typedef struct _WLAN_FRAME_MSRREP {
64 	WLAN_80211HDR_A3    Header;
65 	unsigned char byCategory;
66 	unsigned char byAction;
67 	unsigned char byDialogToken;
68 	WLAN_IE_MEASURE_REP sMSRRepEIDs[1];
69 } WLAN_FRAME_MSRREP, *PWLAN_FRAME_MSRREP;
70 
71 typedef struct _WLAN_FRAME_TPCREQ {
72 	WLAN_80211HDR_A3    Header;
73 	unsigned char byCategory;
74 	unsigned char byAction;
75 	unsigned char byDialogToken;
76 	WLAN_IE_TPC_REQ     sTPCReqEIDs;
77 } WLAN_FRAME_TPCREQ, *PWLAN_FRAME_TPCREQ;
78 
79 typedef struct _WLAN_FRAME_TPCREP {
80 	WLAN_80211HDR_A3    Header;
81 	unsigned char byCategory;
82 	unsigned char byAction;
83 	unsigned char byDialogToken;
84 	WLAN_IE_TPC_REP     sTPCRepEIDs;
85 } WLAN_FRAME_TPCREP, *PWLAN_FRAME_TPCREP;
86 
87 #pragma pack()
88 
89 /* action field reference ieee 802.11h Table 20e */
90 #define ACTION_MSRREQ       0
91 #define ACTION_MSRREP       1
92 #define ACTION_TPCREQ       2
93 #define ACTION_TPCREP       3
94 #define ACTION_CHSW         4
95 
96 /*---------------------  Static Classes  ----------------------------*/
97 
98 /*---------------------  Static Variables  --------------------------*/
99 
100 /*---------------------  Static Functions  --------------------------*/
s_bRxMSRReq(PSMgmtObject pMgmt,PWLAN_FRAME_MSRREQ pMSRReq,unsigned int uLength)101 static bool s_bRxMSRReq(PSMgmtObject pMgmt, PWLAN_FRAME_MSRREQ pMSRReq,
102 		unsigned int uLength)
103 {
104 	size_t    uNumOfEIDs = 0;
105 	bool bResult = true;
106 
107 	if (uLength <= WLAN_A3FR_MAXLEN)
108 		memcpy(pMgmt->abyCurrentMSRReq, pMSRReq, uLength);
109 	uNumOfEIDs = ((uLength - offsetof(WLAN_FRAME_MSRREQ,
110 			sMSRReqEIDs))/
111 			(sizeof(WLAN_IE_MEASURE_REQ)));
112 	pMgmt->pCurrMeasureEIDRep = &(((PWLAN_FRAME_MSRREP)
113 			(pMgmt->abyCurrentMSRRep))->sMSRRepEIDs[0]);
114 	pMgmt->uLengthOfRepEIDs = 0;
115 	bResult = CARDbStartMeasure(pMgmt->pAdapter,
116 				((PWLAN_FRAME_MSRREQ)
117 				(pMgmt->abyCurrentMSRReq))->sMSRReqEIDs,
118 				uNumOfEIDs
119 				);
120 	return bResult;
121 }
122 
123 
s_bRxTPCReq(PSMgmtObject pMgmt,PWLAN_FRAME_TPCREQ pTPCReq,unsigned char byRate,unsigned char byRSSI)124 static bool s_bRxTPCReq(PSMgmtObject pMgmt,
125 			PWLAN_FRAME_TPCREQ pTPCReq,
126 			unsigned char byRate,
127 			unsigned char byRSSI)
128 {
129 	PWLAN_FRAME_TPCREP  pFrame;
130 	PSTxMgmtPacket      pTxPacket = NULL;
131 
132 	pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool;
133 	memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_A3FR_MAXLEN);
134 	pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket +
135 sizeof(STxMgmtPacket));
136 
137 	pFrame = (PWLAN_FRAME_TPCREP)((unsigned char *)pTxPacket +
138 sizeof(STxMgmtPacket));
139 
140 	pFrame->Header.wFrameCtl = (WLAN_SET_FC_FTYPE(WLAN_FTYPE_MGMT) |
141 				WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_ACTION)
142 				);
143 
144 	memcpy(pFrame->Header.abyAddr1,
145 		pTPCReq->Header.abyAddr2,
146 		WLAN_ADDR_LEN);
147 	memcpy(pFrame->Header.abyAddr2,
148 		CARDpGetCurrentAddress(pMgmt->pAdapter),
149 		WLAN_ADDR_LEN);
150 	memcpy(pFrame->Header.abyAddr3,
151 		pMgmt->abyCurrBSSID,
152 		WLAN_BSSID_LEN);
153 
154 	pFrame->byCategory = 0;
155 	pFrame->byAction = 3;
156 	pFrame->byDialogToken = ((PWLAN_FRAME_MSRREQ)
157 (pMgmt->abyCurrentMSRReq))->byDialogToken;
158 
159 	pFrame->sTPCRepEIDs.byElementID = WLAN_EID_TPC_REP;
160 	pFrame->sTPCRepEIDs.len = 2;
161 	pFrame->sTPCRepEIDs.byTxPower = CARDbyGetTransmitPower(pMgmt->pAdapter);
162 	switch (byRate) {
163 	case RATE_54M:
164 		pFrame->sTPCRepEIDs.byLinkMargin = 65 - byRSSI;
165 		break;
166 	case RATE_48M:
167 		pFrame->sTPCRepEIDs.byLinkMargin = 66 - byRSSI;
168 		break;
169 	case RATE_36M:
170 		pFrame->sTPCRepEIDs.byLinkMargin = 70 - byRSSI;
171 		break;
172 	case RATE_24M:
173 		pFrame->sTPCRepEIDs.byLinkMargin = 74 - byRSSI;
174 		break;
175 	case RATE_18M:
176 		pFrame->sTPCRepEIDs.byLinkMargin = 77 - byRSSI;
177 		break;
178 	case RATE_12M:
179 		pFrame->sTPCRepEIDs.byLinkMargin = 79 - byRSSI;
180 		break;
181 	case RATE_9M:
182 		pFrame->sTPCRepEIDs.byLinkMargin = 81 - byRSSI;
183 		break;
184 	case RATE_6M:
185 	default:
186 		pFrame->sTPCRepEIDs.byLinkMargin = 82 - byRSSI;
187 		break;
188 }
189 
190 	pTxPacket->cbMPDULen = sizeof(WLAN_FRAME_TPCREP);
191 	pTxPacket->cbPayloadLen = sizeof(WLAN_FRAME_TPCREP) -
192 WLAN_HDR_ADDR3_LEN;
193 	if (csMgmt_xmit(pMgmt->pAdapter, pTxPacket) != CMD_STATUS_PENDING)
194 		return false;
195 	return true;
196 /*    return (CARDbSendPacket(pMgmt->pAdapter, pFrame, PKT_TYPE_802_11_MNG,
197 sizeof(WLAN_FRAME_TPCREP))); */
198 
199 }
200 
201 
202 /*---------------------  Export Variables  --------------------------*/
203 
204 /*---------------------  Export Functions  --------------------------*/
205 
206 
207 /*+
208  *
209  * Description:
210  *      Handles action management frames.
211  *
212  * Parameters:
213  *  In:
214  *      pMgmt           - Management Object structure
215  *      pRxPacket       - Received packet
216  *  Out:
217  *      none
218  *
219  * Return Value: None.
220  *
221 -*/
222 bool
IEEE11hbMgrRxAction(void * pMgmtHandle,void * pRxPacket)223 IEEE11hbMgrRxAction(void *pMgmtHandle, void *pRxPacket)
224 {
225 	PSMgmtObject            pMgmt = (PSMgmtObject) pMgmtHandle;
226 	PWLAN_FRAME_ACTION      pAction = NULL;
227 	unsigned int uLength = 0;
228 	PWLAN_IE_CH_SW          pChannelSwitch = NULL;
229 
230 	/* decode the frame */
231 	uLength = ((PSRxMgmtPacket)pRxPacket)->cbMPDULen;
232 	if (uLength > WLAN_A3FR_MAXLEN)
233 		return false;
234 
235 	pAction = (PWLAN_FRAME_ACTION)
236 (((PSRxMgmtPacket)pRxPacket)->p80211Header);
237 
238 	if (pAction->byCategory == 0) {
239 		switch (pAction->byAction) {
240 		case ACTION_MSRREQ:
241 			return s_bRxMSRReq(pMgmt,
242 					(PWLAN_FRAME_MSRREQ)
243 					pAction,
244 					uLength);
245 			break;
246 		case ACTION_MSRREP:
247 			break;
248 		case ACTION_TPCREQ:
249 			return s_bRxTPCReq(pMgmt,
250 				(PWLAN_FRAME_TPCREQ) pAction,
251 				((PSRxMgmtPacket)pRxPacket)->byRxRate,
252 				(unsigned char)
253 				((PSRxMgmtPacket)pRxPacket)->uRSSI);
254 			break;
255 		case ACTION_TPCREP:
256 			break;
257 		case ACTION_CHSW:
258 			pChannelSwitch = (PWLAN_IE_CH_SW) (pAction->abyVars);
259 			if ((pChannelSwitch->byElementID == WLAN_EID_CH_SWITCH)
260 			&& (pChannelSwitch->len == 3)) {
261 				/* valid element id */
262 				CARDbChannelSwitch(pMgmt->pAdapter,
263 				pChannelSwitch->byMode,
264 				get_channel_mapping(pMgmt->pAdapter,
265 				pChannelSwitch->byChannel,
266 				pMgmt->eCurrentPHYMode),
267 				pChannelSwitch->byCount);
268 			}
269 			break;
270 		default:
271 			DBG_PRT(MSG_LEVEL_DEBUG,
272 				KERN_INFO"Unknown Action = %d\n",
273 				pAction->byAction);
274 			break;
275 		}
276 	} else {
277 	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Unknown Category = %d\n",
278 pAction->byCategory);
279 	pAction->byCategory |= 0x80;
280 
281 	/*return (CARDbSendPacket(pMgmt->pAdapter, pAction, PKT_TYPE_802_11_MNG,
282 uLength));*/
283 	return true;
284 	}
285 	return true;
286 }
287 
288 
IEEE11hbMSRRepTx(void * pMgmtHandle)289 bool IEEE11hbMSRRepTx(void *pMgmtHandle)
290 {
291 	PSMgmtObject            pMgmt = (PSMgmtObject) pMgmtHandle;
292 	PWLAN_FRAME_MSRREP      pMSRRep = (PWLAN_FRAME_MSRREP)
293 (pMgmt->abyCurrentMSRRep + sizeof(STxMgmtPacket));
294 	size_t                    uLength = 0;
295 	PSTxMgmtPacket          pTxPacket = NULL;
296 
297 	pTxPacket = (PSTxMgmtPacket)pMgmt->abyCurrentMSRRep;
298 	memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_A3FR_MAXLEN);
299 	pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket +
300 sizeof(STxMgmtPacket));
301 
302 	pMSRRep->Header.wFrameCtl = (WLAN_SET_FC_FTYPE(WLAN_FTYPE_MGMT) |
303 				WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_ACTION)
304 				);
305 
306 	memcpy(pMSRRep->Header.abyAddr1, ((PWLAN_FRAME_MSRREQ)
307 		(pMgmt->abyCurrentMSRReq))->Header.abyAddr2, WLAN_ADDR_LEN);
308 	memcpy(pMSRRep->Header.abyAddr2,
309 		CARDpGetCurrentAddress(pMgmt->pAdapter), WLAN_ADDR_LEN);
310 	memcpy(pMSRRep->Header.abyAddr3, pMgmt->abyCurrBSSID, WLAN_BSSID_LEN);
311 
312 	pMSRRep->byCategory = 0;
313 	pMSRRep->byAction = 1;
314 	pMSRRep->byDialogToken = ((PWLAN_FRAME_MSRREQ)
315 		(pMgmt->abyCurrentMSRReq))->byDialogToken;
316 
317 	uLength = pMgmt->uLengthOfRepEIDs + offsetof(WLAN_FRAME_MSRREP,
318 						     sMSRRepEIDs);
319 
320 	pTxPacket->cbMPDULen = uLength;
321 	pTxPacket->cbPayloadLen = uLength - WLAN_HDR_ADDR3_LEN;
322 	if (csMgmt_xmit(pMgmt->pAdapter, pTxPacket) != CMD_STATUS_PENDING)
323 		return false;
324 	return true;
325 /*    return (CARDbSendPacket(pMgmt->pAdapter, pMSRRep, PKT_TYPE_802_11_MNG,
326 uLength)); */
327 
328 }
329 
330