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