• 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 
28     Module Name:
29 	action.c
30 
31     Abstract:
32     Handle association related requests either from WSTA or from local MLME
33 
34     Revision History:
35     Who          When          What
36     ---------    ----------    ----------------------------------------------
37 	Fonchi Wu    2008	  	   created for 802.11h
38  */
39 
40 #include "../rt_config.h"
41 #include "action.h"
42 
MeasureReqTabInit(IN PRTMP_ADAPTER pAd)43 VOID MeasureReqTabInit(
44 	IN PRTMP_ADAPTER pAd)
45 {
46 	NdisAllocateSpinLock(&pAd->CommonCfg.MeasureReqTabLock);
47 
48 	pAd->CommonCfg.pMeasureReqTab = kmalloc(sizeof(MEASURE_REQ_TAB), GFP_ATOMIC);
49 	if (pAd->CommonCfg.pMeasureReqTab)
50 		NdisZeroMemory(pAd->CommonCfg.pMeasureReqTab, sizeof(MEASURE_REQ_TAB));
51 	else
52 		DBGPRINT(RT_DEBUG_ERROR, ("%s Fail to alloc memory for pAd->CommonCfg.pMeasureReqTab.\n", __func__));
53 
54 	return;
55 }
56 
MeasureReqTabExit(IN PRTMP_ADAPTER pAd)57 VOID MeasureReqTabExit(
58 	IN PRTMP_ADAPTER pAd)
59 {
60 	NdisFreeSpinLock(pAd->CommonCfg.MeasureReqTabLock);
61 
62 	if (pAd->CommonCfg.pMeasureReqTab)
63 		kfree(pAd->CommonCfg.pMeasureReqTab);
64 	pAd->CommonCfg.pMeasureReqTab = NULL;
65 
66 	return;
67 }
68 
MeasureReqLookUp(IN PRTMP_ADAPTER pAd,IN UINT8 DialogToken)69 static PMEASURE_REQ_ENTRY MeasureReqLookUp(
70 	IN PRTMP_ADAPTER	pAd,
71 	IN UINT8			DialogToken)
72 {
73 	UINT HashIdx;
74 	PMEASURE_REQ_TAB pTab = pAd->CommonCfg.pMeasureReqTab;
75 	PMEASURE_REQ_ENTRY pEntry = NULL;
76 	PMEASURE_REQ_ENTRY pPrevEntry = NULL;
77 
78 	if (pTab == NULL)
79 	{
80 		DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab doesn't exist.\n", __func__));
81 		return NULL;
82 	}
83 
84 	RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock);
85 
86 	HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(DialogToken);
87 	pEntry = pTab->Hash[HashIdx];
88 
89 	while (pEntry)
90 	{
91 		if (pEntry->DialogToken == DialogToken)
92 			break;
93 		else
94 		{
95 			pPrevEntry = pEntry;
96 			pEntry = pEntry->pNext;
97 		}
98 	}
99 
100 	RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock);
101 
102 	return pEntry;
103 }
104 
MeasureReqInsert(IN PRTMP_ADAPTER pAd,IN UINT8 DialogToken)105 static PMEASURE_REQ_ENTRY MeasureReqInsert(
106 	IN PRTMP_ADAPTER	pAd,
107 	IN UINT8			DialogToken)
108 {
109 	INT i;
110 	ULONG HashIdx;
111 	PMEASURE_REQ_TAB pTab = pAd->CommonCfg.pMeasureReqTab;
112 	PMEASURE_REQ_ENTRY pEntry = NULL, pCurrEntry;
113 	ULONG Now;
114 
115 	if(pTab == NULL)
116 	{
117 		DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab doesn't exist.\n", __func__));
118 		return NULL;
119 	}
120 
121 	pEntry = MeasureReqLookUp(pAd, DialogToken);
122 	if (pEntry == NULL)
123 	{
124 		RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock);
125 		for (i = 0; i < MAX_MEASURE_REQ_TAB_SIZE; i++)
126 		{
127 			NdisGetSystemUpTime(&Now);
128 			pEntry = &pTab->Content[i];
129 
130 			if ((pEntry->Valid == TRUE)
131 				&& RTMP_TIME_AFTER((unsigned long)Now, (unsigned long)(pEntry->lastTime + MQ_REQ_AGE_OUT)))
132 			{
133 				PMEASURE_REQ_ENTRY pPrevEntry = NULL;
134 				ULONG HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken);
135 				PMEASURE_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx];
136 
137 				// update Hash list
138 				do
139 				{
140 					if (pProbeEntry == pEntry)
141 					{
142 						if (pPrevEntry == NULL)
143 						{
144 							pTab->Hash[HashIdx] = pEntry->pNext;
145 						}
146 						else
147 						{
148 							pPrevEntry->pNext = pEntry->pNext;
149 						}
150 						break;
151 					}
152 
153 					pPrevEntry = pProbeEntry;
154 					pProbeEntry = pProbeEntry->pNext;
155 				} while (pProbeEntry);
156 
157 				NdisZeroMemory(pEntry, sizeof(MEASURE_REQ_ENTRY));
158 				pTab->Size--;
159 
160 				break;
161 			}
162 
163 			if (pEntry->Valid == FALSE)
164 				break;
165 		}
166 
167 		if (i < MAX_MEASURE_REQ_TAB_SIZE)
168 		{
169 			NdisGetSystemUpTime(&Now);
170 			pEntry->lastTime = Now;
171 			pEntry->Valid = TRUE;
172 			pEntry->DialogToken = DialogToken;
173 			pTab->Size++;
174 		}
175 		else
176 		{
177 			pEntry = NULL;
178 			DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab tab full.\n", __func__));
179 		}
180 
181 		// add this Neighbor entry into HASH table
182 		if (pEntry)
183 		{
184 			HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(DialogToken);
185 			if (pTab->Hash[HashIdx] == NULL)
186 			{
187 				pTab->Hash[HashIdx] = pEntry;
188 			}
189 			else
190 			{
191 				pCurrEntry = pTab->Hash[HashIdx];
192 				while (pCurrEntry->pNext != NULL)
193 					pCurrEntry = pCurrEntry->pNext;
194 				pCurrEntry->pNext = pEntry;
195 			}
196 		}
197 
198 		RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock);
199 	}
200 
201 	return pEntry;
202 }
203 
MeasureReqDelete(IN PRTMP_ADAPTER pAd,IN UINT8 DialogToken)204 static VOID MeasureReqDelete(
205 	IN PRTMP_ADAPTER	pAd,
206 	IN UINT8			DialogToken)
207 {
208 	PMEASURE_REQ_TAB pTab = pAd->CommonCfg.pMeasureReqTab;
209 	PMEASURE_REQ_ENTRY pEntry = NULL;
210 
211 	if(pTab == NULL)
212 	{
213 		DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab doesn't exist.\n", __func__));
214 		return;
215 	}
216 
217 	// if empty, return
218 	if (pTab->Size == 0)
219 	{
220 		DBGPRINT(RT_DEBUG_ERROR, ("pMeasureReqTab empty.\n"));
221 		return;
222 	}
223 
224 	pEntry = MeasureReqLookUp(pAd, DialogToken);
225 	if (pEntry != NULL)
226 	{
227 		PMEASURE_REQ_ENTRY pPrevEntry = NULL;
228 		ULONG HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken);
229 		PMEASURE_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx];
230 
231 		RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock);
232 		// update Hash list
233 		do
234 		{
235 			if (pProbeEntry == pEntry)
236 			{
237 				if (pPrevEntry == NULL)
238 				{
239 					pTab->Hash[HashIdx] = pEntry->pNext;
240 				}
241 				else
242 				{
243 					pPrevEntry->pNext = pEntry->pNext;
244 				}
245 				break;
246 			}
247 
248 			pPrevEntry = pProbeEntry;
249 			pProbeEntry = pProbeEntry->pNext;
250 		} while (pProbeEntry);
251 
252 		NdisZeroMemory(pEntry, sizeof(MEASURE_REQ_ENTRY));
253 		pTab->Size--;
254 
255 		RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock);
256 	}
257 
258 	return;
259 }
260 
TpcReqTabInit(IN PRTMP_ADAPTER pAd)261 VOID TpcReqTabInit(
262 	IN PRTMP_ADAPTER pAd)
263 {
264 	NdisAllocateSpinLock(&pAd->CommonCfg.TpcReqTabLock);
265 
266 	pAd->CommonCfg.pTpcReqTab = kmalloc(sizeof(TPC_REQ_TAB), GFP_ATOMIC);
267 	if (pAd->CommonCfg.pTpcReqTab)
268 		NdisZeroMemory(pAd->CommonCfg.pTpcReqTab, sizeof(TPC_REQ_TAB));
269 	else
270 		DBGPRINT(RT_DEBUG_ERROR, ("%s Fail to alloc memory for pAd->CommonCfg.pTpcReqTab.\n", __func__));
271 
272 	return;
273 }
274 
TpcReqTabExit(IN PRTMP_ADAPTER pAd)275 VOID TpcReqTabExit(
276 	IN PRTMP_ADAPTER pAd)
277 {
278 	NdisFreeSpinLock(pAd->CommonCfg.TpcReqTabLock);
279 
280 	if (pAd->CommonCfg.pTpcReqTab)
281 		kfree(pAd->CommonCfg.pTpcReqTab);
282 	pAd->CommonCfg.pTpcReqTab = NULL;
283 
284 	return;
285 }
286 
TpcReqLookUp(IN PRTMP_ADAPTER pAd,IN UINT8 DialogToken)287 static PTPC_REQ_ENTRY TpcReqLookUp(
288 	IN PRTMP_ADAPTER	pAd,
289 	IN UINT8			DialogToken)
290 {
291 	UINT HashIdx;
292 	PTPC_REQ_TAB pTab = pAd->CommonCfg.pTpcReqTab;
293 	PTPC_REQ_ENTRY pEntry = NULL;
294 	PTPC_REQ_ENTRY pPrevEntry = NULL;
295 
296 	if (pTab == NULL)
297 	{
298 		DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab doesn't exist.\n", __func__));
299 		return NULL;
300 	}
301 
302 	RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock);
303 
304 	HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(DialogToken);
305 	pEntry = pTab->Hash[HashIdx];
306 
307 	while (pEntry)
308 	{
309 		if (pEntry->DialogToken == DialogToken)
310 			break;
311 		else
312 		{
313 			pPrevEntry = pEntry;
314 			pEntry = pEntry->pNext;
315 		}
316 	}
317 
318 	RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock);
319 
320 	return pEntry;
321 }
322 
323 
TpcReqInsert(IN PRTMP_ADAPTER pAd,IN UINT8 DialogToken)324 static PTPC_REQ_ENTRY TpcReqInsert(
325 	IN PRTMP_ADAPTER	pAd,
326 	IN UINT8			DialogToken)
327 {
328 	INT i;
329 	ULONG HashIdx;
330 	PTPC_REQ_TAB pTab = pAd->CommonCfg.pTpcReqTab;
331 	PTPC_REQ_ENTRY pEntry = NULL, pCurrEntry;
332 	ULONG Now;
333 
334 	if(pTab == NULL)
335 	{
336 		DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab doesn't exist.\n", __func__));
337 		return NULL;
338 	}
339 
340 	pEntry = TpcReqLookUp(pAd, DialogToken);
341 	if (pEntry == NULL)
342 	{
343 		RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock);
344 		for (i = 0; i < MAX_TPC_REQ_TAB_SIZE; i++)
345 		{
346 			NdisGetSystemUpTime(&Now);
347 			pEntry = &pTab->Content[i];
348 
349 			if ((pEntry->Valid == TRUE)
350 				&& RTMP_TIME_AFTER((unsigned long)Now, (unsigned long)(pEntry->lastTime + TPC_REQ_AGE_OUT)))
351 			{
352 				PTPC_REQ_ENTRY pPrevEntry = NULL;
353 				ULONG HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken);
354 				PTPC_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx];
355 
356 				// update Hash list
357 				do
358 				{
359 					if (pProbeEntry == pEntry)
360 					{
361 						if (pPrevEntry == NULL)
362 						{
363 							pTab->Hash[HashIdx] = pEntry->pNext;
364 						}
365 						else
366 						{
367 							pPrevEntry->pNext = pEntry->pNext;
368 						}
369 						break;
370 					}
371 
372 					pPrevEntry = pProbeEntry;
373 					pProbeEntry = pProbeEntry->pNext;
374 				} while (pProbeEntry);
375 
376 				NdisZeroMemory(pEntry, sizeof(TPC_REQ_ENTRY));
377 				pTab->Size--;
378 
379 				break;
380 			}
381 
382 			if (pEntry->Valid == FALSE)
383 				break;
384 		}
385 
386 		if (i < MAX_TPC_REQ_TAB_SIZE)
387 		{
388 			NdisGetSystemUpTime(&Now);
389 			pEntry->lastTime = Now;
390 			pEntry->Valid = TRUE;
391 			pEntry->DialogToken = DialogToken;
392 			pTab->Size++;
393 		}
394 		else
395 		{
396 			pEntry = NULL;
397 			DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab tab full.\n", __func__));
398 		}
399 
400 		// add this Neighbor entry into HASH table
401 		if (pEntry)
402 		{
403 			HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(DialogToken);
404 			if (pTab->Hash[HashIdx] == NULL)
405 			{
406 				pTab->Hash[HashIdx] = pEntry;
407 			}
408 			else
409 			{
410 				pCurrEntry = pTab->Hash[HashIdx];
411 				while (pCurrEntry->pNext != NULL)
412 					pCurrEntry = pCurrEntry->pNext;
413 				pCurrEntry->pNext = pEntry;
414 			}
415 		}
416 
417 		RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock);
418 	}
419 
420 	return pEntry;
421 }
422 
TpcReqDelete(IN PRTMP_ADAPTER pAd,IN UINT8 DialogToken)423 static VOID TpcReqDelete(
424 	IN PRTMP_ADAPTER	pAd,
425 	IN UINT8			DialogToken)
426 {
427 	PTPC_REQ_TAB pTab = pAd->CommonCfg.pTpcReqTab;
428 	PTPC_REQ_ENTRY pEntry = NULL;
429 
430 	if(pTab == NULL)
431 	{
432 		DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab doesn't exist.\n", __func__));
433 		return;
434 	}
435 
436 	// if empty, return
437 	if (pTab->Size == 0)
438 	{
439 		DBGPRINT(RT_DEBUG_ERROR, ("pTpcReqTab empty.\n"));
440 		return;
441 	}
442 
443 	pEntry = TpcReqLookUp(pAd, DialogToken);
444 	if (pEntry != NULL)
445 	{
446 		PTPC_REQ_ENTRY pPrevEntry = NULL;
447 		ULONG HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken);
448 		PTPC_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx];
449 
450 		RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock);
451 		// update Hash list
452 		do
453 		{
454 			if (pProbeEntry == pEntry)
455 			{
456 				if (pPrevEntry == NULL)
457 				{
458 					pTab->Hash[HashIdx] = pEntry->pNext;
459 				}
460 				else
461 				{
462 					pPrevEntry->pNext = pEntry->pNext;
463 				}
464 				break;
465 			}
466 
467 			pPrevEntry = pProbeEntry;
468 			pProbeEntry = pProbeEntry->pNext;
469 		} while (pProbeEntry);
470 
471 		NdisZeroMemory(pEntry, sizeof(TPC_REQ_ENTRY));
472 		pTab->Size--;
473 
474 		RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock);
475 	}
476 
477 	return;
478 }
479 
480 /*
481 	==========================================================================
482 	Description:
483 		Get Current TimeS tamp.
484 
485 	Parametrs:
486 
487 	Return	: Current Time Stamp.
488 	==========================================================================
489  */
GetCurrentTimeStamp(IN PRTMP_ADAPTER pAd)490 static UINT64 GetCurrentTimeStamp(
491 	IN PRTMP_ADAPTER pAd)
492 {
493 	// get current time stamp.
494 	return 0;
495 }
496 
497 /*
498 	==========================================================================
499 	Description:
500 		Get Current Transmit Power.
501 
502 	Parametrs:
503 
504 	Return	: Current Time Stamp.
505 	==========================================================================
506  */
GetCurTxPwr(IN PRTMP_ADAPTER pAd,IN UINT8 Wcid)507 static UINT8 GetCurTxPwr(
508 	IN PRTMP_ADAPTER pAd,
509 	IN UINT8 Wcid)
510 {
511 	return 16; /* 16 dBm */
512 }
513 
514 /*
515 	==========================================================================
516 	Description:
517 		Insert Dialog Token into frame.
518 
519 	Parametrs:
520 		1. frame buffer pointer.
521 		2. frame length.
522 		3. Dialog token.
523 
524 	Return	: None.
525 	==========================================================================
526  */
InsertDialogToken(IN PRTMP_ADAPTER pAd,OUT PUCHAR pFrameBuf,OUT PULONG pFrameLen,IN UINT8 DialogToken)527 static VOID InsertDialogToken(
528 	IN PRTMP_ADAPTER pAd,
529 	OUT PUCHAR pFrameBuf,
530 	OUT PULONG pFrameLen,
531 	IN UINT8 DialogToken)
532 {
533 	ULONG TempLen;
534 	MakeOutgoingFrame(pFrameBuf,	&TempLen,
535 					1,				&DialogToken,
536 					END_OF_ARGS);
537 
538 	*pFrameLen = *pFrameLen + TempLen;
539 
540 	return;
541 }
542 
543 /*
544 	==========================================================================
545 	Description:
546 		Insert TPC Request IE into frame.
547 
548 	Parametrs:
549 		1. frame buffer pointer.
550 		2. frame length.
551 
552 	Return	: None.
553 	==========================================================================
554  */
InsertTpcReqIE(IN PRTMP_ADAPTER pAd,OUT PUCHAR pFrameBuf,OUT PULONG pFrameLen)555  static VOID InsertTpcReqIE(
556 	IN PRTMP_ADAPTER pAd,
557 	OUT PUCHAR pFrameBuf,
558 	OUT PULONG pFrameLen)
559 {
560 	ULONG TempLen;
561 	ULONG Len = 0;
562 	UINT8 ElementID = IE_TPC_REQUEST;
563 
564 	MakeOutgoingFrame(pFrameBuf,					&TempLen,
565 						1,							&ElementID,
566 						1,							&Len,
567 						END_OF_ARGS);
568 
569 	*pFrameLen = *pFrameLen + TempLen;
570 
571 	return;
572 }
573 
574 /*
575 	==========================================================================
576 	Description:
577 		Insert TPC Report IE into frame.
578 
579 	Parametrs:
580 		1. frame buffer pointer.
581 		2. frame length.
582 		3. Transmit Power.
583 		4. Link Margin.
584 
585 	Return	: None.
586 	==========================================================================
587  */
InsertTpcReportIE(IN PRTMP_ADAPTER pAd,OUT PUCHAR pFrameBuf,OUT PULONG pFrameLen,IN UINT8 TxPwr,IN UINT8 LinkMargin)588  static VOID InsertTpcReportIE(
589 	IN PRTMP_ADAPTER pAd,
590 	OUT PUCHAR pFrameBuf,
591 	OUT PULONG pFrameLen,
592 	IN UINT8 TxPwr,
593 	IN UINT8 LinkMargin)
594 {
595 	ULONG TempLen;
596 	ULONG Len = sizeof(TPC_REPORT_INFO);
597 	UINT8 ElementID = IE_TPC_REPORT;
598 	TPC_REPORT_INFO TpcReportIE;
599 
600 	TpcReportIE.TxPwr = TxPwr;
601 	TpcReportIE.LinkMargin = LinkMargin;
602 
603 	MakeOutgoingFrame(pFrameBuf,					&TempLen,
604 						1,							&ElementID,
605 						1,							&Len,
606 						Len,						&TpcReportIE,
607 						END_OF_ARGS);
608 
609 	*pFrameLen = *pFrameLen + TempLen;
610 
611 
612 	return;
613 }
614 
615 /*
616 	==========================================================================
617 	Description:
618 		Insert Channel Switch Announcement IE into frame.
619 
620 	Parametrs:
621 		1. frame buffer pointer.
622 		2. frame length.
623 		3. channel switch announcement mode.
624 		4. new selected channel.
625 		5. channel switch announcement count.
626 
627 	Return	: None.
628 	==========================================================================
629  */
InsertChSwAnnIE(IN PRTMP_ADAPTER pAd,OUT PUCHAR pFrameBuf,OUT PULONG pFrameLen,IN UINT8 ChSwMode,IN UINT8 NewChannel,IN UINT8 ChSwCnt)630 static VOID InsertChSwAnnIE(
631 	IN PRTMP_ADAPTER pAd,
632 	OUT PUCHAR pFrameBuf,
633 	OUT PULONG pFrameLen,
634 	IN UINT8 ChSwMode,
635 	IN UINT8 NewChannel,
636 	IN UINT8 ChSwCnt)
637 {
638 	ULONG TempLen;
639 	ULONG Len = sizeof(CH_SW_ANN_INFO);
640 	UINT8 ElementID = IE_CHANNEL_SWITCH_ANNOUNCEMENT;
641 	CH_SW_ANN_INFO ChSwAnnIE;
642 
643 	ChSwAnnIE.ChSwMode = ChSwMode;
644 	ChSwAnnIE.Channel = NewChannel;
645 	ChSwAnnIE.ChSwCnt = ChSwCnt;
646 
647 	MakeOutgoingFrame(pFrameBuf,				&TempLen,
648 						1,						&ElementID,
649 						1,						&Len,
650 						Len,					&ChSwAnnIE,
651 						END_OF_ARGS);
652 
653 	*pFrameLen = *pFrameLen + TempLen;
654 
655 
656 	return;
657 }
658 
659 /*
660 	==========================================================================
661 	Description:
662 		Insert Measure Request IE into frame.
663 
664 	Parametrs:
665 		1. frame buffer pointer.
666 		2. frame length.
667 		3. Measure Token.
668 		4. Measure Request Mode.
669 		5. Measure Request Type.
670 		6. Measure Channel.
671 		7. Measure Start time.
672 		8. Measure Duration.
673 
674 
675 	Return	: None.
676 	==========================================================================
677  */
InsertMeasureReqIE(IN PRTMP_ADAPTER pAd,OUT PUCHAR pFrameBuf,OUT PULONG pFrameLen,IN PMEASURE_REQ_INFO pMeasureReqIE)678 static VOID InsertMeasureReqIE(
679 	IN PRTMP_ADAPTER pAd,
680 	OUT PUCHAR pFrameBuf,
681 	OUT PULONG pFrameLen,
682 	IN PMEASURE_REQ_INFO pMeasureReqIE)
683 {
684 	ULONG TempLen;
685 	UINT8 Len = sizeof(MEASURE_REQ_INFO);
686 	UINT8 ElementID = IE_MEASUREMENT_REQUEST;
687 
688 	MakeOutgoingFrame(pFrameBuf,					&TempLen,
689 						1,							&ElementID,
690 						1,							&Len,
691 						Len,						pMeasureReqIE,
692 						END_OF_ARGS);
693 
694 	*pFrameLen = *pFrameLen + TempLen;
695 
696 	return;
697 }
698 
699 /*
700 	==========================================================================
701 	Description:
702 		Insert Measure Report IE into frame.
703 
704 	Parametrs:
705 		1. frame buffer pointer.
706 		2. frame length.
707 		3. Measure Token.
708 		4. Measure Request Mode.
709 		5. Measure Request Type.
710 		6. Length of Report Infomation
711 		7. Pointer of Report Infomation Buffer.
712 
713 	Return	: None.
714 	==========================================================================
715  */
InsertMeasureReportIE(IN PRTMP_ADAPTER pAd,OUT PUCHAR pFrameBuf,OUT PULONG pFrameLen,IN PMEASURE_REPORT_INFO pMeasureReportIE,IN UINT8 ReportLnfoLen,IN PUINT8 pReportInfo)716 static VOID InsertMeasureReportIE(
717 	IN PRTMP_ADAPTER pAd,
718 	OUT PUCHAR pFrameBuf,
719 	OUT PULONG pFrameLen,
720 	IN PMEASURE_REPORT_INFO pMeasureReportIE,
721 	IN UINT8 ReportLnfoLen,
722 	IN PUINT8 pReportInfo)
723 {
724 	ULONG TempLen;
725 	ULONG Len;
726 	UINT8 ElementID = IE_MEASUREMENT_REPORT;
727 
728 	Len = sizeof(MEASURE_REPORT_INFO) + ReportLnfoLen;
729 
730 	MakeOutgoingFrame(pFrameBuf,					&TempLen,
731 						1,							&ElementID,
732 						1,							&Len,
733 						Len,						pMeasureReportIE,
734 						END_OF_ARGS);
735 
736 	*pFrameLen = *pFrameLen + TempLen;
737 
738 	if ((ReportLnfoLen > 0) && (pReportInfo != NULL))
739 	{
740 		MakeOutgoingFrame(pFrameBuf + *pFrameLen,		&TempLen,
741 							ReportLnfoLen,				pReportInfo,
742 							END_OF_ARGS);
743 
744 		*pFrameLen = *pFrameLen + TempLen;
745 	}
746 	return;
747 }
748 
749 /*
750 	==========================================================================
751 	Description:
752 		Prepare Measurement request action frame and enqueue it into
753 		management queue waiting for transmition.
754 
755 	Parametrs:
756 		1. the destination mac address of the frame.
757 
758 	Return	: None.
759 	==========================================================================
760  */
EnqueueMeasurementReq(IN PRTMP_ADAPTER pAd,IN PUCHAR pDA,IN UINT8 MeasureToken,IN UINT8 MeasureReqMode,IN UINT8 MeasureReqType,IN UINT8 MeasureCh,IN UINT16 MeasureDuration)761 VOID EnqueueMeasurementReq(
762 	IN PRTMP_ADAPTER pAd,
763 	IN PUCHAR pDA,
764 	IN UINT8 MeasureToken,
765 	IN UINT8 MeasureReqMode,
766 	IN UINT8 MeasureReqType,
767 	IN UINT8 MeasureCh,
768 	IN UINT16 MeasureDuration)
769 {
770 	PUCHAR pOutBuffer = NULL;
771 	NDIS_STATUS NStatus;
772 	ULONG FrameLen;
773 	HEADER_802_11 ActHdr;
774 	MEASURE_REQ_INFO MeasureReqIE;
775 	UINT8 RmReqDailogToken = RandomByte(pAd);
776 	UINT64 MeasureStartTime = GetCurrentTimeStamp(pAd);
777 
778 	// build action frame header.
779 	MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
780 						pAd->CurrentAddress);
781 
782 	NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer);  //Get an unused nonpaged memory
783 	if(NStatus != NDIS_STATUS_SUCCESS)
784 	{
785 		DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __func__));
786 		return;
787 	}
788 	NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11));
789 	FrameLen = sizeof(HEADER_802_11);
790 
791 	InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_MRQ);
792 
793 	// fill Dialog Token
794 	InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, MeasureToken);
795 
796 	// prepare Measurement IE.
797 	NdisZeroMemory(&MeasureReqIE, sizeof(MEASURE_REQ_INFO));
798 	MeasureReqIE.Token = RmReqDailogToken;
799 	MeasureReqIE.ReqMode.word = MeasureReqMode;
800 	MeasureReqIE.ReqType = MeasureReqType;
801 	MeasureReqIE.MeasureReq.ChNum = MeasureCh;
802 	MeasureReqIE.MeasureReq.MeasureStartTime = cpu2le64(MeasureStartTime);
803 	MeasureReqIE.MeasureReq.MeasureDuration = cpu2le16(MeasureDuration);
804 	InsertMeasureReqIE(pAd, (pOutBuffer + FrameLen), &FrameLen, &MeasureReqIE);
805 
806 	MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
807 	MlmeFreeMemory(pAd, pOutBuffer);
808 
809 	return;
810 }
811 
812 /*
813 	==========================================================================
814 	Description:
815 		Prepare Measurement report action frame and enqueue it into
816 		management queue waiting for transmition.
817 
818 	Parametrs:
819 		1. the destination mac address of the frame.
820 
821 	Return	: None.
822 	==========================================================================
823  */
EnqueueMeasurementRep(IN PRTMP_ADAPTER pAd,IN PUCHAR pDA,IN UINT8 DialogToken,IN UINT8 MeasureToken,IN UINT8 MeasureReqMode,IN UINT8 MeasureReqType,IN UINT8 ReportInfoLen,IN PUINT8 pReportInfo)824 VOID EnqueueMeasurementRep(
825 	IN PRTMP_ADAPTER pAd,
826 	IN PUCHAR pDA,
827 	IN UINT8 DialogToken,
828 	IN UINT8 MeasureToken,
829 	IN UINT8 MeasureReqMode,
830 	IN UINT8 MeasureReqType,
831 	IN UINT8 ReportInfoLen,
832 	IN PUINT8 pReportInfo)
833 {
834 	PUCHAR pOutBuffer = NULL;
835 	NDIS_STATUS NStatus;
836 	ULONG FrameLen;
837 	HEADER_802_11 ActHdr;
838 	MEASURE_REPORT_INFO MeasureRepIE;
839 
840 	// build action frame header.
841 	MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
842 						pAd->CurrentAddress);
843 
844 	NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer);  //Get an unused nonpaged memory
845 	if(NStatus != NDIS_STATUS_SUCCESS)
846 	{
847 		DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __func__));
848 		return;
849 	}
850 	NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11));
851 	FrameLen = sizeof(HEADER_802_11);
852 
853 	InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_MRP);
854 
855 	// fill Dialog Token
856 	InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken);
857 
858 	// prepare Measurement IE.
859 	NdisZeroMemory(&MeasureRepIE, sizeof(MEASURE_REPORT_INFO));
860 	MeasureRepIE.Token = MeasureToken;
861 	MeasureRepIE.ReportMode.word = MeasureReqMode;
862 	MeasureRepIE.ReportType = MeasureReqType;
863 	InsertMeasureReportIE(pAd, (pOutBuffer + FrameLen), &FrameLen, &MeasureRepIE, ReportInfoLen, pReportInfo);
864 
865 	MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
866 	MlmeFreeMemory(pAd, pOutBuffer);
867 
868 	return;
869 }
870 
871 /*
872 	==========================================================================
873 	Description:
874 		Prepare TPC Request action frame and enqueue it into
875 		management queue waiting for transmition.
876 
877 	Parametrs:
878 		1. the destination mac address of the frame.
879 
880 	Return	: None.
881 	==========================================================================
882  */
EnqueueTPCReq(IN PRTMP_ADAPTER pAd,IN PUCHAR pDA,IN UCHAR DialogToken)883 VOID EnqueueTPCReq(
884 	IN PRTMP_ADAPTER pAd,
885 	IN PUCHAR pDA,
886 	IN UCHAR DialogToken)
887 {
888 	PUCHAR pOutBuffer = NULL;
889 	NDIS_STATUS NStatus;
890 	ULONG FrameLen;
891 
892 	HEADER_802_11 ActHdr;
893 
894 	// build action frame header.
895 	MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
896 						pAd->CurrentAddress);
897 
898 	NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer);  //Get an unused nonpaged memory
899 	if(NStatus != NDIS_STATUS_SUCCESS)
900 	{
901 		DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __func__));
902 		return;
903 	}
904 	NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11));
905 	FrameLen = sizeof(HEADER_802_11);
906 
907 	InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_TPCRQ);
908 
909 	// fill Dialog Token
910 	InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken);
911 
912 	// Insert TPC Request IE.
913 	InsertTpcReqIE(pAd, (pOutBuffer + FrameLen), &FrameLen);
914 
915 	MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
916 	MlmeFreeMemory(pAd, pOutBuffer);
917 
918 	return;
919 }
920 
921 /*
922 	==========================================================================
923 	Description:
924 		Prepare TPC Report action frame and enqueue it into
925 		management queue waiting for transmition.
926 
927 	Parametrs:
928 		1. the destination mac address of the frame.
929 
930 	Return	: None.
931 	==========================================================================
932  */
EnqueueTPCRep(IN PRTMP_ADAPTER pAd,IN PUCHAR pDA,IN UINT8 DialogToken,IN UINT8 TxPwr,IN UINT8 LinkMargin)933 VOID EnqueueTPCRep(
934 	IN PRTMP_ADAPTER pAd,
935 	IN PUCHAR pDA,
936 	IN UINT8 DialogToken,
937 	IN UINT8 TxPwr,
938 	IN UINT8 LinkMargin)
939 {
940 	PUCHAR pOutBuffer = NULL;
941 	NDIS_STATUS NStatus;
942 	ULONG FrameLen;
943 
944 	HEADER_802_11 ActHdr;
945 
946 	// build action frame header.
947 	MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
948 						pAd->CurrentAddress);
949 
950 	NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer);  //Get an unused nonpaged memory
951 	if(NStatus != NDIS_STATUS_SUCCESS)
952 	{
953 		DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __func__));
954 		return;
955 	}
956 	NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11));
957 	FrameLen = sizeof(HEADER_802_11);
958 
959 	InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_TPCRP);
960 
961 	// fill Dialog Token
962 	InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken);
963 
964 	// Insert TPC Request IE.
965 	InsertTpcReportIE(pAd, (pOutBuffer + FrameLen), &FrameLen, TxPwr, LinkMargin);
966 
967 	MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
968 	MlmeFreeMemory(pAd, pOutBuffer);
969 
970 	return;
971 }
972 
973 /*
974 	==========================================================================
975 	Description:
976 		Prepare Channel Switch Announcement action frame and enqueue it into
977 		management queue waiting for transmition.
978 
979 	Parametrs:
980 		1. the destination mac address of the frame.
981 		2. Channel switch announcement mode.
982 		2. a New selected channel.
983 
984 	Return	: None.
985 	==========================================================================
986  */
EnqueueChSwAnn(IN PRTMP_ADAPTER pAd,IN PUCHAR pDA,IN UINT8 ChSwMode,IN UINT8 NewCh)987 VOID EnqueueChSwAnn(
988 	IN PRTMP_ADAPTER pAd,
989 	IN PUCHAR pDA,
990 	IN UINT8 ChSwMode,
991 	IN UINT8 NewCh)
992 {
993 	PUCHAR pOutBuffer = NULL;
994 	NDIS_STATUS NStatus;
995 	ULONG FrameLen;
996 
997 	HEADER_802_11 ActHdr;
998 
999 	// build action frame header.
1000 	MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
1001 						pAd->CurrentAddress);
1002 
1003 	NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer);  //Get an unused nonpaged memory
1004 	if(NStatus != NDIS_STATUS_SUCCESS)
1005 	{
1006 		DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __func__));
1007 		return;
1008 	}
1009 	NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11));
1010 	FrameLen = sizeof(HEADER_802_11);
1011 
1012 	InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_CHANNEL_SWITCH);
1013 
1014 	InsertChSwAnnIE(pAd, (pOutBuffer + FrameLen), &FrameLen, ChSwMode, NewCh, 0);
1015 
1016 	MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1017 	MlmeFreeMemory(pAd, pOutBuffer);
1018 
1019 	return;
1020 }
1021 
DfsRequirementCheck(IN PRTMP_ADAPTER pAd,IN UINT8 Channel)1022 static BOOLEAN DfsRequirementCheck(
1023 	IN PRTMP_ADAPTER pAd,
1024 	IN UINT8 Channel)
1025 {
1026 	BOOLEAN Result = FALSE;
1027 	INT i;
1028 
1029 	do
1030 	{
1031 		// check DFS procedure is running.
1032 		// make sure DFS procedure won't start twice.
1033 		if (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)
1034 		{
1035 			Result = FALSE;
1036 			break;
1037 		}
1038 
1039 		// check the new channel carried from Channel Switch Announcemnet is valid.
1040 		for (i=0; i<pAd->ChannelListNum; i++)
1041 		{
1042 			if ((Channel == pAd->ChannelList[i].Channel)
1043 				&&(pAd->ChannelList[i].RemainingTimeForUse == 0))
1044 			{
1045 				// found radar signal in the channel. the channel can't use at least for 30 minutes.
1046 				pAd->ChannelList[i].RemainingTimeForUse = 1800;//30 min = 1800 sec
1047 				Result = TRUE;
1048 				break;
1049 			}
1050 		}
1051 	} while(FALSE);
1052 
1053 	return Result;
1054 }
1055 
NotifyChSwAnnToPeerAPs(IN PRTMP_ADAPTER pAd,IN PUCHAR pRA,IN PUCHAR pTA,IN UINT8 ChSwMode,IN UINT8 Channel)1056 VOID NotifyChSwAnnToPeerAPs(
1057 	IN PRTMP_ADAPTER pAd,
1058 	IN PUCHAR pRA,
1059 	IN PUCHAR pTA,
1060 	IN UINT8 ChSwMode,
1061 	IN UINT8 Channel)
1062 {
1063 #ifdef WDS_SUPPORT
1064 	if (!((pRA[0] & 0xff) == 0xff)) // is pRA a broadcase address.
1065 	{
1066 		INT i;
1067 		// info neighbor APs that Radar signal found throgh WDS link.
1068 		for (i = 0; i < MAX_WDS_ENTRY; i++)
1069 		{
1070 			if (ValidWdsEntry(pAd, i))
1071 			{
1072 				PUCHAR pDA = pAd->WdsTab.WdsEntry[i].PeerWdsAddr;
1073 
1074 				// DA equal to SA. have no necessary orignal AP which found Radar signal.
1075 				if (MAC_ADDR_EQUAL(pTA, pDA))
1076 					continue;
1077 
1078 				// send Channel Switch Action frame to info Neighbro APs.
1079 				EnqueueChSwAnn(pAd, pDA, ChSwMode, Channel);
1080 			}
1081 		}
1082 	}
1083 #endif // WDS_SUPPORT //
1084 }
1085 
StartDFSProcedure(IN PRTMP_ADAPTER pAd,IN UCHAR Channel,IN UINT8 ChSwMode)1086 static VOID StartDFSProcedure(
1087 	IN PRTMP_ADAPTER pAd,
1088 	IN UCHAR Channel,
1089 	IN UINT8 ChSwMode)
1090 {
1091 	// start DFS procedure
1092 	pAd->CommonCfg.Channel = Channel;
1093 #ifdef DOT11_N_SUPPORT
1094 	N_ChannelCheck(pAd);
1095 #endif // DOT11_N_SUPPORT //
1096 	pAd->CommonCfg.RadarDetect.RDMode = RD_SWITCHING_MODE;
1097 	pAd->CommonCfg.RadarDetect.CSCount = 0;
1098 }
1099 
1100 /*
1101 	==========================================================================
1102 	Description:
1103 		Channel Switch Announcement action frame sanity check.
1104 
1105 	Parametrs:
1106 		1. MLME message containing the received frame
1107 		2. message length.
1108 		3. Channel switch announcement infomation buffer.
1109 
1110 
1111 	Return	: None.
1112 	==========================================================================
1113  */
1114 
1115 /*
1116   Channel Switch Announcement IE.
1117   +----+-----+-----------+------------+-----------+
1118   | ID | Len |Ch Sw Mode | New Ch Num | Ch Sw Cnt |
1119   +----+-----+-----------+------------+-----------+
1120     1    1        1           1            1
1121 */
PeerChSwAnnSanity(IN PRTMP_ADAPTER pAd,IN VOID * pMsg,IN ULONG MsgLen,OUT PCH_SW_ANN_INFO pChSwAnnInfo)1122 static BOOLEAN PeerChSwAnnSanity(
1123 	IN PRTMP_ADAPTER pAd,
1124 	IN VOID *pMsg,
1125 	IN ULONG MsgLen,
1126 	OUT PCH_SW_ANN_INFO pChSwAnnInfo)
1127 {
1128 	PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
1129 	PUCHAR pFramePtr = Fr->Octet;
1130 	BOOLEAN result = FALSE;
1131 	PEID_STRUCT eid_ptr;
1132 
1133 	// skip 802.11 header.
1134 	MsgLen -= sizeof(HEADER_802_11);
1135 
1136 	// skip category and action code.
1137 	pFramePtr += 2;
1138 	MsgLen -= 2;
1139 
1140 	if (pChSwAnnInfo == NULL)
1141 		return result;
1142 
1143 	eid_ptr = (PEID_STRUCT)pFramePtr;
1144 	while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
1145 	{
1146 		switch(eid_ptr->Eid)
1147 		{
1148 			case IE_CHANNEL_SWITCH_ANNOUNCEMENT:
1149 				NdisMoveMemory(&pChSwAnnInfo->ChSwMode, eid_ptr->Octet, 1);
1150 				NdisMoveMemory(&pChSwAnnInfo->Channel, eid_ptr->Octet + 1, 1);
1151 				NdisMoveMemory(&pChSwAnnInfo->ChSwCnt, eid_ptr->Octet + 2, 1);
1152 
1153 				result = TRUE;
1154                 break;
1155 
1156 			default:
1157 				break;
1158 		}
1159 		eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
1160 	}
1161 
1162 	return result;
1163 }
1164 
1165 /*
1166 	==========================================================================
1167 	Description:
1168 		Measurement request action frame sanity check.
1169 
1170 	Parametrs:
1171 		1. MLME message containing the received frame
1172 		2. message length.
1173 		3. Measurement request infomation buffer.
1174 
1175 	Return	: None.
1176 	==========================================================================
1177  */
PeerMeasureReqSanity(IN PRTMP_ADAPTER pAd,IN VOID * pMsg,IN ULONG MsgLen,OUT PUINT8 pDialogToken,OUT PMEASURE_REQ_INFO pMeasureReqInfo)1178 static BOOLEAN PeerMeasureReqSanity(
1179 	IN PRTMP_ADAPTER pAd,
1180 	IN VOID *pMsg,
1181 	IN ULONG MsgLen,
1182 	OUT PUINT8 pDialogToken,
1183 	OUT PMEASURE_REQ_INFO pMeasureReqInfo)
1184 {
1185 	PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
1186 	PUCHAR pFramePtr = Fr->Octet;
1187 	BOOLEAN result = FALSE;
1188 	PEID_STRUCT eid_ptr;
1189 	PUCHAR ptr;
1190 	UINT64 MeasureStartTime;
1191 	UINT16 MeasureDuration;
1192 
1193 	// skip 802.11 header.
1194 	MsgLen -= sizeof(HEADER_802_11);
1195 
1196 	// skip category and action code.
1197 	pFramePtr += 2;
1198 	MsgLen -= 2;
1199 
1200 	if (pMeasureReqInfo == NULL)
1201 		return result;
1202 
1203 	NdisMoveMemory(pDialogToken, pFramePtr, 1);
1204 	pFramePtr += 1;
1205 	MsgLen -= 1;
1206 
1207 	eid_ptr = (PEID_STRUCT)pFramePtr;
1208 	while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
1209 	{
1210 		switch(eid_ptr->Eid)
1211 		{
1212 			case IE_MEASUREMENT_REQUEST:
1213 				NdisMoveMemory(&pMeasureReqInfo->Token, eid_ptr->Octet, 1);
1214 				NdisMoveMemory(&pMeasureReqInfo->ReqMode.word, eid_ptr->Octet + 1, 1);
1215 				NdisMoveMemory(&pMeasureReqInfo->ReqType, eid_ptr->Octet + 2, 1);
1216 				ptr = eid_ptr->Octet + 3;
1217 				NdisMoveMemory(&pMeasureReqInfo->MeasureReq.ChNum, ptr, 1);
1218 				NdisMoveMemory(&MeasureStartTime, ptr + 1, 8);
1219 				pMeasureReqInfo->MeasureReq.MeasureStartTime = SWAP64(MeasureStartTime);
1220 				NdisMoveMemory(&MeasureDuration, ptr + 9, 2);
1221 				pMeasureReqInfo->MeasureReq.MeasureDuration = SWAP16(MeasureDuration);
1222 
1223 				result = TRUE;
1224 				break;
1225 
1226 			default:
1227 				break;
1228 		}
1229 		eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
1230 	}
1231 
1232 	return result;
1233 }
1234 
1235 /*
1236 	==========================================================================
1237 	Description:
1238 		Measurement report action frame sanity check.
1239 
1240 	Parametrs:
1241 		1. MLME message containing the received frame
1242 		2. message length.
1243 		3. Measurement report infomation buffer.
1244 		4. basic report infomation buffer.
1245 
1246 	Return	: None.
1247 	==========================================================================
1248  */
1249 
1250 /*
1251   Measurement Report IE.
1252   +----+-----+-------+-------------+--------------+----------------+
1253   | ID | Len | Token | Report Mode | Measure Type | Measure Report |
1254   +----+-----+-------+-------------+--------------+----------------+
1255     1     1      1          1             1            variable
1256 
1257   Basic Report.
1258   +--------+------------+----------+-----+
1259   | Ch Num | Start Time | Duration | Map |
1260   +--------+------------+----------+-----+
1261       1          8           2        1
1262 
1263   Map Field Bit Format.
1264   +-----+---------------+---------------------+-------+------------+----------+
1265   | Bss | OFDM Preamble | Unidentified signal | Radar | Unmeasured | Reserved |
1266   +-----+---------------+---------------------+-------+------------+----------+
1267      0          1                  2              3         4          5-7
1268 */
PeerMeasureReportSanity(IN PRTMP_ADAPTER pAd,IN VOID * pMsg,IN ULONG MsgLen,OUT PUINT8 pDialogToken,OUT PMEASURE_REPORT_INFO pMeasureReportInfo,OUT PUINT8 pReportBuf)1269 static BOOLEAN PeerMeasureReportSanity(
1270 	IN PRTMP_ADAPTER pAd,
1271 	IN VOID *pMsg,
1272 	IN ULONG MsgLen,
1273 	OUT PUINT8 pDialogToken,
1274 	OUT PMEASURE_REPORT_INFO pMeasureReportInfo,
1275 	OUT PUINT8 pReportBuf)
1276 {
1277 	PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
1278 	PUCHAR pFramePtr = Fr->Octet;
1279 	BOOLEAN result = FALSE;
1280 	PEID_STRUCT eid_ptr;
1281 	PUCHAR ptr;
1282 
1283 	// skip 802.11 header.
1284 	MsgLen -= sizeof(HEADER_802_11);
1285 
1286 	// skip category and action code.
1287 	pFramePtr += 2;
1288 	MsgLen -= 2;
1289 
1290 	if (pMeasureReportInfo == NULL)
1291 		return result;
1292 
1293 	NdisMoveMemory(pDialogToken, pFramePtr, 1);
1294 	pFramePtr += 1;
1295 	MsgLen -= 1;
1296 
1297 	eid_ptr = (PEID_STRUCT)pFramePtr;
1298 	while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
1299 	{
1300 		switch(eid_ptr->Eid)
1301 		{
1302 			case IE_MEASUREMENT_REPORT:
1303 				NdisMoveMemory(&pMeasureReportInfo->Token, eid_ptr->Octet, 1);
1304 				NdisMoveMemory(&pMeasureReportInfo->ReportMode, eid_ptr->Octet + 1, 1);
1305 				NdisMoveMemory(&pMeasureReportInfo->ReportType, eid_ptr->Octet + 2, 1);
1306 				if (pMeasureReportInfo->ReportType == RM_BASIC)
1307 				{
1308 					PMEASURE_BASIC_REPORT pReport = (PMEASURE_BASIC_REPORT)pReportBuf;
1309 					ptr = eid_ptr->Octet + 3;
1310 					NdisMoveMemory(&pReport->ChNum, ptr, 1);
1311 					NdisMoveMemory(&pReport->MeasureStartTime, ptr + 1, 8);
1312 					NdisMoveMemory(&pReport->MeasureDuration, ptr + 9, 2);
1313 					NdisMoveMemory(&pReport->Map, ptr + 11, 1);
1314 
1315 				}
1316 				else if (pMeasureReportInfo->ReportType == RM_CCA)
1317 				{
1318 					PMEASURE_CCA_REPORT pReport = (PMEASURE_CCA_REPORT)pReportBuf;
1319 					ptr = eid_ptr->Octet + 3;
1320 					NdisMoveMemory(&pReport->ChNum, ptr, 1);
1321 					NdisMoveMemory(&pReport->MeasureStartTime, ptr + 1, 8);
1322 					NdisMoveMemory(&pReport->MeasureDuration, ptr + 9, 2);
1323 					NdisMoveMemory(&pReport->CCA_Busy_Fraction, ptr + 11, 1);
1324 
1325 				}
1326 				else if (pMeasureReportInfo->ReportType == RM_RPI_HISTOGRAM)
1327 				{
1328 					PMEASURE_RPI_REPORT pReport = (PMEASURE_RPI_REPORT)pReportBuf;
1329 					ptr = eid_ptr->Octet + 3;
1330 					NdisMoveMemory(&pReport->ChNum, ptr, 1);
1331 					NdisMoveMemory(&pReport->MeasureStartTime, ptr + 1, 8);
1332 					NdisMoveMemory(&pReport->MeasureDuration, ptr + 9, 2);
1333 					NdisMoveMemory(&pReport->RPI_Density, ptr + 11, 8);
1334 				}
1335 				result = TRUE;
1336                 break;
1337 
1338 			default:
1339 				break;
1340 		}
1341 		eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
1342 	}
1343 
1344 	return result;
1345 }
1346 
1347 /*
1348 	==========================================================================
1349 	Description:
1350 		TPC Request action frame sanity check.
1351 
1352 	Parametrs:
1353 		1. MLME message containing the received frame
1354 		2. message length.
1355 		3. Dialog Token.
1356 
1357 	Return	: None.
1358 	==========================================================================
1359  */
PeerTpcReqSanity(IN PRTMP_ADAPTER pAd,IN VOID * pMsg,IN ULONG MsgLen,OUT PUINT8 pDialogToken)1360 static BOOLEAN PeerTpcReqSanity(
1361 	IN PRTMP_ADAPTER pAd,
1362 	IN VOID *pMsg,
1363 	IN ULONG MsgLen,
1364 	OUT PUINT8 pDialogToken)
1365 {
1366 	PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
1367 	PUCHAR pFramePtr = Fr->Octet;
1368 	BOOLEAN result = FALSE;
1369 	PEID_STRUCT eid_ptr;
1370 
1371 	MsgLen -= sizeof(HEADER_802_11);
1372 
1373 	// skip category and action code.
1374 	pFramePtr += 2;
1375 	MsgLen -= 2;
1376 
1377 	if (pDialogToken == NULL)
1378 		return result;
1379 
1380 	NdisMoveMemory(pDialogToken, pFramePtr, 1);
1381 	pFramePtr += 1;
1382 	MsgLen -= 1;
1383 
1384 	eid_ptr = (PEID_STRUCT)pFramePtr;
1385 	while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
1386 	{
1387 		switch(eid_ptr->Eid)
1388 		{
1389 			case IE_TPC_REQUEST:
1390 				result = TRUE;
1391                 break;
1392 
1393 			default:
1394 				break;
1395 		}
1396 		eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
1397 	}
1398 
1399 	return result;
1400 }
1401 
1402 /*
1403 	==========================================================================
1404 	Description:
1405 		TPC Report action frame sanity check.
1406 
1407 	Parametrs:
1408 		1. MLME message containing the received frame
1409 		2. message length.
1410 		3. Dialog Token.
1411 		4. TPC Report IE.
1412 
1413 	Return	: None.
1414 	==========================================================================
1415  */
PeerTpcRepSanity(IN PRTMP_ADAPTER pAd,IN VOID * pMsg,IN ULONG MsgLen,OUT PUINT8 pDialogToken,OUT PTPC_REPORT_INFO pTpcRepInfo)1416 static BOOLEAN PeerTpcRepSanity(
1417 	IN PRTMP_ADAPTER pAd,
1418 	IN VOID *pMsg,
1419 	IN ULONG MsgLen,
1420 	OUT PUINT8 pDialogToken,
1421 	OUT PTPC_REPORT_INFO pTpcRepInfo)
1422 {
1423 	PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
1424 	PUCHAR pFramePtr = Fr->Octet;
1425 	BOOLEAN result = FALSE;
1426 	PEID_STRUCT eid_ptr;
1427 
1428 	MsgLen -= sizeof(HEADER_802_11);
1429 
1430 	// skip category and action code.
1431 	pFramePtr += 2;
1432 	MsgLen -= 2;
1433 
1434 	if (pDialogToken == NULL)
1435 		return result;
1436 
1437 	NdisMoveMemory(pDialogToken, pFramePtr, 1);
1438 	pFramePtr += 1;
1439 	MsgLen -= 1;
1440 
1441 	eid_ptr = (PEID_STRUCT)pFramePtr;
1442 	while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
1443 	{
1444 		switch(eid_ptr->Eid)
1445 		{
1446 			case IE_TPC_REPORT:
1447 				NdisMoveMemory(&pTpcRepInfo->TxPwr, eid_ptr->Octet, 1);
1448 				NdisMoveMemory(&pTpcRepInfo->LinkMargin, eid_ptr->Octet + 1, 1);
1449 				result = TRUE;
1450                 break;
1451 
1452 			default:
1453 				break;
1454 		}
1455 		eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
1456 	}
1457 
1458 	return result;
1459 }
1460 
1461 /*
1462 	==========================================================================
1463 	Description:
1464 		Channel Switch Announcement action frame handler.
1465 
1466 	Parametrs:
1467 		Elme - MLME message containing the received frame
1468 
1469 	Return	: None.
1470 	==========================================================================
1471  */
PeerChSwAnnAction(IN PRTMP_ADAPTER pAd,IN MLME_QUEUE_ELEM * Elem)1472 static VOID PeerChSwAnnAction(
1473 	IN PRTMP_ADAPTER pAd,
1474 	IN MLME_QUEUE_ELEM *Elem)
1475 {
1476 	CH_SW_ANN_INFO ChSwAnnInfo;
1477 	PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg;
1478 #ifdef CONFIG_STA_SUPPORT
1479 	UCHAR index = 0, Channel = 0, NewChannel = 0;
1480 	ULONG Bssidx = 0;
1481 #endif // CONFIG_STA_SUPPORT //
1482 
1483 	NdisZeroMemory(&ChSwAnnInfo, sizeof(CH_SW_ANN_INFO));
1484 	if (! PeerChSwAnnSanity(pAd, Elem->Msg, Elem->MsgLen, &ChSwAnnInfo))
1485 	{
1486 		DBGPRINT(RT_DEBUG_TRACE, ("Invalid Channel Switch Action Frame.\n"));
1487 		return;
1488 	}
1489 
1490 
1491 #ifdef CONFIG_STA_SUPPORT
1492 	if (pAd->OpMode == OPMODE_STA)
1493 	{
1494 		Bssidx = BssTableSearch(&pAd->ScanTab, pFr->Hdr.Addr3, pAd->CommonCfg.Channel);
1495 		if (Bssidx == BSS_NOT_FOUND)
1496 		{
1497 			DBGPRINT(RT_DEBUG_TRACE, ("PeerChSwAnnAction - Bssidx is not found\n"));
1498 			return;
1499 		}
1500 
1501 		DBGPRINT(RT_DEBUG_TRACE, ("\n****Bssidx is %d, Channel = %d\n", index, pAd->ScanTab.BssEntry[Bssidx].Channel));
1502 		hex_dump("SSID",pAd->ScanTab.BssEntry[Bssidx].Bssid ,6);
1503 
1504 		Channel = pAd->CommonCfg.Channel;
1505 		NewChannel = ChSwAnnInfo.Channel;
1506 
1507 		if ((pAd->CommonCfg.bIEEE80211H == 1) && (NewChannel != 0) && (Channel != NewChannel))
1508 		{
1509 			// Switching to channel 1 can prevent from rescanning the current channel immediately (by auto reconnection).
1510 			// In addition, clear the MLME queue and the scan table to discard the RX packets and previous scanning results.
1511 			AsicSwitchChannel(pAd, 1, FALSE);
1512 			AsicLockChannel(pAd, 1);
1513 		    LinkDown(pAd, FALSE);
1514 			MlmeQueueInit(&pAd->Mlme.Queue);
1515 			BssTableInit(&pAd->ScanTab);
1516 		    RTMPusecDelay(1000000);		// use delay to prevent STA do reassoc
1517 
1518 			// channel sanity check
1519 			for (index = 0 ; index < pAd->ChannelListNum; index++)
1520 			{
1521 				if (pAd->ChannelList[index].Channel == NewChannel)
1522 				{
1523 					pAd->ScanTab.BssEntry[Bssidx].Channel = NewChannel;
1524 					pAd->CommonCfg.Channel = NewChannel;
1525 					AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
1526 					AsicLockChannel(pAd, pAd->CommonCfg.Channel);
1527 					DBGPRINT(RT_DEBUG_TRACE, ("&&&&&&&&&&&&&&&&PeerChSwAnnAction - STA receive channel switch announcement IE (New Channel =%d)\n", NewChannel));
1528 					break;
1529 				}
1530 			}
1531 
1532 			if (index >= pAd->ChannelListNum)
1533 			{
1534 				DBGPRINT_ERR(("&&&&&&&&&&&&&&&&&&&&&&&&&&PeerChSwAnnAction(can not find New Channel=%d in ChannelList[%d]\n", pAd->CommonCfg.Channel, pAd->ChannelListNum));
1535 			}
1536 		}
1537 	}
1538 #endif // CONFIG_STA_SUPPORT //
1539 
1540 	return;
1541 }
1542 
1543 
1544 /*
1545 	==========================================================================
1546 	Description:
1547 		Measurement Request action frame handler.
1548 
1549 	Parametrs:
1550 		Elme - MLME message containing the received frame
1551 
1552 	Return	: None.
1553 	==========================================================================
1554  */
PeerMeasureReqAction(IN PRTMP_ADAPTER pAd,IN MLME_QUEUE_ELEM * Elem)1555 static VOID PeerMeasureReqAction(
1556 	IN PRTMP_ADAPTER pAd,
1557 	IN MLME_QUEUE_ELEM *Elem)
1558 {
1559 	PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg;
1560 	UINT8 DialogToken;
1561 	MEASURE_REQ_INFO MeasureReqInfo;
1562 	MEASURE_REPORT_MODE ReportMode;
1563 
1564 	if(PeerMeasureReqSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &MeasureReqInfo))
1565 	{
1566 		ReportMode.word = 0;
1567 		ReportMode.field.Incapable = 1;
1568 		EnqueueMeasurementRep(pAd, pFr->Hdr.Addr2, DialogToken, MeasureReqInfo.Token, ReportMode.word, MeasureReqInfo.ReqType, 0, NULL);
1569 	}
1570 
1571 	return;
1572 }
1573 
1574 /*
1575 	==========================================================================
1576 	Description:
1577 		Measurement Report action frame handler.
1578 
1579 	Parametrs:
1580 		Elme - MLME message containing the received frame
1581 
1582 	Return	: None.
1583 	==========================================================================
1584  */
PeerMeasureReportAction(IN PRTMP_ADAPTER pAd,IN MLME_QUEUE_ELEM * Elem)1585 static VOID PeerMeasureReportAction(
1586 	IN PRTMP_ADAPTER pAd,
1587 	IN MLME_QUEUE_ELEM *Elem)
1588 {
1589 	MEASURE_REPORT_INFO MeasureReportInfo;
1590 	PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg;
1591 	UINT8 DialogToken;
1592 	PUINT8 pMeasureReportInfo;
1593 
1594 //	if (pAd->CommonCfg.bIEEE80211H != TRUE)
1595 //		return;
1596 
1597 	if ((pMeasureReportInfo = kmalloc(sizeof(MEASURE_RPI_REPORT), GFP_ATOMIC)) == NULL)
1598 	{
1599 		DBGPRINT(RT_DEBUG_ERROR, ("%s unable to alloc memory for measure report buffer (size=%d).\n", __func__, sizeof(MEASURE_RPI_REPORT)));
1600 		return;
1601 	}
1602 
1603 	NdisZeroMemory(&MeasureReportInfo, sizeof(MEASURE_REPORT_INFO));
1604 	NdisZeroMemory(pMeasureReportInfo, sizeof(MEASURE_RPI_REPORT));
1605 	if (PeerMeasureReportSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &MeasureReportInfo, pMeasureReportInfo))
1606 	{
1607 		do {
1608 			PMEASURE_REQ_ENTRY pEntry = NULL;
1609 
1610 			// Not a autonomous measure report.
1611 			// check the dialog token field. drop it if the dialog token doesn't match.
1612 			if ((DialogToken != 0)
1613 				&& ((pEntry = MeasureReqLookUp(pAd, DialogToken)) == NULL))
1614 				break;
1615 
1616 			if (pEntry != NULL)
1617 				MeasureReqDelete(pAd, pEntry->DialogToken);
1618 
1619 			if (MeasureReportInfo.ReportType == RM_BASIC)
1620 			{
1621 				PMEASURE_BASIC_REPORT pBasicReport = (PMEASURE_BASIC_REPORT)pMeasureReportInfo;
1622 				if ((pBasicReport->Map.field.Radar)
1623 					&& (DfsRequirementCheck(pAd, pBasicReport->ChNum) == TRUE))
1624 				{
1625 					NotifyChSwAnnToPeerAPs(pAd, pFr->Hdr.Addr1, pFr->Hdr.Addr2, 1, pBasicReport->ChNum);
1626 					StartDFSProcedure(pAd, pBasicReport->ChNum, 1);
1627 				}
1628 			}
1629 		} while (FALSE);
1630 	}
1631 	else
1632 		DBGPRINT(RT_DEBUG_TRACE, ("Invalid Measurement Report Frame.\n"));
1633 
1634 	kfree(pMeasureReportInfo);
1635 
1636 	return;
1637 }
1638 
1639 /*
1640 	==========================================================================
1641 	Description:
1642 		TPC Request action frame handler.
1643 
1644 	Parametrs:
1645 		Elme - MLME message containing the received frame
1646 
1647 	Return	: None.
1648 	==========================================================================
1649  */
PeerTpcReqAction(IN PRTMP_ADAPTER pAd,IN MLME_QUEUE_ELEM * Elem)1650 static VOID PeerTpcReqAction(
1651 	IN PRTMP_ADAPTER pAd,
1652 	IN MLME_QUEUE_ELEM *Elem)
1653 {
1654 	PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg;
1655 	PUCHAR pFramePtr = pFr->Octet;
1656 	UINT8 DialogToken;
1657 	UINT8 TxPwr = GetCurTxPwr(pAd, Elem->Wcid);
1658 	UINT8 LinkMargin = 0;
1659 	CHAR RealRssi;
1660 
1661 	// link margin: Ratio of the received signal power to the minimum desired by the station (STA). The
1662 	//				STA may incorporate rate information and channel conditions, including interference, into its computation
1663 	//				of link margin.
1664 
1665 	RealRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0),
1666 								ConvertToRssi(pAd, Elem->Rssi1, RSSI_1),
1667 								ConvertToRssi(pAd, Elem->Rssi2, RSSI_2));
1668 
1669 	// skip Category and action code.
1670 	pFramePtr += 2;
1671 
1672 	// Dialog token.
1673 	NdisMoveMemory(&DialogToken, pFramePtr, 1);
1674 
1675 	LinkMargin = (RealRssi / MIN_RCV_PWR);
1676 	if (PeerTpcReqSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken))
1677 		EnqueueTPCRep(pAd, pFr->Hdr.Addr2, DialogToken, TxPwr, LinkMargin);
1678 
1679 	return;
1680 }
1681 
1682 /*
1683 	==========================================================================
1684 	Description:
1685 		TPC Report action frame handler.
1686 
1687 	Parametrs:
1688 		Elme - MLME message containing the received frame
1689 
1690 	Return	: None.
1691 	==========================================================================
1692  */
PeerTpcRepAction(IN PRTMP_ADAPTER pAd,IN MLME_QUEUE_ELEM * Elem)1693 static VOID PeerTpcRepAction(
1694 	IN PRTMP_ADAPTER pAd,
1695 	IN MLME_QUEUE_ELEM *Elem)
1696 {
1697 	UINT8 DialogToken;
1698 	TPC_REPORT_INFO TpcRepInfo;
1699 	PTPC_REQ_ENTRY pEntry = NULL;
1700 
1701 	NdisZeroMemory(&TpcRepInfo, sizeof(TPC_REPORT_INFO));
1702 	if (PeerTpcRepSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &TpcRepInfo))
1703 	{
1704 		if ((pEntry = TpcReqLookUp(pAd, DialogToken)) != NULL)
1705 		{
1706 			TpcReqDelete(pAd, pEntry->DialogToken);
1707 			DBGPRINT(RT_DEBUG_TRACE, ("%s: DialogToken=%x, TxPwr=%d, LinkMargin=%d\n",
1708 				__func__, DialogToken, TpcRepInfo.TxPwr, TpcRepInfo.LinkMargin));
1709 		}
1710 	}
1711 
1712 	return;
1713 }
1714 
1715 /*
1716 	==========================================================================
1717 	Description:
1718 		Spectrun action frames Handler such as channel switch annoucement,
1719 		measurement report, measurement request actions frames.
1720 
1721 	Parametrs:
1722 		Elme - MLME message containing the received frame
1723 
1724 	Return	: None.
1725 	==========================================================================
1726  */
PeerSpectrumAction(IN PRTMP_ADAPTER pAd,IN MLME_QUEUE_ELEM * Elem)1727 VOID PeerSpectrumAction(
1728 	IN PRTMP_ADAPTER pAd,
1729 	IN MLME_QUEUE_ELEM *Elem)
1730 {
1731 
1732 	UCHAR	Action = Elem->Msg[LENGTH_802_11+1];
1733 
1734 	if (pAd->CommonCfg.bIEEE80211H != TRUE)
1735 		return;
1736 
1737 	switch(Action)
1738 	{
1739 		case SPEC_MRQ:
1740 			// current rt2860 unable do such measure specified in Measurement Request.
1741 			// reject all measurement request.
1742 			PeerMeasureReqAction(pAd, Elem);
1743 			break;
1744 
1745 		case SPEC_MRP:
1746 			PeerMeasureReportAction(pAd, Elem);
1747 			break;
1748 
1749 		case SPEC_TPCRQ:
1750 			PeerTpcReqAction(pAd, Elem);
1751 			break;
1752 
1753 		case SPEC_TPCRP:
1754 			PeerTpcRepAction(pAd, Elem);
1755 			break;
1756 
1757 		case SPEC_CHANNEL_SWITCH:
1758 {
1759 #ifdef DOT11N_DRAFT3
1760 				SEC_CHA_OFFSET_IE	Secondary;
1761 				CHA_SWITCH_ANNOUNCE_IE	ChannelSwitch;
1762 
1763 				// 802.11h only has Channel Switch Announcement IE.
1764 				RTMPMoveMemory(&ChannelSwitch, &Elem->Msg[LENGTH_802_11+4], sizeof (CHA_SWITCH_ANNOUNCE_IE));
1765 
1766 				// 802.11n D3.03 adds secondary channel offset element in the end.
1767 				if (Elem->MsgLen ==  (LENGTH_802_11 + 2 + sizeof (CHA_SWITCH_ANNOUNCE_IE) + sizeof (SEC_CHA_OFFSET_IE)))
1768 				{
1769 					RTMPMoveMemory(&Secondary, &Elem->Msg[LENGTH_802_11+9], sizeof (SEC_CHA_OFFSET_IE));
1770 				}
1771 				else
1772 				{
1773 					Secondary.SecondaryChannelOffset = 0;
1774 				}
1775 
1776 				if ((Elem->Msg[LENGTH_802_11+2] == IE_CHANNEL_SWITCH_ANNOUNCEMENT) && (Elem->Msg[LENGTH_802_11+3] == 3))
1777 				{
1778 					ChannelSwitchAction(pAd, Elem->Wcid, ChannelSwitch.NewChannel, Secondary.SecondaryChannelOffset);
1779 				}
1780 #endif // DOT11N_DRAFT3 //
1781 }
1782 			PeerChSwAnnAction(pAd, Elem);
1783 			break;
1784 	}
1785 
1786 	return;
1787 }
1788 
1789 /*
1790 	==========================================================================
1791 	Description:
1792 
1793 	Parametrs:
1794 
1795 	Return	: None.
1796 	==========================================================================
1797  */
Set_MeasureReq_Proc(IN PRTMP_ADAPTER pAd,IN PUCHAR arg)1798 INT Set_MeasureReq_Proc(
1799 	IN	PRTMP_ADAPTER	pAd,
1800 	IN	PUCHAR			arg)
1801 {
1802 	UINT Aid = 1;
1803 	UINT ArgIdx;
1804 	PUCHAR thisChar;
1805 
1806 	MEASURE_REQ_MODE MeasureReqMode;
1807 	UINT8 MeasureReqToken = RandomByte(pAd);
1808 	UINT8 MeasureReqType = RM_BASIC;
1809 	UINT8 MeasureCh = 1;
1810 
1811 	ArgIdx = 1;
1812 	while ((thisChar = strsep((char **)&arg, "-")) != NULL)
1813 	{
1814 		switch(ArgIdx)
1815 		{
1816 			case 1:	// Aid.
1817 				Aid = simple_strtol(thisChar, 0, 16);
1818 				break;
1819 
1820 			case 2: // Measurement Request Type.
1821 				MeasureReqType = simple_strtol(thisChar, 0, 16);
1822 				if (MeasureReqType > 3)
1823 				{
1824 					DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow MeasureReqType(%d)\n", __func__, MeasureReqType));
1825 					return TRUE;
1826 				}
1827 				break;
1828 
1829 			case 3: // Measurement channel.
1830 				MeasureCh = simple_strtol(thisChar, 0, 16);
1831 				break;
1832 		}
1833 		ArgIdx++;
1834 	}
1835 
1836 	DBGPRINT(RT_DEBUG_TRACE, ("%s::Aid = %d, MeasureReqType=%d MeasureCh=%d\n", __func__, Aid, MeasureReqType, MeasureCh));
1837 	if (!VALID_WCID(Aid))
1838 	{
1839 		DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow sta of Aid(%d)\n", __func__, Aid));
1840 		return TRUE;
1841 	}
1842 
1843 	MeasureReqMode.word = 0;
1844 	MeasureReqMode.field.Enable = 1;
1845 
1846 	MeasureReqInsert(pAd, MeasureReqToken);
1847 
1848 	EnqueueMeasurementReq(pAd, pAd->MacTab.Content[Aid].Addr,
1849 		MeasureReqToken, MeasureReqMode.word, MeasureReqType, MeasureCh, 2000);
1850 
1851 	return TRUE;
1852 }
1853 
Set_TpcReq_Proc(IN PRTMP_ADAPTER pAd,IN PUCHAR arg)1854 INT Set_TpcReq_Proc(
1855 	IN	PRTMP_ADAPTER	pAd,
1856 	IN	PUCHAR			arg)
1857 {
1858 	UINT Aid;
1859 
1860 	UINT8 TpcReqToken = RandomByte(pAd);
1861 
1862 	Aid = simple_strtol(arg, 0, 16);
1863 
1864 	DBGPRINT(RT_DEBUG_TRACE, ("%s::Aid = %d\n", __func__, Aid));
1865 	if (!VALID_WCID(Aid))
1866 	{
1867 		DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow sta of Aid(%d)\n", __func__, Aid));
1868 		return TRUE;
1869 	}
1870 
1871 	TpcReqInsert(pAd, TpcReqToken);
1872 
1873 	EnqueueTPCReq(pAd, pAd->MacTab.Content[Aid].Addr, TpcReqToken);
1874 
1875 	return TRUE;
1876 }
1877 
1878