• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *************************************************************************
3  * Ralink Tech Inc.
4  * 5F., No.36, Taiyuan St., Jhubei City,
5  * Hsinchu County 302,
6  * Taiwan, R.O.C.
7  *
8  * (c) Copyright 2002-2007, Ralink Technology, Inc.
9  *
10  * This program is free software; you can redistribute it and/or modify  *
11  * it under the terms of the GNU General Public License as published by  *
12  * the Free Software Foundation; either version 2 of the License, or     *
13  * (at your option) any later version.                                   *
14  *                                                                       *
15  * This program is distributed in the hope that it will be useful,       *
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
18  * GNU General Public License for more details.                          *
19  *                                                                       *
20  * You should have received a copy of the GNU General Public License     *
21  * along with this program; if not, write to the                         *
22  * Free Software Foundation, Inc.,                                       *
23  * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
24  *                                                                       *
25  *************************************************************************
26 
27 	Module Name:
28 	aironet.c
29 
30 	Abstract:
31 
32 	Revision History:
33 	Who			When			What
34 	--------	----------		----------------------------------------------
35 	Paul Lin	04-06-15		Initial
36 */
37 #include "../rt_config.h"
38 
39 /*
40 	==========================================================================
41 	Description:
42 		association	state machine init,	including state	transition and timer init
43 	Parameters:
44 		S -	pointer	to the association state machine
45 	==========================================================================
46  */
AironetStateMachineInit(IN PRTMP_ADAPTER pAd,IN STATE_MACHINE * S,OUT STATE_MACHINE_FUNC Trans[])47 VOID	AironetStateMachineInit(
48 	IN	PRTMP_ADAPTER		pAd,
49 	IN	STATE_MACHINE		*S,
50 	OUT	STATE_MACHINE_FUNC	Trans[])
51 {
52 	StateMachineInit(S,	Trans, MAX_AIRONET_STATE, MAX_AIRONET_MSG, (STATE_MACHINE_FUNC)Drop, AIRONET_IDLE, AIRONET_MACHINE_BASE);
53 	StateMachineSetAction(S, AIRONET_IDLE, MT2_AIRONET_MSG, (STATE_MACHINE_FUNC)AironetMsgAction);
54 	StateMachineSetAction(S, AIRONET_IDLE, MT2_AIRONET_SCAN_REQ, (STATE_MACHINE_FUNC)AironetRequestAction);
55 	StateMachineSetAction(S, AIRONET_SCANNING, MT2_AIRONET_SCAN_DONE, (STATE_MACHINE_FUNC)AironetReportAction);
56 }
57 
58 /*
59 	==========================================================================
60 	Description:
61 		This is	state machine function.
62 		When receiving EAPOL packets which is  for 802.1x key management.
63 		Use	both in	WPA, and WPAPSK	case.
64 		In this	function, further dispatch to different	functions according	to the received	packet.	 3 categories are :
65 		  1.  normal 4-way pairwisekey and 2-way groupkey handshake
66 		  2.  MIC error	(Countermeasures attack)  report packet	from STA.
67 		  3.  Request for pairwise/group key update	from STA
68 	Return:
69 	==========================================================================
70 */
AironetMsgAction(IN PRTMP_ADAPTER pAd,IN MLME_QUEUE_ELEM * Elem)71 VOID	AironetMsgAction(
72 	IN	PRTMP_ADAPTER	pAd,
73 	IN	MLME_QUEUE_ELEM	*Elem)
74 {
75 	USHORT							Length;
76 	UCHAR							Index, i;
77 	PUCHAR							pData;
78 	PAIRONET_RM_REQUEST_FRAME		pRMReq;
79 	PRM_REQUEST_ACTION				pReqElem;
80 
81 	DBGPRINT(RT_DEBUG_TRACE, ("-----> AironetMsgAction\n"));
82 
83 	// 0. Get Aironet IAPP header first
84 	pRMReq = (PAIRONET_RM_REQUEST_FRAME) &Elem->Msg[LENGTH_802_11];
85 	pData  = (PUCHAR) &Elem->Msg[LENGTH_802_11];
86 
87 	// 1. Change endian format form network to little endian
88 	Length = be2cpu16(pRMReq->IAPP.Length);
89 
90 	// 2.0 Sanity check, this should only happen when CCX 2.0 support is enabled
91 	if (pAd->StaCfg.CCXEnable != TRUE)
92 		return;
93 
94 	// 2.1 Radio measurement must be on
95 	if (pAd->StaCfg.CCXControl.field.RMEnable != 1)
96 		return;
97 
98 	// 2.2. Debug print all bit information
99 	DBGPRINT(RT_DEBUG_TRACE, ("IAPP ID & Length %d\n", Length));
100 	DBGPRINT(RT_DEBUG_TRACE, ("IAPP Type %x\n", pRMReq->IAPP.Type));
101 	DBGPRINT(RT_DEBUG_TRACE, ("IAPP SubType %x\n", pRMReq->IAPP.SubType));
102 	DBGPRINT(RT_DEBUG_TRACE, ("IAPP Dialog Token %x\n", pRMReq->IAPP.Token));
103 	DBGPRINT(RT_DEBUG_TRACE, ("IAPP Activation Delay %x\n", pRMReq->Delay));
104 	DBGPRINT(RT_DEBUG_TRACE, ("IAPP Measurement Offset %x\n", pRMReq->Offset));
105 
106 	// 3. Check IAPP frame type, it must be 0x32 for Cisco Aironet extension
107 	if (pRMReq->IAPP.Type != AIRONET_IAPP_TYPE)
108 	{
109 		DBGPRINT(RT_DEBUG_ERROR, ("Wrong IAPP type for Cisco Aironet extension\n"));
110 		return;
111 	}
112 
113 	// 4. Check IAPP frame subtype, it must be 0x01 for Cisco Aironet extension request.
114 	//    Since we are acting as client only, we will disregards reply subtype.
115 	if (pRMReq->IAPP.SubType != AIRONET_IAPP_SUBTYPE_REQUEST)
116 	{
117 		DBGPRINT(RT_DEBUG_ERROR, ("Wrong IAPP subtype for Cisco Aironet extension\n"));
118 		return;
119 	}
120 
121 	// 5. Verify Destination MAC and Source MAC, both should be all zeros.
122 	if (! MAC_ADDR_EQUAL(pRMReq->IAPP.DA, ZERO_MAC_ADDR))
123 	{
124 		DBGPRINT(RT_DEBUG_ERROR, ("Wrong IAPP DA for Cisco Aironet extension, it's not Zero\n"));
125 		return;
126 	}
127 
128 	if (! MAC_ADDR_EQUAL(pRMReq->IAPP.SA, ZERO_MAC_ADDR))
129 	{
130 		DBGPRINT(RT_DEBUG_ERROR, ("Wrong IAPP SA for Cisco Aironet extension, it's not Zero\n"));
131 		return;
132 	}
133 
134 	// 6. Reinit all report related fields
135 	NdisZeroMemory(pAd->StaCfg.FrameReportBuf, 2048);
136 	NdisZeroMemory(pAd->StaCfg.BssReportOffset, sizeof(USHORT) * MAX_LEN_OF_BSS_TABLE);
137 	NdisZeroMemory(pAd->StaCfg.MeasurementRequest, sizeof(RM_REQUEST_ACTION) * 4);
138 
139 	// 7. Point to the start of first element report element
140 	pAd->StaCfg.FrameReportLen   = LENGTH_802_11 + sizeof(AIRONET_IAPP_HEADER);
141 	DBGPRINT(RT_DEBUG_TRACE, ("FR len = %d\n", pAd->StaCfg.FrameReportLen));
142 	pAd->StaCfg.LastBssIndex     = 0xff;
143 	pAd->StaCfg.RMReqCnt         = 0;
144 	pAd->StaCfg.ParallelReq      = FALSE;
145 	pAd->StaCfg.ParallelDuration = 0;
146 	pAd->StaCfg.ParallelChannel  = 0;
147 	pAd->StaCfg.IAPPToken        = pRMReq->IAPP.Token;
148 	pAd->StaCfg.CurrentRMReqIdx  = 0;
149 	pAd->StaCfg.CLBusyBytes      = 0;
150 	// Reset the statistics
151 	for (i = 0; i < 8; i++)
152 		pAd->StaCfg.RPIDensity[i] = 0;
153 
154 	Index = 0;
155 
156 	// 8. Save dialog token for report
157 	pAd->StaCfg.IAPPToken = pRMReq->IAPP.Token;
158 
159 	// Save Activation delay & measurement offset, Not really needed
160 
161 	// 9. Point to the first request element
162 	pData += sizeof(AIRONET_RM_REQUEST_FRAME);
163 	//    Length should exclude the CISCO Aironet SNAP header
164 	Length -= (sizeof(AIRONET_RM_REQUEST_FRAME) - LENGTH_802_1_H);
165 
166 	// 10. Start Parsing the Measurement elements.
167 	//    Be careful about multiple MR elements within one frames.
168 	while (Length > 0)
169 	{
170 		pReqElem = (PRM_REQUEST_ACTION) pData;
171 		switch (pReqElem->ReqElem.Eid)
172 		{
173 			case IE_MEASUREMENT_REQUEST:
174 				// From the example, it seems we only need to support one request in one frame
175 				// There is no multiple request in one frame.
176 				// Besides, looks like we need to take care the measurement request only.
177 				// The measurement request is always 4 bytes.
178 
179 				// Start parsing this type of request.
180 				// 0. Eid is IE_MEASUREMENT_REQUEST
181 				// 1. Length didn't include Eid and Length field, it always be 8.
182 				// 2. Measurement Token, we nned to save it for the corresponding report.
183 				// 3. Measurement Mode, Although there are definitions, but we din't see value other than
184 				//    0 from test specs examples.
185 				// 4. Measurement Type, this is what we need to do.
186 				switch (pReqElem->ReqElem.Type)
187 				{
188 					case MSRN_TYPE_CHANNEL_LOAD_REQ:
189 					case MSRN_TYPE_NOISE_HIST_REQ:
190 					case MSRN_TYPE_BEACON_REQ:
191 						// Check the Enable non-serving channel measurement control
192 						if (pAd->StaCfg.CCXControl.field.DCRMEnable == 0)
193 						{
194 							// Check channel before enqueue the action
195 							if (pReqElem->Measurement.Channel != pAd->CommonCfg.Channel)
196 								break;
197 						}
198 						else
199 						{
200 							// If off channel measurement, check the TU duration limit
201 							if (pReqElem->Measurement.Channel != pAd->CommonCfg.Channel)
202 								if (pReqElem->Measurement.Duration > pAd->StaCfg.CCXControl.field.TuLimit)
203 									break;
204 						}
205 
206 						// Save requests and execute actions later
207 						NdisMoveMemory(&pAd->StaCfg.MeasurementRequest[Index], pReqElem, sizeof(RM_REQUEST_ACTION));
208 						Index += 1;
209 						break;
210 
211 					case MSRN_TYPE_FRAME_REQ:
212 						// Since it's option, we will support later
213 						// FrameRequestAction(pAd, pData);
214 						break;
215 
216 					default:
217 						break;
218 				}
219 
220 				// Point to next Measurement request
221 				pData  += sizeof(RM_REQUEST_ACTION);
222 				Length -= sizeof(RM_REQUEST_ACTION);
223 				break;
224 
225 			// We accept request only, all others are dropped
226 			case IE_MEASUREMENT_REPORT:
227 			case IE_AP_TX_POWER:
228 			case IE_MEASUREMENT_CAPABILITY:
229 			default:
230 				return;
231 		}
232 	}
233 
234 	// 11. Update some flags and index
235 	pAd->StaCfg.RMReqCnt = Index;
236 
237 	if (Index)
238 	{
239 		MlmeEnqueue(pAd, AIRONET_STATE_MACHINE, MT2_AIRONET_SCAN_REQ, 0, NULL);
240 		RT28XX_MLME_HANDLER(pAd);
241 	}
242 
243 	DBGPRINT(RT_DEBUG_TRACE, ("<----- AironetMsgAction\n"));
244 }
245 
246 /*
247 	========================================================================
248 
249 	Routine Description:
250 
251 	Arguments:
252 
253 	Return Value:
254 		None
255 
256 	Note:
257 
258 	========================================================================
259 */
AironetRequestAction(IN PRTMP_ADAPTER pAd,IN MLME_QUEUE_ELEM * Elem)260 VOID	AironetRequestAction(
261 	IN	PRTMP_ADAPTER	pAd,
262 	IN	MLME_QUEUE_ELEM	*Elem)
263 {
264 	PRM_REQUEST_ACTION	pReq;
265 
266 	// 1. Point to next request element
267 	pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[pAd->StaCfg.CurrentRMReqIdx];
268 
269 	// 2. Parse measurement type and call appropriate functions
270 	if (pReq->ReqElem.Type == MSRN_TYPE_CHANNEL_LOAD_REQ)
271 		// Channel Load measurement request
272 		ChannelLoadRequestAction(pAd, pAd->StaCfg.CurrentRMReqIdx);
273 	else if (pReq->ReqElem.Type == MSRN_TYPE_NOISE_HIST_REQ)
274 		// Noise Histogram measurement request
275 		NoiseHistRequestAction(pAd, pAd->StaCfg.CurrentRMReqIdx);
276 	else if (pReq->ReqElem.Type == MSRN_TYPE_BEACON_REQ)
277 		// Beacon measurement request
278 		BeaconRequestAction(pAd, pAd->StaCfg.CurrentRMReqIdx);
279 	else
280 		// Unknown. Do nothing and return, this should never happen
281 		return;
282 
283 	// 3. Peek into the next request, if it's parallel, we will update the scan time to the largest one
284 	if ((pAd->StaCfg.CurrentRMReqIdx + 1) < pAd->StaCfg.RMReqCnt)
285 	{
286 		pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[pAd->StaCfg.CurrentRMReqIdx + 1];
287 		// Check for parallel bit
288 		if ((pReq->ReqElem.Mode & 0x01) && (pReq->Measurement.Channel == pAd->StaCfg.CCXScanChannel))
289 		{
290 			// Update parallel mode request information
291 			pAd->StaCfg.ParallelReq = TRUE;
292 			pAd->StaCfg.CCXScanTime = ((pReq->Measurement.Duration > pAd->StaCfg.CCXScanTime) ?
293 			(pReq->Measurement.Duration) : (pAd->StaCfg.CCXScanTime));
294 		}
295 	}
296 
297 	// 4. Call RT28XX_MLME_HANDLER to execute the request mlme commands, Scan request is the only one used
298 	RT28XX_MLME_HANDLER(pAd);
299 
300 }
301 
302 
303 /*
304 	========================================================================
305 
306 	Routine Description:
307 		Prepare channel load report action, special scan operation added
308 		to support
309 
310 	Arguments:
311 		pAd	Pointer	to our adapter
312 		pData		Start from element ID
313 
314 	Return Value:
315 		None
316 
317 	Note:
318 
319 	========================================================================
320 */
ChannelLoadRequestAction(IN PRTMP_ADAPTER pAd,IN UCHAR Index)321 VOID	ChannelLoadRequestAction(
322 	IN	PRTMP_ADAPTER	pAd,
323 	IN	UCHAR			Index)
324 {
325 	PRM_REQUEST_ACTION				pReq;
326 	MLME_SCAN_REQ_STRUCT			ScanReq;
327 	UCHAR							ZeroSsid[32];
328 	NDIS_STATUS						NStatus;
329 	PUCHAR							pOutBuffer = NULL;
330 	PHEADER_802_11					pNullFrame;
331 
332 	DBGPRINT(RT_DEBUG_TRACE, ("ChannelLoadRequestAction ----->\n"));
333 
334 	pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[Index];
335 	NdisZeroMemory(ZeroSsid, 32);
336 
337 	// Prepare for special scan request
338 	// The scan definition is different with our Active, Passive scan definition.
339 	// For CCX2, Active means send out probe request with broadcast BSSID.
340 	// Passive means no probe request sent, only listen to the beacons.
341 	// The channel scanned is fixed as specified, no need to scan all channels.
342 	// The scan wait time is specified in the request too.
343 	// Passive scan Mode
344 
345 	// Control state machine is not idle, reject the request
346 	if ((pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) && (Index == 0))
347 		return;
348 
349 	// Fill out stuff for scan request
350 	ScanParmFill(pAd, &ScanReq, ZeroSsid, 0, BSS_ANY, SCAN_CISCO_CHANNEL_LOAD);
351 	MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
352 	pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
353 
354 	// Reset some internal control flags to make sure this scan works.
355 	BssTableInit(&pAd->StaCfg.CCXBssTab);
356 	pAd->StaCfg.ScanCnt        = 0;
357 	pAd->StaCfg.CCXScanChannel = pReq->Measurement.Channel;
358 	pAd->StaCfg.CCXScanTime    = pReq->Measurement.Duration;
359 
360 	DBGPRINT(RT_DEBUG_TRACE, ("Duration %d, Channel %d!\n", pReq->Measurement.Duration, pReq->Measurement.Channel));
361 
362 	// If it's non serving channel scan, send out a null frame with PSM bit on.
363 	if (pAd->StaCfg.CCXScanChannel != pAd->CommonCfg.Channel)
364 	{
365 		// Use MLME enqueue method
366 		NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer);  //Get an unused nonpaged memory
367 		if (NStatus	!= NDIS_STATUS_SUCCESS)
368 			return;
369 
370 		pNullFrame = (PHEADER_802_11) pOutBuffer;;
371 		// Make the power save Null frame with PSM bit on
372 		MgtMacHeaderInit(pAd, pNullFrame, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid);
373 		pNullFrame->Duration 	= 0;
374 		pNullFrame->FC.Type 	= BTYPE_DATA;
375 		pNullFrame->FC.PwrMgmt	= PWR_SAVE;
376 
377 		// Send using priority queue
378 		MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11));
379 		MlmeFreeMemory(pAd, pOutBuffer);
380 		DBGPRINT(RT_DEBUG_TRACE, ("Send PSM Data frame for off channel RM\n"));
381 		RTMPusecDelay(5000);
382 	}
383 
384 	pAd->StaCfg.CCXReqType     = MSRN_TYPE_CHANNEL_LOAD_REQ;
385 	pAd->StaCfg.CLBusyBytes    = 0;
386 	// Enable Rx with promiscuous reception
387 	RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, 0x1010);
388 
389 	// Set channel load measurement flag
390 	RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_MEASUREMENT);
391 
392 	pAd->Mlme.AironetMachine.CurrState = AIRONET_SCANNING;
393 
394 	DBGPRINT(RT_DEBUG_TRACE, ("ChannelLoadRequestAction <-----\n"));
395 }
396 
397 /*
398 	========================================================================
399 
400 	Routine Description:
401 		Prepare noise histogram report action, special scan operation added
402 		to support
403 
404 	Arguments:
405 		pAd	Pointer	to our adapter
406 		pData		Start from element ID
407 
408 	Return Value:
409 		None
410 
411 	Note:
412 
413 	========================================================================
414 */
NoiseHistRequestAction(IN PRTMP_ADAPTER pAd,IN UCHAR Index)415 VOID	NoiseHistRequestAction(
416 	IN	PRTMP_ADAPTER	pAd,
417 	IN	UCHAR			Index)
418 {
419 	PRM_REQUEST_ACTION				pReq;
420 	MLME_SCAN_REQ_STRUCT			ScanReq;
421 	UCHAR							ZeroSsid[32], i;
422 	NDIS_STATUS						NStatus;
423 	PUCHAR							pOutBuffer = NULL;
424 	PHEADER_802_11					pNullFrame;
425 
426 	DBGPRINT(RT_DEBUG_TRACE, ("NoiseHistRequestAction ----->\n"));
427 
428 	pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[Index];
429 	NdisZeroMemory(ZeroSsid, 32);
430 
431 	// Prepare for special scan request
432 	// The scan definition is different with our Active, Passive scan definition.
433 	// For CCX2, Active means send out probe request with broadcast BSSID.
434 	// Passive means no probe request sent, only listen to the beacons.
435 	// The channel scanned is fixed as specified, no need to scan all channels.
436 	// The scan wait time is specified in the request too.
437 	// Passive scan Mode
438 
439 	// Control state machine is not idle, reject the request
440 	if ((pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) && (Index == 0))
441 		return;
442 
443 	// Fill out stuff for scan request
444 	ScanParmFill(pAd, &ScanReq, ZeroSsid, 0, BSS_ANY, SCAN_CISCO_NOISE);
445 	MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
446 	pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
447 
448 	// Reset some internal control flags to make sure this scan works.
449 	BssTableInit(&pAd->StaCfg.CCXBssTab);
450 	pAd->StaCfg.ScanCnt        = 0;
451 	pAd->StaCfg.CCXScanChannel = pReq->Measurement.Channel;
452 	pAd->StaCfg.CCXScanTime    = pReq->Measurement.Duration;
453 	pAd->StaCfg.CCXReqType     = MSRN_TYPE_NOISE_HIST_REQ;
454 
455 	DBGPRINT(RT_DEBUG_TRACE, ("Duration %d, Channel %d!\n", pReq->Measurement.Duration, pReq->Measurement.Channel));
456 
457 	// If it's non serving channel scan, send out a null frame with PSM bit on.
458 	if (pAd->StaCfg.CCXScanChannel != pAd->CommonCfg.Channel)
459 	{
460 		// Use MLME enqueue method
461 		NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer);  //Get an unused nonpaged memory
462 		if (NStatus	!= NDIS_STATUS_SUCCESS)
463 			return;
464 
465 		pNullFrame = (PHEADER_802_11) pOutBuffer;
466 		// Make the power save Null frame with PSM bit on
467 		MgtMacHeaderInit(pAd, pNullFrame, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid);
468 		pNullFrame->Duration 	= 0;
469 		pNullFrame->FC.Type  	= BTYPE_DATA;
470 		pNullFrame->FC.PwrMgmt	= PWR_SAVE;
471 
472 		// Send using priority queue
473 		MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11));
474 		MlmeFreeMemory(pAd, pOutBuffer);
475 		DBGPRINT(RT_DEBUG_TRACE, ("Send PSM Data frame for off channel RM\n"));
476 		RTMPusecDelay(5000);
477 	}
478 
479 	// Reset the statistics
480 	for (i = 0; i < 8; i++)
481 		pAd->StaCfg.RPIDensity[i] = 0;
482 
483 	// Enable Rx with promiscuous reception
484 	RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, 0x1010);
485 
486 	// Set channel load measurement flag
487 	RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_MEASUREMENT);
488 
489 	pAd->Mlme.AironetMachine.CurrState = AIRONET_SCANNING;
490 
491 	DBGPRINT(RT_DEBUG_TRACE, ("NoiseHistRequestAction <-----\n"));
492 }
493 
494 /*
495 	========================================================================
496 
497 	Routine Description:
498 		Prepare Beacon report action, special scan operation added
499 		to support
500 
501 	Arguments:
502 		pAd	Pointer	to our adapter
503 		pData		Start from element ID
504 
505 	Return Value:
506 		None
507 
508 	Note:
509 
510 	========================================================================
511 */
BeaconRequestAction(IN PRTMP_ADAPTER pAd,IN UCHAR Index)512 VOID	BeaconRequestAction(
513 	IN	PRTMP_ADAPTER	pAd,
514 	IN	UCHAR			Index)
515 {
516 	PRM_REQUEST_ACTION				pReq;
517 	NDIS_STATUS						NStatus;
518 	PUCHAR							pOutBuffer = NULL;
519 	PHEADER_802_11					pNullFrame;
520 	MLME_SCAN_REQ_STRUCT			ScanReq;
521 	UCHAR							ZeroSsid[32];
522 
523 	DBGPRINT(RT_DEBUG_TRACE, ("BeaconRequestAction ----->\n"));
524 
525 	pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[Index];
526 	NdisZeroMemory(ZeroSsid, 32);
527 
528 	// Prepare for special scan request
529 	// The scan definition is different with our Active, Passive scan definition.
530 	// For CCX2, Active means send out probe request with broadcast BSSID.
531 	// Passive means no probe request sent, only listen to the beacons.
532 	// The channel scanned is fixed as specified, no need to scan all channels.
533 	// The scan wait time is specified in the request too.
534 	if (pReq->Measurement.ScanMode == MSRN_SCAN_MODE_PASSIVE)
535 	{
536 		// Passive scan Mode
537 		DBGPRINT(RT_DEBUG_TRACE, ("Passive Scan Mode!\n"));
538 
539 		// Control state machine is not idle, reject the request
540 		if ((pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) && (Index == 0))
541 			return;
542 
543 		// Fill out stuff for scan request
544 		ScanParmFill(pAd, &ScanReq, ZeroSsid, 0, BSS_ANY, SCAN_CISCO_PASSIVE);
545 		MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
546 		pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
547 
548 		// Reset some internal control flags to make sure this scan works.
549 		BssTableInit(&pAd->StaCfg.CCXBssTab);
550 		pAd->StaCfg.ScanCnt        = 0;
551 		pAd->StaCfg.CCXScanChannel = pReq->Measurement.Channel;
552 		pAd->StaCfg.CCXScanTime    = pReq->Measurement.Duration;
553 		pAd->StaCfg.CCXReqType     = MSRN_TYPE_BEACON_REQ;
554 		DBGPRINT(RT_DEBUG_TRACE, ("Duration %d!\n", pReq->Measurement.Duration));
555 
556 		// If it's non serving channel scan, send out a null frame with PSM bit on.
557 		if (pAd->StaCfg.CCXScanChannel != pAd->CommonCfg.Channel)
558 		{
559 			// Use MLME enqueue method
560 			NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer);  //Get an unused nonpaged memory
561 			if (NStatus	!= NDIS_STATUS_SUCCESS)
562 				return;
563 
564 			pNullFrame = (PHEADER_802_11) pOutBuffer;
565 			// Make the power save Null frame with PSM bit on
566 			MgtMacHeaderInit(pAd, pNullFrame, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid);
567 			pNullFrame->Duration 	= 0;
568 			pNullFrame->FC.Type     = BTYPE_DATA;
569 			pNullFrame->FC.PwrMgmt  = PWR_SAVE;
570 
571 			// Send using priority queue
572 			MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11));
573 			MlmeFreeMemory(pAd, pOutBuffer);
574 			DBGPRINT(RT_DEBUG_TRACE, ("Send PSM Data frame for off channel RM\n"));
575 			RTMPusecDelay(5000);
576 		}
577 
578 		pAd->Mlme.AironetMachine.CurrState = AIRONET_SCANNING;
579 	}
580 	else if (pReq->Measurement.ScanMode == MSRN_SCAN_MODE_ACTIVE)
581 	{
582 		// Active scan Mode
583 		DBGPRINT(RT_DEBUG_TRACE, ("Active Scan Mode!\n"));
584 
585 		// Control state machine is not idle, reject the request
586 		if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE)
587 			return;
588 
589 		// Fill out stuff for scan request
590 		ScanParmFill(pAd, &ScanReq, ZeroSsid, 0, BSS_ANY, SCAN_CISCO_ACTIVE);
591 		MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
592 		pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
593 
594 		// Reset some internal control flags to make sure this scan works.
595 		BssTableInit(&pAd->StaCfg.CCXBssTab);
596 		pAd->StaCfg.ScanCnt        = 0;
597 		pAd->StaCfg.CCXScanChannel = pReq->Measurement.Channel;
598 		pAd->StaCfg.CCXScanTime    = pReq->Measurement.Duration;
599 		pAd->StaCfg.CCXReqType     = MSRN_TYPE_BEACON_REQ;
600 		DBGPRINT(RT_DEBUG_TRACE, ("Duration %d!\n", pReq->Measurement.Duration));
601 
602 		// If it's non serving channel scan, send out a null frame with PSM bit on.
603 		if (pAd->StaCfg.CCXScanChannel != pAd->CommonCfg.Channel)
604 		{
605 			// Use MLME enqueue method
606 			NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer);  //Get an unused nonpaged memory
607 			if (NStatus	!= NDIS_STATUS_SUCCESS)
608 				return;
609 
610 			pNullFrame = (PHEADER_802_11) pOutBuffer;
611 			// Make the power save Null frame with PSM bit on
612 			MgtMacHeaderInit(pAd, pNullFrame, SUBTYPE_NULL_FUNC, 1, pAd->CommonCfg.Bssid, pAd->CommonCfg.Bssid);
613 			pNullFrame->Duration 	= 0;
614 			pNullFrame->FC.Type     = BTYPE_DATA;
615 			pNullFrame->FC.PwrMgmt  = PWR_SAVE;
616 
617 			// Send using priority queue
618 			MiniportMMRequest(pAd, 0, pOutBuffer, sizeof(HEADER_802_11));
619 			MlmeFreeMemory(pAd, pOutBuffer);
620 			DBGPRINT(RT_DEBUG_TRACE, ("Send PSM Data frame for off channel RM\n"));
621 			RTMPusecDelay(5000);
622 		}
623 
624 		pAd->Mlme.AironetMachine.CurrState = AIRONET_SCANNING;
625 	}
626 	else if (pReq->Measurement.ScanMode == MSRN_SCAN_MODE_BEACON_TABLE)
627 	{
628 		// Beacon report Mode, report all the APS in current bss table
629 		DBGPRINT(RT_DEBUG_TRACE, ("Beacon Report Mode!\n"));
630 
631 		// Copy current BSS table to CCX table, we can omit this step later on.
632 		NdisMoveMemory(&pAd->StaCfg.CCXBssTab, &pAd->ScanTab, sizeof(BSS_TABLE));
633 
634 		// Create beacon report from Bss table
635 		AironetCreateBeaconReportFromBssTable(pAd);
636 
637 		// Set state to scanning
638 		pAd->Mlme.AironetMachine.CurrState = AIRONET_SCANNING;
639 
640 		// Enqueue report request
641 		// Cisco scan request is finished, prepare beacon report
642 		MlmeEnqueue(pAd, AIRONET_STATE_MACHINE, MT2_AIRONET_SCAN_DONE, 0, NULL);
643 	}
644 	else
645 	{
646 		// Wrong scan Mode
647 		DBGPRINT(RT_DEBUG_TRACE, ("Wrong Scan Mode!\n"));
648 	}
649 
650 	DBGPRINT(RT_DEBUG_TRACE, ("BeaconRequestAction <-----\n"));
651 }
652 
653 /*
654 	========================================================================
655 
656 	Routine Description:
657 
658 	Arguments:
659 
660 	Return Value:
661 		None
662 
663 	Note:
664 
665 	========================================================================
666 */
AironetReportAction(IN PRTMP_ADAPTER pAd,IN MLME_QUEUE_ELEM * Elem)667 VOID	AironetReportAction(
668 	IN	PRTMP_ADAPTER	pAd,
669 	IN	MLME_QUEUE_ELEM	*Elem)
670 {
671 	PRM_REQUEST_ACTION	pReq;
672 	ULONG				Now32;
673 
674     NdisGetSystemUpTime(&Now32);
675 	pAd->StaCfg.LastBeaconRxTime = Now32;
676 
677 	pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[pAd->StaCfg.CurrentRMReqIdx];
678 
679 	DBGPRINT(RT_DEBUG_TRACE, ("AironetReportAction ----->\n"));
680 
681 	// 1. Parse measurement type and call appropriate functions
682 	if (pReq->ReqElem.Type == MSRN_TYPE_CHANNEL_LOAD_REQ)
683 		// Channel Load measurement request
684 		ChannelLoadReportAction(pAd, pAd->StaCfg.CurrentRMReqIdx);
685 	else if (pReq->ReqElem.Type == MSRN_TYPE_NOISE_HIST_REQ)
686 		// Noise Histogram measurement request
687 		NoiseHistReportAction(pAd, pAd->StaCfg.CurrentRMReqIdx);
688 	else if (pReq->ReqElem.Type == MSRN_TYPE_BEACON_REQ)
689 		// Beacon measurement request
690 		BeaconReportAction(pAd, pAd->StaCfg.CurrentRMReqIdx);
691 	else
692 		// Unknown. Do nothing and return
693 		;
694 
695 	// 2. Point to the correct index of action element, start from 0
696 	pAd->StaCfg.CurrentRMReqIdx++;
697 
698 	// 3. Check for parallel actions
699 	if (pAd->StaCfg.ParallelReq == TRUE)
700 	{
701 		pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[pAd->StaCfg.CurrentRMReqIdx];
702 
703 		// Process next action right away
704 		if (pReq->ReqElem.Type == MSRN_TYPE_CHANNEL_LOAD_REQ)
705 			// Channel Load measurement request
706 			ChannelLoadReportAction(pAd, pAd->StaCfg.CurrentRMReqIdx);
707 		else if (pReq->ReqElem.Type == MSRN_TYPE_NOISE_HIST_REQ)
708 			// Noise Histogram measurement request
709 			NoiseHistReportAction(pAd, pAd->StaCfg.CurrentRMReqIdx);
710 
711 		pAd->StaCfg.ParallelReq = FALSE;
712 		pAd->StaCfg.CurrentRMReqIdx++;
713 	}
714 
715 	if (pAd->StaCfg.CurrentRMReqIdx >= pAd->StaCfg.RMReqCnt)
716 	{
717 		// 4. There is no more unprocessed measurement request, go for transmit this report
718 		AironetFinalReportAction(pAd);
719 		pAd->Mlme.AironetMachine.CurrState = AIRONET_IDLE;
720 	}
721 	else
722 	{
723 		pReq = (PRM_REQUEST_ACTION) &pAd->StaCfg.MeasurementRequest[pAd->StaCfg.CurrentRMReqIdx];
724 
725 		if (pReq->Measurement.Channel != pAd->CommonCfg.Channel)
726 		{
727 			RTMPusecDelay(100000);
728 		}
729 
730 		// 5. There are more requests to be measure
731 		MlmeEnqueue(pAd, AIRONET_STATE_MACHINE, MT2_AIRONET_SCAN_REQ, 0, NULL);
732 		RT28XX_MLME_HANDLER(pAd);
733 	}
734 
735 	DBGPRINT(RT_DEBUG_TRACE, ("AironetReportAction <-----\n"));
736 }
737 
738 /*
739 	========================================================================
740 
741 	Routine Description:
742 
743 	Arguments:
744 
745 	Return Value:
746 		None
747 
748 	Note:
749 
750 	========================================================================
751 */
AironetFinalReportAction(IN PRTMP_ADAPTER pAd)752 VOID	AironetFinalReportAction(
753 	IN	PRTMP_ADAPTER	pAd)
754 {
755 	PUCHAR					pDest;
756 	PAIRONET_IAPP_HEADER	pIAPP;
757 	PHEADER_802_11			pHeader;
758 	UCHAR					AckRate = RATE_2;
759 	USHORT					AckDuration = 0;
760 	NDIS_STATUS				NStatus;
761 	PUCHAR					pOutBuffer = NULL;
762 	ULONG					FrameLen = 0;
763 
764 	DBGPRINT(RT_DEBUG_TRACE, ("AironetFinalReportAction ----->\n"));
765 
766 	// 0. Set up the frame pointer, Frame was inited at the end of message action
767 	pDest = &pAd->StaCfg.FrameReportBuf[LENGTH_802_11];
768 
769 	// 1. Update report IAPP fields
770 	pIAPP = (PAIRONET_IAPP_HEADER) pDest;
771 
772 	// 2. Copy Cisco SNAP header
773 	NdisMoveMemory(pIAPP->CiscoSnapHeader, SNAP_AIRONET, LENGTH_802_1_H);
774 
775 	// 3. network order for this 16bit length
776 	pIAPP->Length  = cpu2be16(pAd->StaCfg.FrameReportLen - LENGTH_802_11 - LENGTH_802_1_H);
777 
778 	// 3.1 sanity check the report length, ignore it if there is nothing to report
779 	if (be2cpu16(pIAPP->Length) <= 18)
780 		return;
781 
782 	// 4. Type must be 0x32
783 	pIAPP->Type    = AIRONET_IAPP_TYPE;
784 
785 	// 5. SubType for report must be 0x81
786 	pIAPP->SubType = AIRONET_IAPP_SUBTYPE_REPORT;
787 
788 	// 6. DA is not used and must be zero, although the whole frame was cleared at the start of function
789 	//    We will do it again here. We can use BSSID instead
790 	COPY_MAC_ADDR(pIAPP->DA, pAd->CommonCfg.Bssid);
791 
792 	// 7. SA is the client reporting which must be our MAC
793 	COPY_MAC_ADDR(pIAPP->SA, pAd->CurrentAddress);
794 
795 	// 8. Copy the saved dialog token
796 	pIAPP->Token = pAd->StaCfg.IAPPToken;
797 
798 	// 9. Make the Report frame 802.11 header
799 	//    Reuse function in wpa.c
800 	pHeader = (PHEADER_802_11) pAd->StaCfg.FrameReportBuf;
801 	pAd->Sequence ++;
802 	WpaMacHeaderInit(pAd, pHeader, 0, pAd->CommonCfg.Bssid);
803 
804 	// ACK size	is 14 include CRC, and its rate	is based on real time information
805 	AckRate     = pAd->CommonCfg.ExpectedACKRate[pAd->CommonCfg.MlmeRate];
806 	AckDuration = RTMPCalcDuration(pAd, AckRate, 14);
807 	pHeader->Duration = pAd->CommonCfg.Dsifs + AckDuration;
808 
809 	// Use MLME enqueue method
810 	NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);  //Get an unused nonpaged memory
811 	if (NStatus	!= NDIS_STATUS_SUCCESS)
812 		return;
813 
814 	// 10. Prepare report frame with dynamic outbuffer. Just simply copy everything.
815 	MakeOutgoingFrame(pOutBuffer,                       &FrameLen,
816 	                  pAd->StaCfg.FrameReportLen, pAd->StaCfg.FrameReportBuf,
817 		              END_OF_ARGS);
818 
819 	// 11. Send using priority queue
820 	MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
821 	MlmeFreeMemory(pAd, pOutBuffer);
822 
823 	pAd->StaCfg.CCXReqType = MSRN_TYPE_UNUSED;
824 
825 	DBGPRINT(RT_DEBUG_TRACE, ("AironetFinalReportAction <-----\n"));
826 }
827 
828 /*
829 	========================================================================
830 
831 	Routine Description:
832 
833 	Arguments:
834 
835 	Return Value:
836 		None
837 
838 	Note:
839 
840 	========================================================================
841 */
ChannelLoadReportAction(IN PRTMP_ADAPTER pAd,IN UCHAR Index)842 VOID	ChannelLoadReportAction(
843 	IN	PRTMP_ADAPTER	pAd,
844 	IN	UCHAR			Index)
845 {
846 	PMEASUREMENT_REPORT_ELEMENT	pReport;
847 	PCHANNEL_LOAD_REPORT		pLoad;
848 	PUCHAR						pDest;
849 	UCHAR						CCABusyFraction;
850 
851 	DBGPRINT(RT_DEBUG_TRACE, ("ChannelLoadReportAction ----->\n"));
852 
853 	// Disable Rx with promiscuous reception, make it back to normal
854 	RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, STANORMAL); // Staion not drop control frame will fail WiFi Certification.
855 
856 	// 0. Setup pointer for processing beacon & probe response
857 	pDest = (PUCHAR) &pAd->StaCfg.FrameReportBuf[pAd->StaCfg.FrameReportLen];
858 	pReport = (PMEASUREMENT_REPORT_ELEMENT) pDest;
859 
860 	// 1. Fill Measurement report element field.
861 	pReport->Eid    = IE_MEASUREMENT_REPORT;
862 	// Fixed Length at 9, not include Eid and length fields
863 	pReport->Length = 9;
864 	pReport->Token  = pAd->StaCfg.MeasurementRequest[Index].ReqElem.Token;
865 	pReport->Mode   = pAd->StaCfg.MeasurementRequest[Index].ReqElem.Mode;
866 	pReport->Type   = MSRN_TYPE_CHANNEL_LOAD_REQ;
867 
868 	// 2. Fill channel report measurement data
869 	pDest += sizeof(MEASUREMENT_REPORT_ELEMENT);
870 	pLoad  = (PCHANNEL_LOAD_REPORT) pDest;
871 	pLoad->Channel  = pAd->StaCfg.MeasurementRequest[Index].Measurement.Channel;
872 	pLoad->Spare    = 0;
873 	pLoad->Duration = pAd->StaCfg.MeasurementRequest[Index].Measurement.Duration;
874 
875 	// 3. Calculate the CCA Busy Fraction
876 	//    (Bytes + ACK size) * 8 / Tx speed * 255 / 1000 / measurement duration, use 24 us Tx speed
877 	//     =  (Bytes + ACK) / 12 / duration
878 	//     9 is the good value for pAd->StaCfg.CLFactor
879 	// CCABusyFraction = (UCHAR) (pAd->StaCfg.CLBusyBytes / 9 / pLoad->Duration);
880 	CCABusyFraction = (UCHAR) (pAd->StaCfg.CLBusyBytes / pAd->StaCfg.CLFactor / pLoad->Duration);
881 	if (CCABusyFraction < 10)
882 			CCABusyFraction = (UCHAR) (pAd->StaCfg.CLBusyBytes / 3 / pLoad->Duration) + 1;
883 
884 	pLoad->CCABusy = CCABusyFraction;
885 	DBGPRINT(RT_DEBUG_TRACE, ("CLBusyByte %ld, Duration %d, Result, %d\n", pAd->StaCfg.CLBusyBytes, pLoad->Duration, CCABusyFraction));
886 
887 	DBGPRINT(RT_DEBUG_TRACE, ("FrameReportLen %d\n", pAd->StaCfg.FrameReportLen));
888 	pAd->StaCfg.FrameReportLen += (sizeof(MEASUREMENT_REPORT_ELEMENT) + sizeof(CHANNEL_LOAD_REPORT));
889 	DBGPRINT(RT_DEBUG_TRACE, ("FrameReportLen %d\n", pAd->StaCfg.FrameReportLen));
890 
891 	// 4. Clear channel load measurement flag
892 	RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_MEASUREMENT);
893 
894 	// 5. reset to idle state
895 	pAd->Mlme.AironetMachine.CurrState = AIRONET_IDLE;
896 
897 	DBGPRINT(RT_DEBUG_TRACE, ("ChannelLoadReportAction <-----\n"));
898 }
899 
900 /*
901 	========================================================================
902 
903 	Routine Description:
904 
905 	Arguments:
906 
907 	Return Value:
908 		None
909 
910 	Note:
911 
912 	========================================================================
913 */
NoiseHistReportAction(IN PRTMP_ADAPTER pAd,IN UCHAR Index)914 VOID	NoiseHistReportAction(
915 	IN	PRTMP_ADAPTER	pAd,
916 	IN	UCHAR			Index)
917 {
918 	PMEASUREMENT_REPORT_ELEMENT	pReport;
919 	PNOISE_HIST_REPORT			pNoise;
920 	PUCHAR						pDest;
921 	UCHAR						i,NoiseCnt;
922 	USHORT						TotalRPICnt, TotalRPISum;
923 
924 	DBGPRINT(RT_DEBUG_TRACE, ("NoiseHistReportAction ----->\n"));
925 
926 	// 0. Disable Rx with promiscuous reception, make it back to normal
927 	RTMP_IO_WRITE32(pAd, RX_FILTR_CFG, STANORMAL); // Staion not drop control frame will fail WiFi Certification.
928 	// 1. Setup pointer for processing beacon & probe response
929 	pDest = (PUCHAR) &pAd->StaCfg.FrameReportBuf[pAd->StaCfg.FrameReportLen];
930 	pReport = (PMEASUREMENT_REPORT_ELEMENT) pDest;
931 
932 	// 2. Fill Measurement report element field.
933 	pReport->Eid    = IE_MEASUREMENT_REPORT;
934 	// Fixed Length at 16, not include Eid and length fields
935 	pReport->Length = 16;
936 	pReport->Token  = pAd->StaCfg.MeasurementRequest[Index].ReqElem.Token;
937 	pReport->Mode   = pAd->StaCfg.MeasurementRequest[Index].ReqElem.Mode;
938 	pReport->Type   = MSRN_TYPE_NOISE_HIST_REQ;
939 
940 	// 3. Fill noise histogram report measurement data
941 	pDest += sizeof(MEASUREMENT_REPORT_ELEMENT);
942 	pNoise  = (PNOISE_HIST_REPORT) pDest;
943 	pNoise->Channel  = pAd->StaCfg.MeasurementRequest[Index].Measurement.Channel;
944 	pNoise->Spare    = 0;
945 	pNoise->Duration = pAd->StaCfg.MeasurementRequest[Index].Measurement.Duration;
946 	// 4. Fill Noise histogram, the total RPI counts should be 0.4 * TU
947 	//    We estimate 4000 normal packets received durning 10 seconds test.
948 	//    Adjust it if required.
949 	// 3 is a good value for pAd->StaCfg.NHFactor
950 	// TotalRPICnt = pNoise->Duration * 3 / 10;
951 	TotalRPICnt = pNoise->Duration * pAd->StaCfg.NHFactor / 10;
952 	TotalRPISum = 0;
953 
954 	for (i = 0; i < 8; i++)
955 	{
956 		TotalRPISum += pAd->StaCfg.RPIDensity[i];
957 		DBGPRINT(RT_DEBUG_TRACE, ("RPI %d Conuts %d\n", i, pAd->StaCfg.RPIDensity[i]));
958 	}
959 
960 	// Double check if the counter is larger than our expectation.
961 	// We will replace it with the total number plus a fraction.
962 	if (TotalRPISum > TotalRPICnt)
963 		TotalRPICnt = TotalRPISum + pNoise->Duration / 20;
964 
965 	DBGPRINT(RT_DEBUG_TRACE, ("Total RPI Conuts %d\n", TotalRPICnt));
966 
967 	// 5. Initialize noise count for the total summation of 0xff
968 	NoiseCnt = 0;
969 	for (i = 1; i < 8; i++)
970 	{
971 		pNoise->Density[i] = (UCHAR) (pAd->StaCfg.RPIDensity[i] * 255 / TotalRPICnt);
972 		if ((pNoise->Density[i] == 0) && (pAd->StaCfg.RPIDensity[i] != 0))
973 			pNoise->Density[i]++;
974 		NoiseCnt += pNoise->Density[i];
975 		DBGPRINT(RT_DEBUG_TRACE, ("Reported RPI[%d]  = 0x%02x\n", i, pNoise->Density[i]));
976 	}
977 
978 	// 6. RPI[0] represents the rest of counts
979 	pNoise->Density[0] = 0xff - NoiseCnt;
980 	DBGPRINT(RT_DEBUG_TRACE, ("Reported RPI[0]  = 0x%02x\n", pNoise->Density[0]));
981 
982 	pAd->StaCfg.FrameReportLen += (sizeof(MEASUREMENT_REPORT_ELEMENT) + sizeof(NOISE_HIST_REPORT));
983 
984 	// 7. Clear channel load measurement flag
985 	RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_MEASUREMENT);
986 
987 	// 8. reset to idle state
988 	pAd->Mlme.AironetMachine.CurrState = AIRONET_IDLE;
989 
990 	DBGPRINT(RT_DEBUG_TRACE, ("NoiseHistReportAction <-----\n"));
991 }
992 
993 /*
994 	========================================================================
995 
996 	Routine Description:
997 		Prepare Beacon report action,
998 
999 	Arguments:
1000 		pAd	Pointer	to our adapter
1001 
1002 	Return Value:
1003 		None
1004 
1005 	Note:
1006 
1007 	========================================================================
1008 */
BeaconReportAction(IN PRTMP_ADAPTER pAd,IN UCHAR Index)1009 VOID	BeaconReportAction(
1010 	IN	PRTMP_ADAPTER	pAd,
1011 	IN	UCHAR			Index)
1012 {
1013 	DBGPRINT(RT_DEBUG_TRACE, ("BeaconReportAction ----->\n"));
1014 
1015 	// Looks like we don't have anything thing need to do here.
1016 	// All measurement report already finished in AddBeaconReport
1017 	// The length is in the FrameReportLen
1018 
1019 	// reset Beacon index for next beacon request
1020 	pAd->StaCfg.LastBssIndex = 0xff;
1021 
1022 	// reset to idle state
1023 	pAd->Mlme.AironetMachine.CurrState = AIRONET_IDLE;
1024 
1025 	DBGPRINT(RT_DEBUG_TRACE, ("BeaconReportAction <-----\n"));
1026 }
1027 
1028 /*
1029 	========================================================================
1030 
1031 	Routine Description:
1032 
1033 	Arguments:
1034 		Index		Current BSSID in CCXBsstab entry index
1035 
1036 	Return Value:
1037 
1038 	Note:
1039 
1040 	========================================================================
1041 */
AironetAddBeaconReport(IN PRTMP_ADAPTER pAd,IN ULONG Index,IN PMLME_QUEUE_ELEM pElem)1042 VOID	AironetAddBeaconReport(
1043 	IN	PRTMP_ADAPTER		pAd,
1044 	IN	ULONG				Index,
1045 	IN	PMLME_QUEUE_ELEM	pElem)
1046 {
1047 	PVOID						pMsg;
1048 	PUCHAR						pSrc, pDest;
1049 	UCHAR						ReqIdx;
1050 	ULONG						MsgLen;
1051 	USHORT						Length;
1052 	PFRAME_802_11				pFrame;
1053 	PMEASUREMENT_REPORT_ELEMENT	pReport;
1054 	PEID_STRUCT			        pEid;
1055 	PBEACON_REPORT				pBeaconReport;
1056 	PBSS_ENTRY					pBss;
1057 
1058 	// 0. Setup pointer for processing beacon & probe response
1059 	pMsg   = pElem->Msg;
1060 	MsgLen = pElem->MsgLen;
1061 	pFrame = (PFRAME_802_11) pMsg;
1062 	pSrc   = pFrame->Octet;				// Start from AP TSF
1063 	pBss   = (PBSS_ENTRY) &pAd->StaCfg.CCXBssTab.BssEntry[Index];
1064 	ReqIdx = pAd->StaCfg.CurrentRMReqIdx;
1065 
1066 	// 1 Check the Index, if we already create this entry, only update the average RSSI
1067 	if ((Index <= pAd->StaCfg.LastBssIndex) && (pAd->StaCfg.LastBssIndex != 0xff))
1068 	{
1069 		pDest  = (PUCHAR) &pAd->StaCfg.FrameReportBuf[pAd->StaCfg.BssReportOffset[Index]];
1070 		// Point to bss report information
1071 		pDest += sizeof(MEASUREMENT_REPORT_ELEMENT);
1072 		pBeaconReport = (PBEACON_REPORT) pDest;
1073 
1074 		// Update Rx power, in dBm
1075 		// Get the original RSSI readback from BBP
1076 		pBeaconReport->RxPower += pAd->BbpRssiToDbmDelta;
1077 		// Average the Rssi reading
1078 		pBeaconReport->RxPower  = (pBeaconReport->RxPower + pBss->Rssi) / 2;
1079 		// Get to dBm format
1080 		pBeaconReport->RxPower -= pAd->BbpRssiToDbmDelta;
1081 
1082 		DBGPRINT(RT_DEBUG_TRACE, ("Bssid %02x:%02x:%02x:%02x:%02x:%02x ",
1083 			pBss->Bssid[0], pBss->Bssid[1], pBss->Bssid[2],
1084 			pBss->Bssid[3], pBss->Bssid[4], pBss->Bssid[5]));
1085 		DBGPRINT(RT_DEBUG_TRACE, ("RxPower[%ld] Rssi %d, Avg Rssi %d\n", Index, (pBss->Rssi - pAd->BbpRssiToDbmDelta), pBeaconReport->RxPower - 256));
1086 		DBGPRINT(RT_DEBUG_TRACE, ("FrameReportLen = %d\n", pAd->StaCfg.BssReportOffset[Index]));
1087 
1088 		// Update other information here
1089 
1090 		// Done
1091 		return;
1092 	}
1093 
1094 	// 2. Update reported Index
1095 	pAd->StaCfg.LastBssIndex = Index;
1096 
1097 	// 3. Setup the buffer address for copying this BSSID into reporting frame
1098 	//    The offset should start after 802.11 header and report frame header.
1099 	pDest = (PUCHAR) &pAd->StaCfg.FrameReportBuf[pAd->StaCfg.FrameReportLen];
1100 
1101 	// 4. Save the start offset of each Bss in report frame
1102 	pAd->StaCfg.BssReportOffset[Index] = pAd->StaCfg.FrameReportLen;
1103 
1104 	// 5. Fill Measurement report fields
1105 	pReport = (PMEASUREMENT_REPORT_ELEMENT) pDest;
1106 	pReport->Eid = IE_MEASUREMENT_REPORT;
1107 	pReport->Length = 0;
1108 	pReport->Token  = pAd->StaCfg.MeasurementRequest[ReqIdx].ReqElem.Token;
1109 	pReport->Mode   = pAd->StaCfg.MeasurementRequest[ReqIdx].ReqElem.Mode;
1110 	pReport->Type   = MSRN_TYPE_BEACON_REQ;
1111 	Length          = sizeof(MEASUREMENT_REPORT_ELEMENT);
1112 	pDest          += sizeof(MEASUREMENT_REPORT_ELEMENT);
1113 
1114 	// 6. Start thebeacon report format
1115 	pBeaconReport = (PBEACON_REPORT) pDest;
1116 	pDest        += sizeof(BEACON_REPORT);
1117 	Length       += sizeof(BEACON_REPORT);
1118 
1119 	// 7. Copy Channel number
1120 	pBeaconReport->Channel        = pBss->Channel;
1121 	pBeaconReport->Spare          = 0;
1122 	pBeaconReport->Duration       = pAd->StaCfg.MeasurementRequest[ReqIdx].Measurement.Duration;
1123 	pBeaconReport->PhyType        = ((pBss->SupRateLen+pBss->ExtRateLen > 4) ? PHY_ERP : PHY_DSS);
1124 	// 8. Rx power, in dBm
1125 	pBeaconReport->RxPower        = pBss->Rssi - pAd->BbpRssiToDbmDelta;
1126 
1127 	DBGPRINT(RT_DEBUG_TRACE, ("Bssid %02x:%02x:%02x:%02x:%02x:%02x ",
1128 		pBss->Bssid[0], pBss->Bssid[1], pBss->Bssid[2],
1129 		pBss->Bssid[3], pBss->Bssid[4], pBss->Bssid[5]));
1130 	DBGPRINT(RT_DEBUG_TRACE, ("RxPower[%ld], Rssi %d\n", Index, pBeaconReport->RxPower - 256));
1131 	DBGPRINT(RT_DEBUG_TRACE, ("FrameReportLen = %d\n", pAd->StaCfg.FrameReportLen));
1132 
1133 	pBeaconReport->BeaconInterval = pBss->BeaconPeriod;
1134 	COPY_MAC_ADDR(pBeaconReport->BSSID, pFrame->Hdr.Addr3);
1135 	NdisMoveMemory(pBeaconReport->ParentTSF, pSrc, 4);
1136 	NdisMoveMemory(pBeaconReport->TargetTSF, &pElem->TimeStamp.u.LowPart, 4);
1137 	NdisMoveMemory(&pBeaconReport->TargetTSF[4], &pElem->TimeStamp.u.HighPart, 4);
1138 
1139 	// 9. Skip the beacon frame and offset to start of capabilityinfo since we already processed capabilityinfo
1140 	pSrc += (TIMESTAMP_LEN + 2);
1141 	pBeaconReport->CapabilityInfo = *(USHORT *)pSrc;
1142 
1143 	// 10. Point to start of element ID
1144 	pSrc += 2;
1145 	pEid = (PEID_STRUCT) pSrc;
1146 
1147 	// 11. Start process all variable Eid oayload and add the appropriate to the frame report
1148 	while (((PUCHAR) pEid + pEid->Len + 1) < ((PUCHAR) pFrame + MsgLen))
1149 	{
1150 		// Only limited EID are required to report for CCX 2. It includes SSID, Supported rate,
1151 		// FH paramenter set, DS parameter set, CF parameter set, IBSS parameter set,
1152 		// TIM (report first 4 bytes only, radio measurement capability
1153 		switch (pEid->Eid)
1154 		{
1155 			case IE_SSID:
1156 			case IE_SUPP_RATES:
1157 			case IE_FH_PARM:
1158 			case IE_DS_PARM:
1159 			case IE_CF_PARM:
1160 			case IE_IBSS_PARM:
1161 				NdisMoveMemory(pDest, pEid, pEid->Len + 2);
1162 				pDest  += (pEid->Len + 2);
1163 				Length += (pEid->Len + 2);
1164 				break;
1165 
1166 			case IE_MEASUREMENT_CAPABILITY:
1167 				// Since this IE is duplicated with WPA security IE, we has to do sanity check before
1168 				// recognize it.
1169 				// 1. It also has fixed 6 bytes IE length.
1170 				if (pEid->Len != 6)
1171 					break;
1172 				// 2. Check the Cisco Aironet OUI
1173 				if (NdisEqualMemory(CISCO_OUI, (pSrc + 2), 3))
1174 				{
1175 					// Matched, this is what we want
1176 					NdisMoveMemory(pDest, pEid, pEid->Len + 2);
1177 					pDest  += (pEid->Len + 2);
1178 					Length += (pEid->Len + 2);
1179 				}
1180 				break;
1181 
1182 			case IE_TIM:
1183 				if (pEid->Len > 4)
1184 				{
1185 					// May truncate and report the first 4 bytes only, with the eid & len, total should be 6
1186 					NdisMoveMemory(pDest, pEid, 6);
1187 					pDest  += 6;
1188 					Length += 6;
1189 				}
1190 				else
1191 				{
1192 					NdisMoveMemory(pDest, pEid, pEid->Len + 2);
1193 					pDest  += (pEid->Len + 2);
1194 					Length += (pEid->Len + 2);
1195 				}
1196 				break;
1197 
1198 			default:
1199 				break;
1200 		}
1201 		// 12. Move to next element ID
1202 		pSrc += (2 + pEid->Len);
1203 		pEid = (PEID_STRUCT) pSrc;
1204 	}
1205 
1206 	// 13. Update the length in the header, not include EID and length
1207 	pReport->Length = Length - 4;
1208 
1209 	// 14. Update the frame report buffer data length
1210 	pAd->StaCfg.FrameReportLen += Length;
1211 	DBGPRINT(RT_DEBUG_TRACE, ("FR len = %d\n", pAd->StaCfg.FrameReportLen));
1212 }
1213 
1214 /*
1215 	========================================================================
1216 
1217 	Routine Description:
1218 
1219 	Arguments:
1220 		Index		Current BSSID in CCXBsstab entry index
1221 
1222 	Return Value:
1223 
1224 	Note:
1225 
1226 	========================================================================
1227 */
AironetCreateBeaconReportFromBssTable(IN PRTMP_ADAPTER pAd)1228 VOID	AironetCreateBeaconReportFromBssTable(
1229 	IN	PRTMP_ADAPTER		pAd)
1230 {
1231 	PMEASUREMENT_REPORT_ELEMENT	pReport;
1232 	PBEACON_REPORT				pBeaconReport;
1233 	UCHAR						Index, ReqIdx;
1234 	USHORT						Length;
1235 	PUCHAR						pDest;
1236 	PBSS_ENTRY					pBss;
1237 
1238 	// 0. setup base pointer
1239 	ReqIdx = pAd->StaCfg.CurrentRMReqIdx;
1240 
1241 	for (Index = 0; Index < pAd->StaCfg.CCXBssTab.BssNr; Index++)
1242 	{
1243 		// 1. Setup the buffer address for copying this BSSID into reporting frame
1244 		//    The offset should start after 802.11 header and report frame header.
1245 		pDest  = (PUCHAR) &pAd->StaCfg.FrameReportBuf[pAd->StaCfg.FrameReportLen];
1246 		pBss   = (PBSS_ENTRY) &pAd->StaCfg.CCXBssTab.BssEntry[Index];
1247 		Length = 0;
1248 
1249 		// 2. Fill Measurement report fields
1250 		pReport         = (PMEASUREMENT_REPORT_ELEMENT) pDest;
1251 		pReport->Eid    = IE_MEASUREMENT_REPORT;
1252 		pReport->Length = 0;
1253 		pReport->Token  = pAd->StaCfg.MeasurementRequest[ReqIdx].ReqElem.Token;
1254 		pReport->Mode   = pAd->StaCfg.MeasurementRequest[ReqIdx].ReqElem.Mode;
1255 		pReport->Type   = MSRN_TYPE_BEACON_REQ;
1256 		Length          = sizeof(MEASUREMENT_REPORT_ELEMENT);
1257 		pDest          += sizeof(MEASUREMENT_REPORT_ELEMENT);
1258 
1259 		// 3. Start the beacon report format
1260 		pBeaconReport = (PBEACON_REPORT) pDest;
1261 		pDest        += sizeof(BEACON_REPORT);
1262 		Length       += sizeof(BEACON_REPORT);
1263 
1264 		// 4. Copy Channel number
1265 		pBeaconReport->Channel        = pBss->Channel;
1266 		pBeaconReport->Spare          = 0;
1267 		pBeaconReport->Duration       = pAd->StaCfg.MeasurementRequest[ReqIdx].Measurement.Duration;
1268 		pBeaconReport->PhyType        = ((pBss->SupRateLen+pBss->ExtRateLen > 4) ? PHY_ERP : PHY_DSS);
1269 		pBeaconReport->RxPower        = pBss->Rssi - pAd->BbpRssiToDbmDelta;
1270 		pBeaconReport->BeaconInterval = pBss->BeaconPeriod;
1271 		pBeaconReport->CapabilityInfo = pBss->CapabilityInfo;
1272 		COPY_MAC_ADDR(pBeaconReport->BSSID, pBss->Bssid);
1273 		NdisMoveMemory(pBeaconReport->ParentTSF, pBss->PTSF, 4);
1274 		NdisMoveMemory(pBeaconReport->TargetTSF, pBss->TTSF, 8);
1275 
1276 		// 5. Create SSID
1277 		*pDest++ = 0x00;
1278 		*pDest++ = pBss->SsidLen;
1279 		NdisMoveMemory(pDest, pBss->Ssid, pBss->SsidLen);
1280 		pDest  += pBss->SsidLen;
1281 		Length += (2 + pBss->SsidLen);
1282 
1283 		// 6. Create SupportRates
1284 		*pDest++ = 0x01;
1285 		*pDest++ = pBss->SupRateLen;
1286 		NdisMoveMemory(pDest, pBss->SupRate, pBss->SupRateLen);
1287 		pDest  += pBss->SupRateLen;
1288 		Length += (2 + pBss->SupRateLen);
1289 
1290 		// 7. DS Parameter
1291 		*pDest++ = 0x03;
1292 		*pDest++ = 1;
1293 		*pDest++ = pBss->Channel;
1294 		Length  += 3;
1295 
1296 		// 8. IBSS parameter if presents
1297 		if (pBss->BssType == BSS_ADHOC)
1298 		{
1299 			*pDest++ = 0x06;
1300 			*pDest++ = 2;
1301 			*(PUSHORT) pDest = pBss->AtimWin;
1302 			pDest   += 2;
1303 			Length  += 4;
1304 		}
1305 
1306 		// 9. Update length field, not include EID and length
1307 		pReport->Length = Length - 4;
1308 
1309 		// 10. Update total frame size
1310 		pAd->StaCfg.FrameReportLen += Length;
1311 	}
1312 }
1313