aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/rt3070/common/spectrum.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/rt3070/common/spectrum.c')
-rw-r--r--drivers/staging/rt3070/common/spectrum.c1876
1 files changed, 1876 insertions, 0 deletions
diff --git a/drivers/staging/rt3070/common/spectrum.c b/drivers/staging/rt3070/common/spectrum.c
new file mode 100644
index 00000000000..da57b1202d6
--- /dev/null
+++ b/drivers/staging/rt3070/common/spectrum.c
@@ -0,0 +1,1876 @@
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
42VOID 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", __FUNCTION__));
52
53 return;
54}
55
56VOID 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
68static 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", __FUNCTION__));
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
104static 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", __FUNCTION__));
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", __FUNCTION__));
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
203static 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", __FUNCTION__));
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
260VOID 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", __FUNCTION__));
270
271 return;
272}
273
274VOID 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
286static 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", __FUNCTION__));
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
323static 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", __FUNCTION__));
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", __FUNCTION__));
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
422static 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", __FUNCTION__));
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 */
489static 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 */
506static 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 */
526static 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 */
629static 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 */
677static 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 */
715static 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 */
760VOID 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", __FUNCTION__));
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 */
823VOID 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", __FUNCTION__));
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 */
882VOID 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", __FUNCTION__));
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 */
932VOID 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", __FUNCTION__));
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 */
986VOID 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", __FUNCTION__));
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
1021static 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
1055VOID 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
1085static 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*/
1121static 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 */
1177static 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*/
1268static 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 */
1359static 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 */
1415static 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 */
1471static 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 */
1554static 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 */
1584static 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", __FUNCTION__, 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 */
1649static 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 */
1692static 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 __FUNCTION__, 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 */
1726VOID 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 */
1797INT 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", __FUNCTION__, 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", __FUNCTION__, Aid, MeasureReqType, MeasureCh));
1836 if (!VALID_WCID(Aid))
1837 {
1838 DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow sta of Aid(%d)\n", __FUNCTION__, 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
1853INT 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", __FUNCTION__, Aid));
1864 if (!VALID_WCID(Aid))
1865 {
1866 DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow sta of Aid(%d)\n", __FUNCTION__, 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