Staging: rt3070: remove dead DOT11N_DRAFT3 code
[linux-2.6] / drivers / staging / rt3070 / common / spectrum.c
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
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
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
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
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
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
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
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
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
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
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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
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
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 }
1063
1064 static VOID StartDFSProcedure(
1065         IN PRTMP_ADAPTER pAd,
1066         IN UCHAR Channel,
1067         IN UINT8 ChSwMode)
1068 {
1069         // start DFS procedure
1070         pAd->CommonCfg.Channel = Channel;
1071 #ifdef DOT11_N_SUPPORT
1072         N_ChannelCheck(pAd);
1073 #endif // DOT11_N_SUPPORT //
1074         pAd->CommonCfg.RadarDetect.RDMode = RD_SWITCHING_MODE;
1075         pAd->CommonCfg.RadarDetect.CSCount = 0;
1076 }
1077
1078 /*
1079         ==========================================================================
1080         Description:
1081                 Channel Switch Announcement action frame sanity check.
1082
1083         Parametrs:
1084                 1. MLME message containing the received frame
1085                 2. message length.
1086                 3. Channel switch announcement infomation buffer.
1087
1088
1089         Return  : None.
1090         ==========================================================================
1091  */
1092
1093 /*
1094   Channel Switch Announcement IE.
1095   +----+-----+-----------+------------+-----------+
1096   | ID | Len |Ch Sw Mode | New Ch Num | Ch Sw Cnt |
1097   +----+-----+-----------+------------+-----------+
1098     1    1        1           1            1
1099 */
1100 static BOOLEAN PeerChSwAnnSanity(
1101         IN PRTMP_ADAPTER pAd,
1102         IN VOID *pMsg,
1103         IN ULONG MsgLen,
1104         OUT PCH_SW_ANN_INFO pChSwAnnInfo)
1105 {
1106         PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
1107         PUCHAR pFramePtr = Fr->Octet;
1108         BOOLEAN result = FALSE;
1109         PEID_STRUCT eid_ptr;
1110
1111         // skip 802.11 header.
1112         MsgLen -= sizeof(HEADER_802_11);
1113
1114         // skip category and action code.
1115         pFramePtr += 2;
1116         MsgLen -= 2;
1117
1118         if (pChSwAnnInfo == NULL)
1119                 return result;
1120
1121         eid_ptr = (PEID_STRUCT)pFramePtr;
1122         while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
1123         {
1124                 switch(eid_ptr->Eid)
1125                 {
1126                         case IE_CHANNEL_SWITCH_ANNOUNCEMENT:
1127                                 NdisMoveMemory(&pChSwAnnInfo->ChSwMode, eid_ptr->Octet, 1);
1128                                 NdisMoveMemory(&pChSwAnnInfo->Channel, eid_ptr->Octet + 1, 1);
1129                                 NdisMoveMemory(&pChSwAnnInfo->ChSwCnt, eid_ptr->Octet + 2, 1);
1130
1131                                 result = TRUE;
1132                 break;
1133
1134                         default:
1135                                 break;
1136                 }
1137                 eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
1138         }
1139
1140         return result;
1141 }
1142
1143 /*
1144         ==========================================================================
1145         Description:
1146                 Measurement request action frame sanity check.
1147
1148         Parametrs:
1149                 1. MLME message containing the received frame
1150                 2. message length.
1151                 3. Measurement request infomation buffer.
1152
1153         Return  : None.
1154         ==========================================================================
1155  */
1156 static BOOLEAN PeerMeasureReqSanity(
1157         IN PRTMP_ADAPTER pAd,
1158         IN VOID *pMsg,
1159         IN ULONG MsgLen,
1160         OUT PUINT8 pDialogToken,
1161         OUT PMEASURE_REQ_INFO pMeasureReqInfo)
1162 {
1163         PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
1164         PUCHAR pFramePtr = Fr->Octet;
1165         BOOLEAN result = FALSE;
1166         PEID_STRUCT eid_ptr;
1167         PUCHAR ptr;
1168         UINT64 MeasureStartTime;
1169         UINT16 MeasureDuration;
1170
1171         // skip 802.11 header.
1172         MsgLen -= sizeof(HEADER_802_11);
1173
1174         // skip category and action code.
1175         pFramePtr += 2;
1176         MsgLen -= 2;
1177
1178         if (pMeasureReqInfo == NULL)
1179                 return result;
1180
1181         NdisMoveMemory(pDialogToken, pFramePtr, 1);
1182         pFramePtr += 1;
1183         MsgLen -= 1;
1184
1185         eid_ptr = (PEID_STRUCT)pFramePtr;
1186         while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
1187         {
1188                 switch(eid_ptr->Eid)
1189                 {
1190                         case IE_MEASUREMENT_REQUEST:
1191                                 NdisMoveMemory(&pMeasureReqInfo->Token, eid_ptr->Octet, 1);
1192                                 NdisMoveMemory(&pMeasureReqInfo->ReqMode.word, eid_ptr->Octet + 1, 1);
1193                                 NdisMoveMemory(&pMeasureReqInfo->ReqType, eid_ptr->Octet + 2, 1);
1194                                 ptr = eid_ptr->Octet + 3;
1195                                 NdisMoveMemory(&pMeasureReqInfo->MeasureReq.ChNum, ptr, 1);
1196                                 NdisMoveMemory(&MeasureStartTime, ptr + 1, 8);
1197                                 pMeasureReqInfo->MeasureReq.MeasureStartTime = SWAP64(MeasureStartTime);
1198                                 NdisMoveMemory(&MeasureDuration, ptr + 9, 2);
1199                                 pMeasureReqInfo->MeasureReq.MeasureDuration = SWAP16(MeasureDuration);
1200
1201                                 result = TRUE;
1202                                 break;
1203
1204                         default:
1205                                 break;
1206                 }
1207                 eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
1208         }
1209
1210         return result;
1211 }
1212
1213 /*
1214         ==========================================================================
1215         Description:
1216                 Measurement report action frame sanity check.
1217
1218         Parametrs:
1219                 1. MLME message containing the received frame
1220                 2. message length.
1221                 3. Measurement report infomation buffer.
1222                 4. basic report infomation buffer.
1223
1224         Return  : None.
1225         ==========================================================================
1226  */
1227
1228 /*
1229   Measurement Report IE.
1230   +----+-----+-------+-------------+--------------+----------------+
1231   | ID | Len | Token | Report Mode | Measure Type | Measure Report |
1232   +----+-----+-------+-------------+--------------+----------------+
1233     1     1      1          1             1            variable
1234
1235   Basic Report.
1236   +--------+------------+----------+-----+
1237   | Ch Num | Start Time | Duration | Map |
1238   +--------+------------+----------+-----+
1239       1          8           2        1
1240
1241   Map Field Bit Format.
1242   +-----+---------------+---------------------+-------+------------+----------+
1243   | Bss | OFDM Preamble | Unidentified signal | Radar | Unmeasured | Reserved |
1244   +-----+---------------+---------------------+-------+------------+----------+
1245      0          1                  2              3         4          5-7
1246 */
1247 static BOOLEAN PeerMeasureReportSanity(
1248         IN PRTMP_ADAPTER pAd,
1249         IN VOID *pMsg,
1250         IN ULONG MsgLen,
1251         OUT PUINT8 pDialogToken,
1252         OUT PMEASURE_REPORT_INFO pMeasureReportInfo,
1253         OUT PUINT8 pReportBuf)
1254 {
1255         PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
1256         PUCHAR pFramePtr = Fr->Octet;
1257         BOOLEAN result = FALSE;
1258         PEID_STRUCT eid_ptr;
1259         PUCHAR ptr;
1260
1261         // skip 802.11 header.
1262         MsgLen -= sizeof(HEADER_802_11);
1263
1264         // skip category and action code.
1265         pFramePtr += 2;
1266         MsgLen -= 2;
1267
1268         if (pMeasureReportInfo == NULL)
1269                 return result;
1270
1271         NdisMoveMemory(pDialogToken, pFramePtr, 1);
1272         pFramePtr += 1;
1273         MsgLen -= 1;
1274
1275         eid_ptr = (PEID_STRUCT)pFramePtr;
1276         while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
1277         {
1278                 switch(eid_ptr->Eid)
1279                 {
1280                         case IE_MEASUREMENT_REPORT:
1281                                 NdisMoveMemory(&pMeasureReportInfo->Token, eid_ptr->Octet, 1);
1282                                 NdisMoveMemory(&pMeasureReportInfo->ReportMode, eid_ptr->Octet + 1, 1);
1283                                 NdisMoveMemory(&pMeasureReportInfo->ReportType, eid_ptr->Octet + 2, 1);
1284                                 if (pMeasureReportInfo->ReportType == RM_BASIC)
1285                                 {
1286                                         PMEASURE_BASIC_REPORT pReport = (PMEASURE_BASIC_REPORT)pReportBuf;
1287                                         ptr = eid_ptr->Octet + 3;
1288                                         NdisMoveMemory(&pReport->ChNum, ptr, 1);
1289                                         NdisMoveMemory(&pReport->MeasureStartTime, ptr + 1, 8);
1290                                         NdisMoveMemory(&pReport->MeasureDuration, ptr + 9, 2);
1291                                         NdisMoveMemory(&pReport->Map, ptr + 11, 1);
1292
1293                                 }
1294                                 else if (pMeasureReportInfo->ReportType == RM_CCA)
1295                                 {
1296                                         PMEASURE_CCA_REPORT pReport = (PMEASURE_CCA_REPORT)pReportBuf;
1297                                         ptr = eid_ptr->Octet + 3;
1298                                         NdisMoveMemory(&pReport->ChNum, ptr, 1);
1299                                         NdisMoveMemory(&pReport->MeasureStartTime, ptr + 1, 8);
1300                                         NdisMoveMemory(&pReport->MeasureDuration, ptr + 9, 2);
1301                                         NdisMoveMemory(&pReport->CCA_Busy_Fraction, ptr + 11, 1);
1302
1303                                 }
1304                                 else if (pMeasureReportInfo->ReportType == RM_RPI_HISTOGRAM)
1305                                 {
1306                                         PMEASURE_RPI_REPORT pReport = (PMEASURE_RPI_REPORT)pReportBuf;
1307                                         ptr = eid_ptr->Octet + 3;
1308                                         NdisMoveMemory(&pReport->ChNum, ptr, 1);
1309                                         NdisMoveMemory(&pReport->MeasureStartTime, ptr + 1, 8);
1310                                         NdisMoveMemory(&pReport->MeasureDuration, ptr + 9, 2);
1311                                         NdisMoveMemory(&pReport->RPI_Density, ptr + 11, 8);
1312                                 }
1313                                 result = TRUE;
1314                 break;
1315
1316                         default:
1317                                 break;
1318                 }
1319                 eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
1320         }
1321
1322         return result;
1323 }
1324
1325 /*
1326         ==========================================================================
1327         Description:
1328                 TPC Request action frame sanity check.
1329
1330         Parametrs:
1331                 1. MLME message containing the received frame
1332                 2. message length.
1333                 3. Dialog Token.
1334
1335         Return  : None.
1336         ==========================================================================
1337  */
1338 static BOOLEAN PeerTpcReqSanity(
1339         IN PRTMP_ADAPTER pAd,
1340         IN VOID *pMsg,
1341         IN ULONG MsgLen,
1342         OUT PUINT8 pDialogToken)
1343 {
1344         PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
1345         PUCHAR pFramePtr = Fr->Octet;
1346         BOOLEAN result = FALSE;
1347         PEID_STRUCT eid_ptr;
1348
1349         MsgLen -= sizeof(HEADER_802_11);
1350
1351         // skip category and action code.
1352         pFramePtr += 2;
1353         MsgLen -= 2;
1354
1355         if (pDialogToken == NULL)
1356                 return result;
1357
1358         NdisMoveMemory(pDialogToken, pFramePtr, 1);
1359         pFramePtr += 1;
1360         MsgLen -= 1;
1361
1362         eid_ptr = (PEID_STRUCT)pFramePtr;
1363         while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
1364         {
1365                 switch(eid_ptr->Eid)
1366                 {
1367                         case IE_TPC_REQUEST:
1368                                 result = TRUE;
1369                 break;
1370
1371                         default:
1372                                 break;
1373                 }
1374                 eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
1375         }
1376
1377         return result;
1378 }
1379
1380 /*
1381         ==========================================================================
1382         Description:
1383                 TPC Report action frame sanity check.
1384
1385         Parametrs:
1386                 1. MLME message containing the received frame
1387                 2. message length.
1388                 3. Dialog Token.
1389                 4. TPC Report IE.
1390
1391         Return  : None.
1392         ==========================================================================
1393  */
1394 static BOOLEAN PeerTpcRepSanity(
1395         IN PRTMP_ADAPTER pAd,
1396         IN VOID *pMsg,
1397         IN ULONG MsgLen,
1398         OUT PUINT8 pDialogToken,
1399         OUT PTPC_REPORT_INFO pTpcRepInfo)
1400 {
1401         PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
1402         PUCHAR pFramePtr = Fr->Octet;
1403         BOOLEAN result = FALSE;
1404         PEID_STRUCT eid_ptr;
1405
1406         MsgLen -= sizeof(HEADER_802_11);
1407
1408         // skip category and action code.
1409         pFramePtr += 2;
1410         MsgLen -= 2;
1411
1412         if (pDialogToken == NULL)
1413                 return result;
1414
1415         NdisMoveMemory(pDialogToken, pFramePtr, 1);
1416         pFramePtr += 1;
1417         MsgLen -= 1;
1418
1419         eid_ptr = (PEID_STRUCT)pFramePtr;
1420         while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
1421         {
1422                 switch(eid_ptr->Eid)
1423                 {
1424                         case IE_TPC_REPORT:
1425                                 NdisMoveMemory(&pTpcRepInfo->TxPwr, eid_ptr->Octet, 1);
1426                                 NdisMoveMemory(&pTpcRepInfo->LinkMargin, eid_ptr->Octet + 1, 1);
1427                                 result = TRUE;
1428                 break;
1429
1430                         default:
1431                                 break;
1432                 }
1433                 eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
1434         }
1435
1436         return result;
1437 }
1438
1439 /*
1440         ==========================================================================
1441         Description:
1442                 Channel Switch Announcement action frame handler.
1443
1444         Parametrs:
1445                 Elme - MLME message containing the received frame
1446
1447         Return  : None.
1448         ==========================================================================
1449  */
1450 static VOID PeerChSwAnnAction(
1451         IN PRTMP_ADAPTER pAd,
1452         IN MLME_QUEUE_ELEM *Elem)
1453 {
1454         CH_SW_ANN_INFO ChSwAnnInfo;
1455         PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg;
1456 #ifdef CONFIG_STA_SUPPORT
1457         UCHAR index = 0, Channel = 0, NewChannel = 0;
1458         ULONG Bssidx = 0;
1459 #endif // CONFIG_STA_SUPPORT //
1460
1461         NdisZeroMemory(&ChSwAnnInfo, sizeof(CH_SW_ANN_INFO));
1462         if (! PeerChSwAnnSanity(pAd, Elem->Msg, Elem->MsgLen, &ChSwAnnInfo))
1463         {
1464                 DBGPRINT(RT_DEBUG_TRACE, ("Invalid Channel Switch Action Frame.\n"));
1465                 return;
1466         }
1467
1468
1469 #ifdef CONFIG_STA_SUPPORT
1470         if (pAd->OpMode == OPMODE_STA)
1471         {
1472                 Bssidx = BssTableSearch(&pAd->ScanTab, pFr->Hdr.Addr3, pAd->CommonCfg.Channel);
1473                 if (Bssidx == BSS_NOT_FOUND)
1474                 {
1475                         DBGPRINT(RT_DEBUG_TRACE, ("PeerChSwAnnAction - Bssidx is not found\n"));
1476                         return;
1477                 }
1478
1479                 DBGPRINT(RT_DEBUG_TRACE, ("\n****Bssidx is %d, Channel = %d\n", index, pAd->ScanTab.BssEntry[Bssidx].Channel));
1480                 hex_dump("SSID",pAd->ScanTab.BssEntry[Bssidx].Bssid ,6);
1481
1482                 Channel = pAd->CommonCfg.Channel;
1483                 NewChannel = ChSwAnnInfo.Channel;
1484
1485                 if ((pAd->CommonCfg.bIEEE80211H == 1) && (NewChannel != 0) && (Channel != NewChannel))
1486                 {
1487                         // Switching to channel 1 can prevent from rescanning the current channel immediately (by auto reconnection).
1488                         // In addition, clear the MLME queue and the scan table to discard the RX packets and previous scanning results.
1489                         AsicSwitchChannel(pAd, 1, FALSE);
1490                         AsicLockChannel(pAd, 1);
1491                     LinkDown(pAd, FALSE);
1492                         MlmeQueueInit(&pAd->Mlme.Queue);
1493                         BssTableInit(&pAd->ScanTab);
1494                     RTMPusecDelay(1000000);             // use delay to prevent STA do reassoc
1495
1496                         // channel sanity check
1497                         for (index = 0 ; index < pAd->ChannelListNum; index++)
1498                         {
1499                                 if (pAd->ChannelList[index].Channel == NewChannel)
1500                                 {
1501                                         pAd->ScanTab.BssEntry[Bssidx].Channel = NewChannel;
1502                                         pAd->CommonCfg.Channel = NewChannel;
1503                                         AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
1504                                         AsicLockChannel(pAd, pAd->CommonCfg.Channel);
1505                                         DBGPRINT(RT_DEBUG_TRACE, ("&&&&&&&&&&&&&&&&PeerChSwAnnAction - STA receive channel switch announcement IE (New Channel =%d)\n", NewChannel));
1506                                         break;
1507                                 }
1508                         }
1509
1510                         if (index >= pAd->ChannelListNum)
1511                         {
1512                                 DBGPRINT_ERR(("&&&&&&&&&&&&&&&&&&&&&&&&&&PeerChSwAnnAction(can not find New Channel=%d in ChannelList[%d]\n", pAd->CommonCfg.Channel, pAd->ChannelListNum));
1513                         }
1514                 }
1515         }
1516 #endif // CONFIG_STA_SUPPORT //
1517
1518         return;
1519 }
1520
1521
1522 /*
1523         ==========================================================================
1524         Description:
1525                 Measurement Request action frame handler.
1526
1527         Parametrs:
1528                 Elme - MLME message containing the received frame
1529
1530         Return  : None.
1531         ==========================================================================
1532  */
1533 static VOID PeerMeasureReqAction(
1534         IN PRTMP_ADAPTER pAd,
1535         IN MLME_QUEUE_ELEM *Elem)
1536 {
1537         PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg;
1538         UINT8 DialogToken;
1539         MEASURE_REQ_INFO MeasureReqInfo;
1540         MEASURE_REPORT_MODE ReportMode;
1541
1542         if(PeerMeasureReqSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &MeasureReqInfo))
1543         {
1544                 ReportMode.word = 0;
1545                 ReportMode.field.Incapable = 1;
1546                 EnqueueMeasurementRep(pAd, pFr->Hdr.Addr2, DialogToken, MeasureReqInfo.Token, ReportMode.word, MeasureReqInfo.ReqType, 0, NULL);
1547         }
1548
1549         return;
1550 }
1551
1552 /*
1553         ==========================================================================
1554         Description:
1555                 Measurement Report action frame handler.
1556
1557         Parametrs:
1558                 Elme - MLME message containing the received frame
1559
1560         Return  : None.
1561         ==========================================================================
1562  */
1563 static VOID PeerMeasureReportAction(
1564         IN PRTMP_ADAPTER pAd,
1565         IN MLME_QUEUE_ELEM *Elem)
1566 {
1567         MEASURE_REPORT_INFO MeasureReportInfo;
1568         PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg;
1569         UINT8 DialogToken;
1570         PUINT8 pMeasureReportInfo;
1571
1572 //      if (pAd->CommonCfg.bIEEE80211H != TRUE)
1573 //              return;
1574
1575         if ((pMeasureReportInfo = kmalloc(sizeof(MEASURE_RPI_REPORT), GFP_ATOMIC)) == NULL)
1576         {
1577                 DBGPRINT(RT_DEBUG_ERROR, ("%s unable to alloc memory for measure report buffer (size=%d).\n", __func__, sizeof(MEASURE_RPI_REPORT)));
1578                 return;
1579         }
1580
1581         NdisZeroMemory(&MeasureReportInfo, sizeof(MEASURE_REPORT_INFO));
1582         NdisZeroMemory(pMeasureReportInfo, sizeof(MEASURE_RPI_REPORT));
1583         if (PeerMeasureReportSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &MeasureReportInfo, pMeasureReportInfo))
1584         {
1585                 do {
1586                         PMEASURE_REQ_ENTRY pEntry = NULL;
1587
1588                         // Not a autonomous measure report.
1589                         // check the dialog token field. drop it if the dialog token doesn't match.
1590                         if ((DialogToken != 0)
1591                                 && ((pEntry = MeasureReqLookUp(pAd, DialogToken)) == NULL))
1592                                 break;
1593
1594                         if (pEntry != NULL)
1595                                 MeasureReqDelete(pAd, pEntry->DialogToken);
1596
1597                         if (MeasureReportInfo.ReportType == RM_BASIC)
1598                         {
1599                                 PMEASURE_BASIC_REPORT pBasicReport = (PMEASURE_BASIC_REPORT)pMeasureReportInfo;
1600                                 if ((pBasicReport->Map.field.Radar)
1601                                         && (DfsRequirementCheck(pAd, pBasicReport->ChNum) == TRUE))
1602                                 {
1603                                         NotifyChSwAnnToPeerAPs(pAd, pFr->Hdr.Addr1, pFr->Hdr.Addr2, 1, pBasicReport->ChNum);
1604                                         StartDFSProcedure(pAd, pBasicReport->ChNum, 1);
1605                                 }
1606                         }
1607                 } while (FALSE);
1608         }
1609         else
1610                 DBGPRINT(RT_DEBUG_TRACE, ("Invalid Measurement Report Frame.\n"));
1611
1612         kfree(pMeasureReportInfo);
1613
1614         return;
1615 }
1616
1617 /*
1618         ==========================================================================
1619         Description:
1620                 TPC Request action frame handler.
1621
1622         Parametrs:
1623                 Elme - MLME message containing the received frame
1624
1625         Return  : None.
1626         ==========================================================================
1627  */
1628 static VOID PeerTpcReqAction(
1629         IN PRTMP_ADAPTER pAd,
1630         IN MLME_QUEUE_ELEM *Elem)
1631 {
1632         PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg;
1633         PUCHAR pFramePtr = pFr->Octet;
1634         UINT8 DialogToken;
1635         UINT8 TxPwr = GetCurTxPwr(pAd, Elem->Wcid);
1636         UINT8 LinkMargin = 0;
1637         CHAR RealRssi;
1638
1639         // link margin: Ratio of the received signal power to the minimum desired by the station (STA). The
1640         //                              STA may incorporate rate information and channel conditions, including interference, into its computation
1641         //                              of link margin.
1642
1643         RealRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0),
1644                                                                 ConvertToRssi(pAd, Elem->Rssi1, RSSI_1),
1645                                                                 ConvertToRssi(pAd, Elem->Rssi2, RSSI_2));
1646
1647         // skip Category and action code.
1648         pFramePtr += 2;
1649
1650         // Dialog token.
1651         NdisMoveMemory(&DialogToken, pFramePtr, 1);
1652
1653         LinkMargin = (RealRssi / MIN_RCV_PWR);
1654         if (PeerTpcReqSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken))
1655                 EnqueueTPCRep(pAd, pFr->Hdr.Addr2, DialogToken, TxPwr, LinkMargin);
1656
1657         return;
1658 }
1659
1660 /*
1661         ==========================================================================
1662         Description:
1663                 TPC Report action frame handler.
1664
1665         Parametrs:
1666                 Elme - MLME message containing the received frame
1667
1668         Return  : None.
1669         ==========================================================================
1670  */
1671 static VOID PeerTpcRepAction(
1672         IN PRTMP_ADAPTER pAd,
1673         IN MLME_QUEUE_ELEM *Elem)
1674 {
1675         UINT8 DialogToken;
1676         TPC_REPORT_INFO TpcRepInfo;
1677         PTPC_REQ_ENTRY pEntry = NULL;
1678
1679         NdisZeroMemory(&TpcRepInfo, sizeof(TPC_REPORT_INFO));
1680         if (PeerTpcRepSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &TpcRepInfo))
1681         {
1682                 if ((pEntry = TpcReqLookUp(pAd, DialogToken)) != NULL)
1683                 {
1684                         TpcReqDelete(pAd, pEntry->DialogToken);
1685                         DBGPRINT(RT_DEBUG_TRACE, ("%s: DialogToken=%x, TxPwr=%d, LinkMargin=%d\n",
1686                                 __func__, DialogToken, TpcRepInfo.TxPwr, TpcRepInfo.LinkMargin));
1687                 }
1688         }
1689
1690         return;
1691 }
1692
1693 /*
1694         ==========================================================================
1695         Description:
1696                 Spectrun action frames Handler such as channel switch annoucement,
1697                 measurement report, measurement request actions frames.
1698
1699         Parametrs:
1700                 Elme - MLME message containing the received frame
1701
1702         Return  : None.
1703         ==========================================================================
1704  */
1705 VOID PeerSpectrumAction(
1706         IN PRTMP_ADAPTER pAd,
1707         IN MLME_QUEUE_ELEM *Elem)
1708 {
1709
1710         UCHAR   Action = Elem->Msg[LENGTH_802_11+1];
1711
1712         if (pAd->CommonCfg.bIEEE80211H != TRUE)
1713                 return;
1714
1715         switch(Action)
1716         {
1717                 case SPEC_MRQ:
1718                         // current rt2860 unable do such measure specified in Measurement Request.
1719                         // reject all measurement request.
1720                         PeerMeasureReqAction(pAd, Elem);
1721                         break;
1722
1723                 case SPEC_MRP:
1724                         PeerMeasureReportAction(pAd, Elem);
1725                         break;
1726
1727                 case SPEC_TPCRQ:
1728                         PeerTpcReqAction(pAd, Elem);
1729                         break;
1730
1731                 case SPEC_TPCRP:
1732                         PeerTpcRepAction(pAd, Elem);
1733                         break;
1734
1735                 case SPEC_CHANNEL_SWITCH:
1736 {
1737 }
1738                         PeerChSwAnnAction(pAd, Elem);
1739                         break;
1740         }
1741
1742         return;
1743 }
1744
1745 /*
1746         ==========================================================================
1747         Description:
1748
1749         Parametrs:
1750
1751         Return  : None.
1752         ==========================================================================
1753  */
1754 INT Set_MeasureReq_Proc(
1755         IN      PRTMP_ADAPTER   pAd,
1756         IN      PUCHAR                  arg)
1757 {
1758         UINT Aid = 1;
1759         UINT ArgIdx;
1760         PUCHAR thisChar;
1761
1762         MEASURE_REQ_MODE MeasureReqMode;
1763         UINT8 MeasureReqToken = RandomByte(pAd);
1764         UINT8 MeasureReqType = RM_BASIC;
1765         UINT8 MeasureCh = 1;
1766
1767         ArgIdx = 1;
1768         while ((thisChar = strsep((char **)&arg, "-")) != NULL)
1769         {
1770                 switch(ArgIdx)
1771                 {
1772                         case 1: // Aid.
1773                                 Aid = simple_strtol(thisChar, 0, 16);
1774                                 break;
1775
1776                         case 2: // Measurement Request Type.
1777                                 MeasureReqType = simple_strtol(thisChar, 0, 16);
1778                                 if (MeasureReqType > 3)
1779                                 {
1780                                         DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow MeasureReqType(%d)\n", __func__, MeasureReqType));
1781                                         return TRUE;
1782                                 }
1783                                 break;
1784
1785                         case 3: // Measurement channel.
1786                                 MeasureCh = simple_strtol(thisChar, 0, 16);
1787                                 break;
1788                 }
1789                 ArgIdx++;
1790         }
1791
1792         DBGPRINT(RT_DEBUG_TRACE, ("%s::Aid = %d, MeasureReqType=%d MeasureCh=%d\n", __func__, Aid, MeasureReqType, MeasureCh));
1793         if (!VALID_WCID(Aid))
1794         {
1795                 DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow sta of Aid(%d)\n", __func__, Aid));
1796                 return TRUE;
1797         }
1798
1799         MeasureReqMode.word = 0;
1800         MeasureReqMode.field.Enable = 1;
1801
1802         MeasureReqInsert(pAd, MeasureReqToken);
1803
1804         EnqueueMeasurementReq(pAd, pAd->MacTab.Content[Aid].Addr,
1805                 MeasureReqToken, MeasureReqMode.word, MeasureReqType, MeasureCh, 2000);
1806
1807         return TRUE;
1808 }
1809
1810 INT Set_TpcReq_Proc(
1811         IN      PRTMP_ADAPTER   pAd,
1812         IN      PUCHAR                  arg)
1813 {
1814         UINT Aid;
1815
1816         UINT8 TpcReqToken = RandomByte(pAd);
1817
1818         Aid = simple_strtol(arg, 0, 16);
1819
1820         DBGPRINT(RT_DEBUG_TRACE, ("%s::Aid = %d\n", __func__, Aid));
1821         if (!VALID_WCID(Aid))
1822         {
1823                 DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow sta of Aid(%d)\n", __func__, Aid));
1824                 return TRUE;
1825         }
1826
1827         TpcReqInsert(pAd, TpcReqToken);
1828
1829         EnqueueTPCReq(pAd, pAd->MacTab.Content[Aid].Addr, TpcReqToken);
1830
1831         return TRUE;
1832 }
1833