2 *************************************************************************
4 * 5F., No.36, Taiyuan St., Jhubei City,
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
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. *
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. *
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. *
25 *************************************************************************
32 Handle association related requests either from WSTA or from local MLME
36 --------- ---------- ----------------------------------------------
37 Fonchi Wu 2008 created for 802.11h
40 #include "../rt_config.h"
43 VOID
MeasureReqTabInit(
46 NdisAllocateSpinLock(&pAd
->CommonCfg
.MeasureReqTabLock
);
48 pAd
->CommonCfg
.pMeasureReqTab
= kmalloc(sizeof(MEASURE_REQ_TAB
), GFP_ATOMIC
);
49 if (pAd
->CommonCfg
.pMeasureReqTab
)
50 NdisZeroMemory(pAd
->CommonCfg
.pMeasureReqTab
, sizeof(MEASURE_REQ_TAB
));
52 DBGPRINT(RT_DEBUG_ERROR
, ("%s Fail to alloc memory for pAd->CommonCfg.pMeasureReqTab.\n", __func__
));
57 VOID
MeasureReqTabExit(
60 NdisFreeSpinLock(pAd
->CommonCfg
.MeasureReqTabLock
);
62 if (pAd
->CommonCfg
.pMeasureReqTab
)
63 kfree(pAd
->CommonCfg
.pMeasureReqTab
);
64 pAd
->CommonCfg
.pMeasureReqTab
= NULL
;
69 static PMEASURE_REQ_ENTRY
MeasureReqLookUp(
74 PMEASURE_REQ_TAB pTab
= pAd
->CommonCfg
.pMeasureReqTab
;
75 PMEASURE_REQ_ENTRY pEntry
= NULL
;
76 PMEASURE_REQ_ENTRY pPrevEntry
= NULL
;
80 DBGPRINT(RT_DEBUG_ERROR
, ("%s: pMeasureReqTab doesn't exist.\n", __func__
));
84 RTMP_SEM_LOCK(&pAd
->CommonCfg
.MeasureReqTabLock
);
86 HashIdx
= MQ_DIALOGTOKEN_HASH_INDEX(DialogToken
);
87 pEntry
= pTab
->Hash
[HashIdx
];
91 if (pEntry
->DialogToken
== DialogToken
)
96 pEntry
= pEntry
->pNext
;
100 RTMP_SEM_UNLOCK(&pAd
->CommonCfg
.MeasureReqTabLock
);
105 static PMEASURE_REQ_ENTRY
MeasureReqInsert(
106 IN PRTMP_ADAPTER pAd
,
107 IN UINT8 DialogToken
)
111 PMEASURE_REQ_TAB pTab
= pAd
->CommonCfg
.pMeasureReqTab
;
112 PMEASURE_REQ_ENTRY pEntry
= NULL
, pCurrEntry
;
117 DBGPRINT(RT_DEBUG_ERROR
, ("%s: pMeasureReqTab doesn't exist.\n", __func__
));
121 pEntry
= MeasureReqLookUp(pAd
, DialogToken
);
124 RTMP_SEM_LOCK(&pAd
->CommonCfg
.MeasureReqTabLock
);
125 for (i
= 0; i
< MAX_MEASURE_REQ_TAB_SIZE
; i
++)
127 NdisGetSystemUpTime(&Now
);
128 pEntry
= &pTab
->Content
[i
];
130 if ((pEntry
->Valid
== TRUE
)
131 && RTMP_TIME_AFTER((unsigned long)Now
, (unsigned long)(pEntry
->lastTime
+ MQ_REQ_AGE_OUT
)))
133 PMEASURE_REQ_ENTRY pPrevEntry
= NULL
;
134 ULONG HashIdx
= MQ_DIALOGTOKEN_HASH_INDEX(pEntry
->DialogToken
);
135 PMEASURE_REQ_ENTRY pProbeEntry
= pTab
->Hash
[HashIdx
];
140 if (pProbeEntry
== pEntry
)
142 if (pPrevEntry
== NULL
)
144 pTab
->Hash
[HashIdx
] = pEntry
->pNext
;
148 pPrevEntry
->pNext
= pEntry
->pNext
;
153 pPrevEntry
= pProbeEntry
;
154 pProbeEntry
= pProbeEntry
->pNext
;
155 } while (pProbeEntry
);
157 NdisZeroMemory(pEntry
, sizeof(MEASURE_REQ_ENTRY
));
163 if (pEntry
->Valid
== FALSE
)
167 if (i
< MAX_MEASURE_REQ_TAB_SIZE
)
169 NdisGetSystemUpTime(&Now
);
170 pEntry
->lastTime
= Now
;
171 pEntry
->Valid
= TRUE
;
172 pEntry
->DialogToken
= DialogToken
;
178 DBGPRINT(RT_DEBUG_ERROR
, ("%s: pMeasureReqTab tab full.\n", __func__
));
181 // add this Neighbor entry into HASH table
184 HashIdx
= MQ_DIALOGTOKEN_HASH_INDEX(DialogToken
);
185 if (pTab
->Hash
[HashIdx
] == NULL
)
187 pTab
->Hash
[HashIdx
] = pEntry
;
191 pCurrEntry
= pTab
->Hash
[HashIdx
];
192 while (pCurrEntry
->pNext
!= NULL
)
193 pCurrEntry
= pCurrEntry
->pNext
;
194 pCurrEntry
->pNext
= pEntry
;
198 RTMP_SEM_UNLOCK(&pAd
->CommonCfg
.MeasureReqTabLock
);
204 static VOID
MeasureReqDelete(
205 IN PRTMP_ADAPTER pAd
,
206 IN UINT8 DialogToken
)
208 PMEASURE_REQ_TAB pTab
= pAd
->CommonCfg
.pMeasureReqTab
;
209 PMEASURE_REQ_ENTRY pEntry
= NULL
;
213 DBGPRINT(RT_DEBUG_ERROR
, ("%s: pMeasureReqTab doesn't exist.\n", __func__
));
220 DBGPRINT(RT_DEBUG_ERROR
, ("pMeasureReqTab empty.\n"));
224 pEntry
= MeasureReqLookUp(pAd
, DialogToken
);
227 PMEASURE_REQ_ENTRY pPrevEntry
= NULL
;
228 ULONG HashIdx
= MQ_DIALOGTOKEN_HASH_INDEX(pEntry
->DialogToken
);
229 PMEASURE_REQ_ENTRY pProbeEntry
= pTab
->Hash
[HashIdx
];
231 RTMP_SEM_LOCK(&pAd
->CommonCfg
.MeasureReqTabLock
);
235 if (pProbeEntry
== pEntry
)
237 if (pPrevEntry
== NULL
)
239 pTab
->Hash
[HashIdx
] = pEntry
->pNext
;
243 pPrevEntry
->pNext
= pEntry
->pNext
;
248 pPrevEntry
= pProbeEntry
;
249 pProbeEntry
= pProbeEntry
->pNext
;
250 } while (pProbeEntry
);
252 NdisZeroMemory(pEntry
, sizeof(MEASURE_REQ_ENTRY
));
255 RTMP_SEM_UNLOCK(&pAd
->CommonCfg
.MeasureReqTabLock
);
262 IN PRTMP_ADAPTER pAd
)
264 NdisAllocateSpinLock(&pAd
->CommonCfg
.TpcReqTabLock
);
266 pAd
->CommonCfg
.pTpcReqTab
= kmalloc(sizeof(TPC_REQ_TAB
), GFP_ATOMIC
);
267 if (pAd
->CommonCfg
.pTpcReqTab
)
268 NdisZeroMemory(pAd
->CommonCfg
.pTpcReqTab
, sizeof(TPC_REQ_TAB
));
270 DBGPRINT(RT_DEBUG_ERROR
, ("%s Fail to alloc memory for pAd->CommonCfg.pTpcReqTab.\n", __func__
));
276 IN PRTMP_ADAPTER pAd
)
278 NdisFreeSpinLock(pAd
->CommonCfg
.TpcReqTabLock
);
280 if (pAd
->CommonCfg
.pTpcReqTab
)
281 kfree(pAd
->CommonCfg
.pTpcReqTab
);
282 pAd
->CommonCfg
.pTpcReqTab
= NULL
;
287 static PTPC_REQ_ENTRY
TpcReqLookUp(
288 IN PRTMP_ADAPTER pAd
,
289 IN UINT8 DialogToken
)
292 PTPC_REQ_TAB pTab
= pAd
->CommonCfg
.pTpcReqTab
;
293 PTPC_REQ_ENTRY pEntry
= NULL
;
294 PTPC_REQ_ENTRY pPrevEntry
= NULL
;
298 DBGPRINT(RT_DEBUG_ERROR
, ("%s: pTpcReqTab doesn't exist.\n", __func__
));
302 RTMP_SEM_LOCK(&pAd
->CommonCfg
.TpcReqTabLock
);
304 HashIdx
= TPC_DIALOGTOKEN_HASH_INDEX(DialogToken
);
305 pEntry
= pTab
->Hash
[HashIdx
];
309 if (pEntry
->DialogToken
== DialogToken
)
314 pEntry
= pEntry
->pNext
;
318 RTMP_SEM_UNLOCK(&pAd
->CommonCfg
.TpcReqTabLock
);
324 static PTPC_REQ_ENTRY
TpcReqInsert(
325 IN PRTMP_ADAPTER pAd
,
326 IN UINT8 DialogToken
)
330 PTPC_REQ_TAB pTab
= pAd
->CommonCfg
.pTpcReqTab
;
331 PTPC_REQ_ENTRY pEntry
= NULL
, pCurrEntry
;
336 DBGPRINT(RT_DEBUG_ERROR
, ("%s: pTpcReqTab doesn't exist.\n", __func__
));
340 pEntry
= TpcReqLookUp(pAd
, DialogToken
);
343 RTMP_SEM_LOCK(&pAd
->CommonCfg
.TpcReqTabLock
);
344 for (i
= 0; i
< MAX_TPC_REQ_TAB_SIZE
; i
++)
346 NdisGetSystemUpTime(&Now
);
347 pEntry
= &pTab
->Content
[i
];
349 if ((pEntry
->Valid
== TRUE
)
350 && RTMP_TIME_AFTER((unsigned long)Now
, (unsigned long)(pEntry
->lastTime
+ TPC_REQ_AGE_OUT
)))
352 PTPC_REQ_ENTRY pPrevEntry
= NULL
;
353 ULONG HashIdx
= TPC_DIALOGTOKEN_HASH_INDEX(pEntry
->DialogToken
);
354 PTPC_REQ_ENTRY pProbeEntry
= pTab
->Hash
[HashIdx
];
359 if (pProbeEntry
== pEntry
)
361 if (pPrevEntry
== NULL
)
363 pTab
->Hash
[HashIdx
] = pEntry
->pNext
;
367 pPrevEntry
->pNext
= pEntry
->pNext
;
372 pPrevEntry
= pProbeEntry
;
373 pProbeEntry
= pProbeEntry
->pNext
;
374 } while (pProbeEntry
);
376 NdisZeroMemory(pEntry
, sizeof(TPC_REQ_ENTRY
));
382 if (pEntry
->Valid
== FALSE
)
386 if (i
< MAX_TPC_REQ_TAB_SIZE
)
388 NdisGetSystemUpTime(&Now
);
389 pEntry
->lastTime
= Now
;
390 pEntry
->Valid
= TRUE
;
391 pEntry
->DialogToken
= DialogToken
;
397 DBGPRINT(RT_DEBUG_ERROR
, ("%s: pTpcReqTab tab full.\n", __func__
));
400 // add this Neighbor entry into HASH table
403 HashIdx
= TPC_DIALOGTOKEN_HASH_INDEX(DialogToken
);
404 if (pTab
->Hash
[HashIdx
] == NULL
)
406 pTab
->Hash
[HashIdx
] = pEntry
;
410 pCurrEntry
= pTab
->Hash
[HashIdx
];
411 while (pCurrEntry
->pNext
!= NULL
)
412 pCurrEntry
= pCurrEntry
->pNext
;
413 pCurrEntry
->pNext
= pEntry
;
417 RTMP_SEM_UNLOCK(&pAd
->CommonCfg
.TpcReqTabLock
);
423 static VOID
TpcReqDelete(
424 IN PRTMP_ADAPTER pAd
,
425 IN UINT8 DialogToken
)
427 PTPC_REQ_TAB pTab
= pAd
->CommonCfg
.pTpcReqTab
;
428 PTPC_REQ_ENTRY pEntry
= NULL
;
432 DBGPRINT(RT_DEBUG_ERROR
, ("%s: pTpcReqTab doesn't exist.\n", __func__
));
439 DBGPRINT(RT_DEBUG_ERROR
, ("pTpcReqTab empty.\n"));
443 pEntry
= TpcReqLookUp(pAd
, DialogToken
);
446 PTPC_REQ_ENTRY pPrevEntry
= NULL
;
447 ULONG HashIdx
= TPC_DIALOGTOKEN_HASH_INDEX(pEntry
->DialogToken
);
448 PTPC_REQ_ENTRY pProbeEntry
= pTab
->Hash
[HashIdx
];
450 RTMP_SEM_LOCK(&pAd
->CommonCfg
.TpcReqTabLock
);
454 if (pProbeEntry
== pEntry
)
456 if (pPrevEntry
== NULL
)
458 pTab
->Hash
[HashIdx
] = pEntry
->pNext
;
462 pPrevEntry
->pNext
= pEntry
->pNext
;
467 pPrevEntry
= pProbeEntry
;
468 pProbeEntry
= pProbeEntry
->pNext
;
469 } while (pProbeEntry
);
471 NdisZeroMemory(pEntry
, sizeof(TPC_REQ_ENTRY
));
474 RTMP_SEM_UNLOCK(&pAd
->CommonCfg
.TpcReqTabLock
);
481 ==========================================================================
483 Get Current TimeS tamp.
487 Return : Current Time Stamp.
488 ==========================================================================
490 static UINT64
GetCurrentTimeStamp(
491 IN PRTMP_ADAPTER pAd
)
493 // get current time stamp.
498 ==========================================================================
500 Get Current Transmit Power.
504 Return : Current Time Stamp.
505 ==========================================================================
507 static UINT8
GetCurTxPwr(
508 IN PRTMP_ADAPTER pAd
,
511 return 16; /* 16 dBm */
515 ==========================================================================
517 Insert Dialog Token into frame.
520 1. frame buffer pointer.
525 ==========================================================================
527 static VOID
InsertDialogToken(
528 IN PRTMP_ADAPTER pAd
,
529 OUT PUCHAR pFrameBuf
,
530 OUT PULONG pFrameLen
,
531 IN UINT8 DialogToken
)
534 MakeOutgoingFrame(pFrameBuf
, &TempLen
,
538 *pFrameLen
= *pFrameLen
+ TempLen
;
544 ==========================================================================
546 Insert TPC Request IE into frame.
549 1. frame buffer pointer.
553 ==========================================================================
555 static VOID
InsertTpcReqIE(
556 IN PRTMP_ADAPTER pAd
,
557 OUT PUCHAR pFrameBuf
,
558 OUT PULONG pFrameLen
)
562 UINT8 ElementID
= IE_TPC_REQUEST
;
564 MakeOutgoingFrame(pFrameBuf
, &TempLen
,
569 *pFrameLen
= *pFrameLen
+ TempLen
;
575 ==========================================================================
577 Insert TPC Report IE into frame.
580 1. frame buffer pointer.
586 ==========================================================================
588 static VOID
InsertTpcReportIE(
589 IN PRTMP_ADAPTER pAd
,
590 OUT PUCHAR pFrameBuf
,
591 OUT PULONG pFrameLen
,
596 ULONG Len
= sizeof(TPC_REPORT_INFO
);
597 UINT8 ElementID
= IE_TPC_REPORT
;
598 TPC_REPORT_INFO TpcReportIE
;
600 TpcReportIE
.TxPwr
= TxPwr
;
601 TpcReportIE
.LinkMargin
= LinkMargin
;
603 MakeOutgoingFrame(pFrameBuf
, &TempLen
,
609 *pFrameLen
= *pFrameLen
+ TempLen
;
616 ==========================================================================
618 Insert Channel Switch Announcement IE into frame.
621 1. frame buffer pointer.
623 3. channel switch announcement mode.
624 4. new selected channel.
625 5. channel switch announcement count.
628 ==========================================================================
630 static VOID
InsertChSwAnnIE(
631 IN PRTMP_ADAPTER pAd
,
632 OUT PUCHAR pFrameBuf
,
633 OUT PULONG pFrameLen
,
639 ULONG Len
= sizeof(CH_SW_ANN_INFO
);
640 UINT8 ElementID
= IE_CHANNEL_SWITCH_ANNOUNCEMENT
;
641 CH_SW_ANN_INFO ChSwAnnIE
;
643 ChSwAnnIE
.ChSwMode
= ChSwMode
;
644 ChSwAnnIE
.Channel
= NewChannel
;
645 ChSwAnnIE
.ChSwCnt
= ChSwCnt
;
647 MakeOutgoingFrame(pFrameBuf
, &TempLen
,
653 *pFrameLen
= *pFrameLen
+ TempLen
;
660 ==========================================================================
662 Insert Measure Request IE into frame.
665 1. frame buffer pointer.
668 4. Measure Request Mode.
669 5. Measure Request Type.
671 7. Measure Start time.
676 ==========================================================================
678 static VOID
InsertMeasureReqIE(
679 IN PRTMP_ADAPTER pAd
,
680 OUT PUCHAR pFrameBuf
,
681 OUT PULONG pFrameLen
,
682 IN PMEASURE_REQ_INFO pMeasureReqIE
)
685 UINT8 Len
= sizeof(MEASURE_REQ_INFO
);
686 UINT8 ElementID
= IE_MEASUREMENT_REQUEST
;
688 MakeOutgoingFrame(pFrameBuf
, &TempLen
,
694 *pFrameLen
= *pFrameLen
+ TempLen
;
700 ==========================================================================
702 Insert Measure Report IE into frame.
705 1. frame buffer pointer.
708 4. Measure Request Mode.
709 5. Measure Request Type.
710 6. Length of Report Infomation
711 7. Pointer of Report Infomation Buffer.
714 ==========================================================================
716 static VOID
InsertMeasureReportIE(
717 IN PRTMP_ADAPTER pAd
,
718 OUT PUCHAR pFrameBuf
,
719 OUT PULONG pFrameLen
,
720 IN PMEASURE_REPORT_INFO pMeasureReportIE
,
721 IN UINT8 ReportLnfoLen
,
722 IN PUINT8 pReportInfo
)
726 UINT8 ElementID
= IE_MEASUREMENT_REPORT
;
728 Len
= sizeof(MEASURE_REPORT_INFO
) + ReportLnfoLen
;
730 MakeOutgoingFrame(pFrameBuf
, &TempLen
,
733 Len
, pMeasureReportIE
,
736 *pFrameLen
= *pFrameLen
+ TempLen
;
738 if ((ReportLnfoLen
> 0) && (pReportInfo
!= NULL
))
740 MakeOutgoingFrame(pFrameBuf
+ *pFrameLen
, &TempLen
,
741 ReportLnfoLen
, pReportInfo
,
744 *pFrameLen
= *pFrameLen
+ TempLen
;
750 ==========================================================================
752 Prepare Measurement request action frame and enqueue it into
753 management queue waiting for transmition.
756 1. the destination mac address of the frame.
759 ==========================================================================
761 VOID
EnqueueMeasurementReq(
762 IN PRTMP_ADAPTER pAd
,
764 IN UINT8 MeasureToken
,
765 IN UINT8 MeasureReqMode
,
766 IN UINT8 MeasureReqType
,
768 IN UINT16 MeasureDuration
)
770 PUCHAR pOutBuffer
= NULL
;
773 HEADER_802_11 ActHdr
;
774 MEASURE_REQ_INFO MeasureReqIE
;
775 UINT8 RmReqDailogToken
= RandomByte(pAd
);
776 UINT64 MeasureStartTime
= GetCurrentTimeStamp(pAd
);
778 // build action frame header.
779 MgtMacHeaderInit(pAd
, &ActHdr
, SUBTYPE_ACTION
, 0, pDA
,
780 pAd
->CurrentAddress
);
782 NStatus
= MlmeAllocateMemory(pAd
, (PVOID
)&pOutBuffer
); //Get an unused nonpaged memory
783 if(NStatus
!= NDIS_STATUS_SUCCESS
)
785 DBGPRINT(RT_DEBUG_TRACE
, ("%s() allocate memory failed \n", __func__
));
788 NdisMoveMemory(pOutBuffer
, (PCHAR
)&ActHdr
, sizeof(HEADER_802_11
));
789 FrameLen
= sizeof(HEADER_802_11
);
791 InsertActField(pAd
, (pOutBuffer
+ FrameLen
), &FrameLen
, CATEGORY_SPECTRUM
, SPEC_MRQ
);
794 InsertDialogToken(pAd
, (pOutBuffer
+ FrameLen
), &FrameLen
, MeasureToken
);
796 // prepare Measurement IE.
797 NdisZeroMemory(&MeasureReqIE
, sizeof(MEASURE_REQ_INFO
));
798 MeasureReqIE
.Token
= RmReqDailogToken
;
799 MeasureReqIE
.ReqMode
.word
= MeasureReqMode
;
800 MeasureReqIE
.ReqType
= MeasureReqType
;
801 MeasureReqIE
.MeasureReq
.ChNum
= MeasureCh
;
802 MeasureReqIE
.MeasureReq
.MeasureStartTime
= cpu2le64(MeasureStartTime
);
803 MeasureReqIE
.MeasureReq
.MeasureDuration
= cpu2le16(MeasureDuration
);
804 InsertMeasureReqIE(pAd
, (pOutBuffer
+ FrameLen
), &FrameLen
, &MeasureReqIE
);
806 MiniportMMRequest(pAd
, QID_AC_BE
, pOutBuffer
, FrameLen
);
807 MlmeFreeMemory(pAd
, pOutBuffer
);
813 ==========================================================================
815 Prepare Measurement report action frame and enqueue it into
816 management queue waiting for transmition.
819 1. the destination mac address of the frame.
822 ==========================================================================
824 VOID
EnqueueMeasurementRep(
825 IN PRTMP_ADAPTER pAd
,
827 IN UINT8 DialogToken
,
828 IN UINT8 MeasureToken
,
829 IN UINT8 MeasureReqMode
,
830 IN UINT8 MeasureReqType
,
831 IN UINT8 ReportInfoLen
,
832 IN PUINT8 pReportInfo
)
834 PUCHAR pOutBuffer
= NULL
;
837 HEADER_802_11 ActHdr
;
838 MEASURE_REPORT_INFO MeasureRepIE
;
840 // build action frame header.
841 MgtMacHeaderInit(pAd
, &ActHdr
, SUBTYPE_ACTION
, 0, pDA
,
842 pAd
->CurrentAddress
);
844 NStatus
= MlmeAllocateMemory(pAd
, (PVOID
)&pOutBuffer
); //Get an unused nonpaged memory
845 if(NStatus
!= NDIS_STATUS_SUCCESS
)
847 DBGPRINT(RT_DEBUG_TRACE
, ("%s() allocate memory failed \n", __func__
));
850 NdisMoveMemory(pOutBuffer
, (PCHAR
)&ActHdr
, sizeof(HEADER_802_11
));
851 FrameLen
= sizeof(HEADER_802_11
);
853 InsertActField(pAd
, (pOutBuffer
+ FrameLen
), &FrameLen
, CATEGORY_SPECTRUM
, SPEC_MRP
);
856 InsertDialogToken(pAd
, (pOutBuffer
+ FrameLen
), &FrameLen
, DialogToken
);
858 // prepare Measurement IE.
859 NdisZeroMemory(&MeasureRepIE
, sizeof(MEASURE_REPORT_INFO
));
860 MeasureRepIE
.Token
= MeasureToken
;
861 MeasureRepIE
.ReportMode
.word
= MeasureReqMode
;
862 MeasureRepIE
.ReportType
= MeasureReqType
;
863 InsertMeasureReportIE(pAd
, (pOutBuffer
+ FrameLen
), &FrameLen
, &MeasureRepIE
, ReportInfoLen
, pReportInfo
);
865 MiniportMMRequest(pAd
, QID_AC_BE
, pOutBuffer
, FrameLen
);
866 MlmeFreeMemory(pAd
, pOutBuffer
);
872 ==========================================================================
874 Prepare TPC Request action frame and enqueue it into
875 management queue waiting for transmition.
878 1. the destination mac address of the frame.
881 ==========================================================================
884 IN PRTMP_ADAPTER pAd
,
886 IN UCHAR DialogToken
)
888 PUCHAR pOutBuffer
= NULL
;
892 HEADER_802_11 ActHdr
;
894 // build action frame header.
895 MgtMacHeaderInit(pAd
, &ActHdr
, SUBTYPE_ACTION
, 0, pDA
,
896 pAd
->CurrentAddress
);
898 NStatus
= MlmeAllocateMemory(pAd
, (PVOID
)&pOutBuffer
); //Get an unused nonpaged memory
899 if(NStatus
!= NDIS_STATUS_SUCCESS
)
901 DBGPRINT(RT_DEBUG_TRACE
, ("%s() allocate memory failed \n", __func__
));
904 NdisMoveMemory(pOutBuffer
, (PCHAR
)&ActHdr
, sizeof(HEADER_802_11
));
905 FrameLen
= sizeof(HEADER_802_11
);
907 InsertActField(pAd
, (pOutBuffer
+ FrameLen
), &FrameLen
, CATEGORY_SPECTRUM
, SPEC_TPCRQ
);
910 InsertDialogToken(pAd
, (pOutBuffer
+ FrameLen
), &FrameLen
, DialogToken
);
912 // Insert TPC Request IE.
913 InsertTpcReqIE(pAd
, (pOutBuffer
+ FrameLen
), &FrameLen
);
915 MiniportMMRequest(pAd
, QID_AC_BE
, pOutBuffer
, FrameLen
);
916 MlmeFreeMemory(pAd
, pOutBuffer
);
922 ==========================================================================
924 Prepare TPC Report action frame and enqueue it into
925 management queue waiting for transmition.
928 1. the destination mac address of the frame.
931 ==========================================================================
934 IN PRTMP_ADAPTER pAd
,
936 IN UINT8 DialogToken
,
940 PUCHAR pOutBuffer
= NULL
;
944 HEADER_802_11 ActHdr
;
946 // build action frame header.
947 MgtMacHeaderInit(pAd
, &ActHdr
, SUBTYPE_ACTION
, 0, pDA
,
948 pAd
->CurrentAddress
);
950 NStatus
= MlmeAllocateMemory(pAd
, (PVOID
)&pOutBuffer
); //Get an unused nonpaged memory
951 if(NStatus
!= NDIS_STATUS_SUCCESS
)
953 DBGPRINT(RT_DEBUG_TRACE
, ("%s() allocate memory failed \n", __func__
));
956 NdisMoveMemory(pOutBuffer
, (PCHAR
)&ActHdr
, sizeof(HEADER_802_11
));
957 FrameLen
= sizeof(HEADER_802_11
);
959 InsertActField(pAd
, (pOutBuffer
+ FrameLen
), &FrameLen
, CATEGORY_SPECTRUM
, SPEC_TPCRP
);
962 InsertDialogToken(pAd
, (pOutBuffer
+ FrameLen
), &FrameLen
, DialogToken
);
964 // Insert TPC Request IE.
965 InsertTpcReportIE(pAd
, (pOutBuffer
+ FrameLen
), &FrameLen
, TxPwr
, LinkMargin
);
967 MiniportMMRequest(pAd
, QID_AC_BE
, pOutBuffer
, FrameLen
);
968 MlmeFreeMemory(pAd
, pOutBuffer
);
974 ==========================================================================
976 Prepare Channel Switch Announcement action frame and enqueue it into
977 management queue waiting for transmition.
980 1. the destination mac address of the frame.
981 2. Channel switch announcement mode.
982 2. a New selected channel.
985 ==========================================================================
988 IN PRTMP_ADAPTER pAd
,
993 PUCHAR pOutBuffer
= NULL
;
997 HEADER_802_11 ActHdr
;
999 // build action frame header.
1000 MgtMacHeaderInit(pAd
, &ActHdr
, SUBTYPE_ACTION
, 0, pDA
,
1001 pAd
->CurrentAddress
);
1003 NStatus
= MlmeAllocateMemory(pAd
, (PVOID
)&pOutBuffer
); //Get an unused nonpaged memory
1004 if(NStatus
!= NDIS_STATUS_SUCCESS
)
1006 DBGPRINT(RT_DEBUG_TRACE
, ("%s() allocate memory failed \n", __func__
));
1009 NdisMoveMemory(pOutBuffer
, (PCHAR
)&ActHdr
, sizeof(HEADER_802_11
));
1010 FrameLen
= sizeof(HEADER_802_11
);
1012 InsertActField(pAd
, (pOutBuffer
+ FrameLen
), &FrameLen
, CATEGORY_SPECTRUM
, SPEC_CHANNEL_SWITCH
);
1014 InsertChSwAnnIE(pAd
, (pOutBuffer
+ FrameLen
), &FrameLen
, ChSwMode
, NewCh
, 0);
1016 MiniportMMRequest(pAd
, QID_AC_BE
, pOutBuffer
, FrameLen
);
1017 MlmeFreeMemory(pAd
, pOutBuffer
);
1022 static BOOLEAN
DfsRequirementCheck(
1023 IN PRTMP_ADAPTER pAd
,
1026 BOOLEAN Result
= FALSE
;
1031 // check DFS procedure is running.
1032 // make sure DFS procedure won't start twice.
1033 if (pAd
->CommonCfg
.RadarDetect
.RDMode
!= RD_NORMAL_MODE
)
1039 // check the new channel carried from Channel Switch Announcemnet is valid.
1040 for (i
=0; i
<pAd
->ChannelListNum
; i
++)
1042 if ((Channel
== pAd
->ChannelList
[i
].Channel
)
1043 &&(pAd
->ChannelList
[i
].RemainingTimeForUse
== 0))
1045 // found radar signal in the channel. the channel can't use at least for 30 minutes.
1046 pAd
->ChannelList
[i
].RemainingTimeForUse
= 1800;//30 min = 1800 sec
1056 VOID
NotifyChSwAnnToPeerAPs(
1057 IN PRTMP_ADAPTER pAd
,
1065 static VOID
StartDFSProcedure(
1066 IN PRTMP_ADAPTER pAd
,
1070 // start DFS procedure
1071 pAd
->CommonCfg
.Channel
= Channel
;
1073 N_ChannelCheck(pAd
);
1075 pAd
->CommonCfg
.RadarDetect
.RDMode
= RD_SWITCHING_MODE
;
1076 pAd
->CommonCfg
.RadarDetect
.CSCount
= 0;
1080 ==========================================================================
1082 Channel Switch Announcement action frame sanity check.
1085 1. MLME message containing the received frame
1087 3. Channel switch announcement infomation buffer.
1091 ==========================================================================
1095 Channel Switch Announcement IE.
1096 +----+-----+-----------+------------+-----------+
1097 | ID | Len |Ch Sw Mode | New Ch Num | Ch Sw Cnt |
1098 +----+-----+-----------+------------+-----------+
1101 static BOOLEAN
PeerChSwAnnSanity(
1102 IN PRTMP_ADAPTER pAd
,
1105 OUT PCH_SW_ANN_INFO pChSwAnnInfo
)
1107 PFRAME_802_11 Fr
= (PFRAME_802_11
)pMsg
;
1108 PUCHAR pFramePtr
= Fr
->Octet
;
1109 BOOLEAN result
= FALSE
;
1110 PEID_STRUCT eid_ptr
;
1112 // skip 802.11 header.
1113 MsgLen
-= sizeof(HEADER_802_11
);
1115 // skip category and action code.
1119 if (pChSwAnnInfo
== NULL
)
1122 eid_ptr
= (PEID_STRUCT
)pFramePtr
;
1123 while (((UCHAR
*)eid_ptr
+ eid_ptr
->Len
+ 1) < ((PUCHAR
)pFramePtr
+ MsgLen
))
1125 switch(eid_ptr
->Eid
)
1127 case IE_CHANNEL_SWITCH_ANNOUNCEMENT
:
1128 NdisMoveMemory(&pChSwAnnInfo
->ChSwMode
, eid_ptr
->Octet
, 1);
1129 NdisMoveMemory(&pChSwAnnInfo
->Channel
, eid_ptr
->Octet
+ 1, 1);
1130 NdisMoveMemory(&pChSwAnnInfo
->ChSwCnt
, eid_ptr
->Octet
+ 2, 1);
1138 eid_ptr
= (PEID_STRUCT
)((UCHAR
*)eid_ptr
+ 2 + eid_ptr
->Len
);
1145 ==========================================================================
1147 Measurement request action frame sanity check.
1150 1. MLME message containing the received frame
1152 3. Measurement request infomation buffer.
1155 ==========================================================================
1157 static BOOLEAN
PeerMeasureReqSanity(
1158 IN PRTMP_ADAPTER pAd
,
1161 OUT PUINT8 pDialogToken
,
1162 OUT PMEASURE_REQ_INFO pMeasureReqInfo
)
1164 PFRAME_802_11 Fr
= (PFRAME_802_11
)pMsg
;
1165 PUCHAR pFramePtr
= Fr
->Octet
;
1166 BOOLEAN result
= FALSE
;
1167 PEID_STRUCT eid_ptr
;
1169 UINT64 MeasureStartTime
;
1170 UINT16 MeasureDuration
;
1172 // skip 802.11 header.
1173 MsgLen
-= sizeof(HEADER_802_11
);
1175 // skip category and action code.
1179 if (pMeasureReqInfo
== NULL
)
1182 NdisMoveMemory(pDialogToken
, pFramePtr
, 1);
1186 eid_ptr
= (PEID_STRUCT
)pFramePtr
;
1187 while (((UCHAR
*)eid_ptr
+ eid_ptr
->Len
+ 1) < ((PUCHAR
)pFramePtr
+ MsgLen
))
1189 switch(eid_ptr
->Eid
)
1191 case IE_MEASUREMENT_REQUEST
:
1192 NdisMoveMemory(&pMeasureReqInfo
->Token
, eid_ptr
->Octet
, 1);
1193 NdisMoveMemory(&pMeasureReqInfo
->ReqMode
.word
, eid_ptr
->Octet
+ 1, 1);
1194 NdisMoveMemory(&pMeasureReqInfo
->ReqType
, eid_ptr
->Octet
+ 2, 1);
1195 ptr
= eid_ptr
->Octet
+ 3;
1196 NdisMoveMemory(&pMeasureReqInfo
->MeasureReq
.ChNum
, ptr
, 1);
1197 NdisMoveMemory(&MeasureStartTime
, ptr
+ 1, 8);
1198 pMeasureReqInfo
->MeasureReq
.MeasureStartTime
= SWAP64(MeasureStartTime
);
1199 NdisMoveMemory(&MeasureDuration
, ptr
+ 9, 2);
1200 pMeasureReqInfo
->MeasureReq
.MeasureDuration
= SWAP16(MeasureDuration
);
1208 eid_ptr
= (PEID_STRUCT
)((UCHAR
*)eid_ptr
+ 2 + eid_ptr
->Len
);
1215 ==========================================================================
1217 Measurement report action frame sanity check.
1220 1. MLME message containing the received frame
1222 3. Measurement report infomation buffer.
1223 4. basic report infomation buffer.
1226 ==========================================================================
1230 Measurement Report IE.
1231 +----+-----+-------+-------------+--------------+----------------+
1232 | ID | Len | Token | Report Mode | Measure Type | Measure Report |
1233 +----+-----+-------+-------------+--------------+----------------+
1237 +--------+------------+----------+-----+
1238 | Ch Num | Start Time | Duration | Map |
1239 +--------+------------+----------+-----+
1242 Map Field Bit Format.
1243 +-----+---------------+---------------------+-------+------------+----------+
1244 | Bss | OFDM Preamble | Unidentified signal | Radar | Unmeasured | Reserved |
1245 +-----+---------------+---------------------+-------+------------+----------+
1248 static BOOLEAN
PeerMeasureReportSanity(
1249 IN PRTMP_ADAPTER pAd
,
1252 OUT PUINT8 pDialogToken
,
1253 OUT PMEASURE_REPORT_INFO pMeasureReportInfo
,
1254 OUT PUINT8 pReportBuf
)
1256 PFRAME_802_11 Fr
= (PFRAME_802_11
)pMsg
;
1257 PUCHAR pFramePtr
= Fr
->Octet
;
1258 BOOLEAN result
= FALSE
;
1259 PEID_STRUCT eid_ptr
;
1262 // skip 802.11 header.
1263 MsgLen
-= sizeof(HEADER_802_11
);
1265 // skip category and action code.
1269 if (pMeasureReportInfo
== NULL
)
1272 NdisMoveMemory(pDialogToken
, pFramePtr
, 1);
1276 eid_ptr
= (PEID_STRUCT
)pFramePtr
;
1277 while (((UCHAR
*)eid_ptr
+ eid_ptr
->Len
+ 1) < ((PUCHAR
)pFramePtr
+ MsgLen
))
1279 switch(eid_ptr
->Eid
)
1281 case IE_MEASUREMENT_REPORT
:
1282 NdisMoveMemory(&pMeasureReportInfo
->Token
, eid_ptr
->Octet
, 1);
1283 NdisMoveMemory(&pMeasureReportInfo
->ReportMode
, eid_ptr
->Octet
+ 1, 1);
1284 NdisMoveMemory(&pMeasureReportInfo
->ReportType
, eid_ptr
->Octet
+ 2, 1);
1285 if (pMeasureReportInfo
->ReportType
== RM_BASIC
)
1287 PMEASURE_BASIC_REPORT pReport
= (PMEASURE_BASIC_REPORT
)pReportBuf
;
1288 ptr
= eid_ptr
->Octet
+ 3;
1289 NdisMoveMemory(&pReport
->ChNum
, ptr
, 1);
1290 NdisMoveMemory(&pReport
->MeasureStartTime
, ptr
+ 1, 8);
1291 NdisMoveMemory(&pReport
->MeasureDuration
, ptr
+ 9, 2);
1292 NdisMoveMemory(&pReport
->Map
, ptr
+ 11, 1);
1295 else if (pMeasureReportInfo
->ReportType
== RM_CCA
)
1297 PMEASURE_CCA_REPORT pReport
= (PMEASURE_CCA_REPORT
)pReportBuf
;
1298 ptr
= eid_ptr
->Octet
+ 3;
1299 NdisMoveMemory(&pReport
->ChNum
, ptr
, 1);
1300 NdisMoveMemory(&pReport
->MeasureStartTime
, ptr
+ 1, 8);
1301 NdisMoveMemory(&pReport
->MeasureDuration
, ptr
+ 9, 2);
1302 NdisMoveMemory(&pReport
->CCA_Busy_Fraction
, ptr
+ 11, 1);
1305 else if (pMeasureReportInfo
->ReportType
== RM_RPI_HISTOGRAM
)
1307 PMEASURE_RPI_REPORT pReport
= (PMEASURE_RPI_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
->RPI_Density
, ptr
+ 11, 8);
1320 eid_ptr
= (PEID_STRUCT
)((UCHAR
*)eid_ptr
+ 2 + eid_ptr
->Len
);
1327 ==========================================================================
1329 TPC Request action frame sanity check.
1332 1. MLME message containing the received frame
1337 ==========================================================================
1339 static BOOLEAN
PeerTpcReqSanity(
1340 IN PRTMP_ADAPTER pAd
,
1343 OUT PUINT8 pDialogToken
)
1345 PFRAME_802_11 Fr
= (PFRAME_802_11
)pMsg
;
1346 PUCHAR pFramePtr
= Fr
->Octet
;
1347 BOOLEAN result
= FALSE
;
1348 PEID_STRUCT eid_ptr
;
1350 MsgLen
-= sizeof(HEADER_802_11
);
1352 // skip category and action code.
1356 if (pDialogToken
== NULL
)
1359 NdisMoveMemory(pDialogToken
, pFramePtr
, 1);
1363 eid_ptr
= (PEID_STRUCT
)pFramePtr
;
1364 while (((UCHAR
*)eid_ptr
+ eid_ptr
->Len
+ 1) < ((PUCHAR
)pFramePtr
+ MsgLen
))
1366 switch(eid_ptr
->Eid
)
1368 case IE_TPC_REQUEST
:
1375 eid_ptr
= (PEID_STRUCT
)((UCHAR
*)eid_ptr
+ 2 + eid_ptr
->Len
);
1382 ==========================================================================
1384 TPC Report action frame sanity check.
1387 1. MLME message containing the received frame
1393 ==========================================================================
1395 static BOOLEAN
PeerTpcRepSanity(
1396 IN PRTMP_ADAPTER pAd
,
1399 OUT PUINT8 pDialogToken
,
1400 OUT PTPC_REPORT_INFO pTpcRepInfo
)
1402 PFRAME_802_11 Fr
= (PFRAME_802_11
)pMsg
;
1403 PUCHAR pFramePtr
= Fr
->Octet
;
1404 BOOLEAN result
= FALSE
;
1405 PEID_STRUCT eid_ptr
;
1407 MsgLen
-= sizeof(HEADER_802_11
);
1409 // skip category and action code.
1413 if (pDialogToken
== NULL
)
1416 NdisMoveMemory(pDialogToken
, pFramePtr
, 1);
1420 eid_ptr
= (PEID_STRUCT
)pFramePtr
;
1421 while (((UCHAR
*)eid_ptr
+ eid_ptr
->Len
+ 1) < ((PUCHAR
)pFramePtr
+ MsgLen
))
1423 switch(eid_ptr
->Eid
)
1426 NdisMoveMemory(&pTpcRepInfo
->TxPwr
, eid_ptr
->Octet
, 1);
1427 NdisMoveMemory(&pTpcRepInfo
->LinkMargin
, eid_ptr
->Octet
+ 1, 1);
1434 eid_ptr
= (PEID_STRUCT
)((UCHAR
*)eid_ptr
+ 2 + eid_ptr
->Len
);
1441 ==========================================================================
1443 Channel Switch Announcement action frame handler.
1446 Elme - MLME message containing the received frame
1449 ==========================================================================
1451 static VOID
PeerChSwAnnAction(
1452 IN PRTMP_ADAPTER pAd
,
1453 IN MLME_QUEUE_ELEM
*Elem
)
1455 CH_SW_ANN_INFO ChSwAnnInfo
;
1456 PFRAME_802_11 pFr
= (PFRAME_802_11
)Elem
->Msg
;
1457 UCHAR index
= 0, Channel
= 0, NewChannel
= 0;
1460 NdisZeroMemory(&ChSwAnnInfo
, sizeof(CH_SW_ANN_INFO
));
1461 if (! PeerChSwAnnSanity(pAd
, Elem
->Msg
, Elem
->MsgLen
, &ChSwAnnInfo
))
1463 DBGPRINT(RT_DEBUG_TRACE
, ("Invalid Channel Switch Action Frame.\n"));
1467 if (pAd
->OpMode
== OPMODE_STA
)
1469 Bssidx
= BssTableSearch(&pAd
->ScanTab
, pFr
->Hdr
.Addr3
, pAd
->CommonCfg
.Channel
);
1470 if (Bssidx
== BSS_NOT_FOUND
)
1472 DBGPRINT(RT_DEBUG_TRACE
, ("PeerChSwAnnAction - Bssidx is not found\n"));
1476 DBGPRINT(RT_DEBUG_TRACE
, ("\n****Bssidx is %d, Channel = %d\n", index
, pAd
->ScanTab
.BssEntry
[Bssidx
].Channel
));
1477 hex_dump("SSID",pAd
->ScanTab
.BssEntry
[Bssidx
].Bssid
,6);
1479 Channel
= pAd
->CommonCfg
.Channel
;
1480 NewChannel
= ChSwAnnInfo
.Channel
;
1482 if ((pAd
->CommonCfg
.bIEEE80211H
== 1) && (NewChannel
!= 0) && (Channel
!= NewChannel
))
1484 // Switching to channel 1 can prevent from rescanning the current channel immediately (by auto reconnection).
1485 // In addition, clear the MLME queue and the scan table to discard the RX packets and previous scanning results.
1486 AsicSwitchChannel(pAd
, 1, FALSE
);
1487 AsicLockChannel(pAd
, 1);
1488 LinkDown(pAd
, FALSE
);
1489 MlmeQueueInit(&pAd
->Mlme
.Queue
);
1490 BssTableInit(&pAd
->ScanTab
);
1491 RTMPusecDelay(1000000); // use delay to prevent STA do reassoc
1493 // channel sanity check
1494 for (index
= 0 ; index
< pAd
->ChannelListNum
; index
++)
1496 if (pAd
->ChannelList
[index
].Channel
== NewChannel
)
1498 pAd
->ScanTab
.BssEntry
[Bssidx
].Channel
= NewChannel
;
1499 pAd
->CommonCfg
.Channel
= NewChannel
;
1500 AsicSwitchChannel(pAd
, pAd
->CommonCfg
.Channel
, FALSE
);
1501 AsicLockChannel(pAd
, pAd
->CommonCfg
.Channel
);
1502 DBGPRINT(RT_DEBUG_TRACE
, ("&&&&&&&&&&&&&&&&PeerChSwAnnAction - STA receive channel switch announcement IE (New Channel =%d)\n", NewChannel
));
1507 if (index
>= pAd
->ChannelListNum
)
1509 DBGPRINT_ERR(("&&&&&&&&&&&&&&&&&&&&&&&&&&PeerChSwAnnAction(can not find New Channel=%d in ChannelList[%d]\n", pAd
->CommonCfg
.Channel
, pAd
->ChannelListNum
));
1519 ==========================================================================
1521 Measurement Request action frame handler.
1524 Elme - MLME message containing the received frame
1527 ==========================================================================
1529 static VOID
PeerMeasureReqAction(
1530 IN PRTMP_ADAPTER pAd
,
1531 IN MLME_QUEUE_ELEM
*Elem
)
1533 PFRAME_802_11 pFr
= (PFRAME_802_11
)Elem
->Msg
;
1535 MEASURE_REQ_INFO MeasureReqInfo
;
1536 MEASURE_REPORT_MODE ReportMode
;
1538 if(PeerMeasureReqSanity(pAd
, Elem
->Msg
, Elem
->MsgLen
, &DialogToken
, &MeasureReqInfo
))
1540 ReportMode
.word
= 0;
1541 ReportMode
.field
.Incapable
= 1;
1542 EnqueueMeasurementRep(pAd
, pFr
->Hdr
.Addr2
, DialogToken
, MeasureReqInfo
.Token
, ReportMode
.word
, MeasureReqInfo
.ReqType
, 0, NULL
);
1549 ==========================================================================
1551 Measurement Report action frame handler.
1554 Elme - MLME message containing the received frame
1557 ==========================================================================
1559 static VOID
PeerMeasureReportAction(
1560 IN PRTMP_ADAPTER pAd
,
1561 IN MLME_QUEUE_ELEM
*Elem
)
1563 MEASURE_REPORT_INFO MeasureReportInfo
;
1564 PFRAME_802_11 pFr
= (PFRAME_802_11
)Elem
->Msg
;
1566 PUINT8 pMeasureReportInfo
;
1568 // if (pAd->CommonCfg.bIEEE80211H != TRUE)
1571 if ((pMeasureReportInfo
= kmalloc(sizeof(MEASURE_RPI_REPORT
), GFP_ATOMIC
)) == NULL
)
1573 DBGPRINT(RT_DEBUG_ERROR
, ("%s unable to alloc memory for measure report buffer (size=%zu).\n", __func__
, sizeof(MEASURE_RPI_REPORT
)));
1577 NdisZeroMemory(&MeasureReportInfo
, sizeof(MEASURE_REPORT_INFO
));
1578 NdisZeroMemory(pMeasureReportInfo
, sizeof(MEASURE_RPI_REPORT
));
1579 if (PeerMeasureReportSanity(pAd
, Elem
->Msg
, Elem
->MsgLen
, &DialogToken
, &MeasureReportInfo
, pMeasureReportInfo
))
1582 PMEASURE_REQ_ENTRY pEntry
= NULL
;
1584 // Not a autonomous measure report.
1585 // check the dialog token field. drop it if the dialog token doesn't match.
1586 if ((DialogToken
!= 0)
1587 && ((pEntry
= MeasureReqLookUp(pAd
, DialogToken
)) == NULL
))
1591 MeasureReqDelete(pAd
, pEntry
->DialogToken
);
1593 if (MeasureReportInfo
.ReportType
== RM_BASIC
)
1595 PMEASURE_BASIC_REPORT pBasicReport
= (PMEASURE_BASIC_REPORT
)pMeasureReportInfo
;
1596 if ((pBasicReport
->Map
.field
.Radar
)
1597 && (DfsRequirementCheck(pAd
, pBasicReport
->ChNum
) == TRUE
))
1599 NotifyChSwAnnToPeerAPs(pAd
, pFr
->Hdr
.Addr1
, pFr
->Hdr
.Addr2
, 1, pBasicReport
->ChNum
);
1600 StartDFSProcedure(pAd
, pBasicReport
->ChNum
, 1);
1606 DBGPRINT(RT_DEBUG_TRACE
, ("Invalid Measurement Report Frame.\n"));
1608 kfree(pMeasureReportInfo
);
1614 ==========================================================================
1616 TPC Request action frame handler.
1619 Elme - MLME message containing the received frame
1622 ==========================================================================
1624 static VOID
PeerTpcReqAction(
1625 IN PRTMP_ADAPTER pAd
,
1626 IN MLME_QUEUE_ELEM
*Elem
)
1628 PFRAME_802_11 pFr
= (PFRAME_802_11
)Elem
->Msg
;
1629 PUCHAR pFramePtr
= pFr
->Octet
;
1631 UINT8 TxPwr
= GetCurTxPwr(pAd
, Elem
->Wcid
);
1632 UINT8 LinkMargin
= 0;
1635 // link margin: Ratio of the received signal power to the minimum desired by the station (STA). The
1636 // STA may incorporate rate information and channel conditions, including interference, into its computation
1639 RealRssi
= RTMPMaxRssi(pAd
, ConvertToRssi(pAd
, Elem
->Rssi0
, RSSI_0
),
1640 ConvertToRssi(pAd
, Elem
->Rssi1
, RSSI_1
),
1641 ConvertToRssi(pAd
, Elem
->Rssi2
, RSSI_2
));
1643 // skip Category and action code.
1647 NdisMoveMemory(&DialogToken
, pFramePtr
, 1);
1649 LinkMargin
= (RealRssi
/ MIN_RCV_PWR
);
1650 if (PeerTpcReqSanity(pAd
, Elem
->Msg
, Elem
->MsgLen
, &DialogToken
))
1651 EnqueueTPCRep(pAd
, pFr
->Hdr
.Addr2
, DialogToken
, TxPwr
, LinkMargin
);
1657 ==========================================================================
1659 TPC Report action frame handler.
1662 Elme - MLME message containing the received frame
1665 ==========================================================================
1667 static VOID
PeerTpcRepAction(
1668 IN PRTMP_ADAPTER pAd
,
1669 IN MLME_QUEUE_ELEM
*Elem
)
1672 TPC_REPORT_INFO TpcRepInfo
;
1673 PTPC_REQ_ENTRY pEntry
= NULL
;
1675 NdisZeroMemory(&TpcRepInfo
, sizeof(TPC_REPORT_INFO
));
1676 if (PeerTpcRepSanity(pAd
, Elem
->Msg
, Elem
->MsgLen
, &DialogToken
, &TpcRepInfo
))
1678 if ((pEntry
= TpcReqLookUp(pAd
, DialogToken
)) != NULL
)
1680 TpcReqDelete(pAd
, pEntry
->DialogToken
);
1681 DBGPRINT(RT_DEBUG_TRACE
, ("%s: DialogToken=%x, TxPwr=%d, LinkMargin=%d\n",
1682 __func__
, DialogToken
, TpcRepInfo
.TxPwr
, TpcRepInfo
.LinkMargin
));
1690 ==========================================================================
1692 Spectrun action frames Handler such as channel switch annoucement,
1693 measurement report, measurement request actions frames.
1696 Elme - MLME message containing the received frame
1699 ==========================================================================
1701 VOID
PeerSpectrumAction(
1702 IN PRTMP_ADAPTER pAd
,
1703 IN MLME_QUEUE_ELEM
*Elem
)
1706 UCHAR Action
= Elem
->Msg
[LENGTH_802_11
+1];
1708 if (pAd
->CommonCfg
.bIEEE80211H
!= TRUE
)
1714 // current rt2860 unable do such measure specified in Measurement Request.
1715 // reject all measurement request.
1716 PeerMeasureReqAction(pAd
, Elem
);
1720 PeerMeasureReportAction(pAd
, Elem
);
1724 PeerTpcReqAction(pAd
, Elem
);
1728 PeerTpcRepAction(pAd
, Elem
);
1731 case SPEC_CHANNEL_SWITCH
:
1734 PeerChSwAnnAction(pAd
, Elem
);
1742 ==========================================================================
1748 ==========================================================================
1750 INT
Set_MeasureReq_Proc(
1751 IN PRTMP_ADAPTER pAd
,
1758 MEASURE_REQ_MODE MeasureReqMode
;
1759 UINT8 MeasureReqToken
= RandomByte(pAd
);
1760 UINT8 MeasureReqType
= RM_BASIC
;
1761 UINT8 MeasureCh
= 1;
1764 while ((thisChar
= strsep((char **)&arg
, "-")) != NULL
)
1769 Aid
= simple_strtol(thisChar
, 0, 16);
1772 case 2: // Measurement Request Type.
1773 MeasureReqType
= simple_strtol(thisChar
, 0, 16);
1774 if (MeasureReqType
> 3)
1776 DBGPRINT(RT_DEBUG_ERROR
, ("%s: unknow MeasureReqType(%d)\n", __func__
, MeasureReqType
));
1781 case 3: // Measurement channel.
1782 MeasureCh
= simple_strtol(thisChar
, 0, 16);
1788 DBGPRINT(RT_DEBUG_TRACE
, ("%s::Aid = %d, MeasureReqType=%d MeasureCh=%d\n", __func__
, Aid
, MeasureReqType
, MeasureCh
));
1789 if (!VALID_WCID(Aid
))
1791 DBGPRINT(RT_DEBUG_ERROR
, ("%s: unknow sta of Aid(%d)\n", __func__
, Aid
));
1795 MeasureReqMode
.word
= 0;
1796 MeasureReqMode
.field
.Enable
= 1;
1798 MeasureReqInsert(pAd
, MeasureReqToken
);
1800 EnqueueMeasurementReq(pAd
, pAd
->MacTab
.Content
[Aid
].Addr
,
1801 MeasureReqToken
, MeasureReqMode
.word
, MeasureReqType
, MeasureCh
, 2000);
1806 INT
Set_TpcReq_Proc(
1807 IN PRTMP_ADAPTER pAd
,
1812 UINT8 TpcReqToken
= RandomByte(pAd
);
1814 Aid
= simple_strtol(arg
, 0, 16);
1816 DBGPRINT(RT_DEBUG_TRACE
, ("%s::Aid = %d\n", __func__
, Aid
));
1817 if (!VALID_WCID(Aid
))
1819 DBGPRINT(RT_DEBUG_ERROR
, ("%s: unknow sta of Aid(%d)\n", __func__
, Aid
));
1823 TpcReqInsert(pAd
, TpcReqToken
);
1825 EnqueueTPCReq(pAd
, pAd
->MacTab
.Content
[Aid
].Addr
, TpcReqToken
);