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 *************************************************************************
31 Handle association related requests either from WSTA or from local MLME
35 --------- ---------- ----------------------------------------------
36 Fonchi Wu 2008 created for 802.11h
39 #include "../rt_config.h"
42 VOID MeasureReqTabInit(
45 NdisAllocateSpinLock(&pAd->CommonCfg.MeasureReqTabLock);
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));
51 DBGPRINT(RT_DEBUG_ERROR, ("%s Fail to alloc memory for pAd->CommonCfg.pMeasureReqTab.\n", __func__));
56 VOID MeasureReqTabExit(
59 NdisFreeSpinLock(pAd->CommonCfg.MeasureReqTabLock);
61 if (pAd->CommonCfg.pMeasureReqTab)
62 kfree(pAd->CommonCfg.pMeasureReqTab);
63 pAd->CommonCfg.pMeasureReqTab = NULL;
68 static PMEASURE_REQ_ENTRY MeasureReqLookUp(
73 PMEASURE_REQ_TAB pTab = pAd->CommonCfg.pMeasureReqTab;
74 PMEASURE_REQ_ENTRY pEntry = NULL;
75 PMEASURE_REQ_ENTRY pPrevEntry = NULL;
79 DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab doesn't exist.\n", __func__));
83 RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock);
85 HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(DialogToken);
86 pEntry = pTab->Hash[HashIdx];
90 if (pEntry->DialogToken == DialogToken)
95 pEntry = pEntry->pNext;
99 RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock);
104 static PMEASURE_REQ_ENTRY MeasureReqInsert(
105 IN PRTMP_ADAPTER pAd,
106 IN UINT8 DialogToken)
110 PMEASURE_REQ_TAB pTab = pAd->CommonCfg.pMeasureReqTab;
111 PMEASURE_REQ_ENTRY pEntry = NULL, pCurrEntry;
116 DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab doesn't exist.\n", __func__));
120 pEntry = MeasureReqLookUp(pAd, DialogToken);
123 RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock);
124 for (i = 0; i < MAX_MEASURE_REQ_TAB_SIZE; i++)
126 NdisGetSystemUpTime(&Now);
127 pEntry = &pTab->Content[i];
129 if ((pEntry->Valid == TRUE)
130 && RTMP_TIME_AFTER((unsigned long)Now, (unsigned long)(pEntry->lastTime + MQ_REQ_AGE_OUT)))
132 PMEASURE_REQ_ENTRY pPrevEntry = NULL;
133 ULONG HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken);
134 PMEASURE_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx];
139 if (pProbeEntry == pEntry)
141 if (pPrevEntry == NULL)
143 pTab->Hash[HashIdx] = pEntry->pNext;
147 pPrevEntry->pNext = pEntry->pNext;
152 pPrevEntry = pProbeEntry;
153 pProbeEntry = pProbeEntry->pNext;
154 } while (pProbeEntry);
156 NdisZeroMemory(pEntry, sizeof(MEASURE_REQ_ENTRY));
162 if (pEntry->Valid == FALSE)
166 if (i < MAX_MEASURE_REQ_TAB_SIZE)
168 NdisGetSystemUpTime(&Now);
169 pEntry->lastTime = Now;
170 pEntry->Valid = TRUE;
171 pEntry->DialogToken = DialogToken;
177 DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab tab full.\n", __func__));
180 // add this Neighbor entry into HASH table
183 HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(DialogToken);
184 if (pTab->Hash[HashIdx] == NULL)
186 pTab->Hash[HashIdx] = pEntry;
190 pCurrEntry = pTab->Hash[HashIdx];
191 while (pCurrEntry->pNext != NULL)
192 pCurrEntry = pCurrEntry->pNext;
193 pCurrEntry->pNext = pEntry;
197 RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock);
203 static VOID MeasureReqDelete(
204 IN PRTMP_ADAPTER pAd,
205 IN UINT8 DialogToken)
207 PMEASURE_REQ_TAB pTab = pAd->CommonCfg.pMeasureReqTab;
208 PMEASURE_REQ_ENTRY pEntry = NULL;
212 DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab doesn't exist.\n", __func__));
219 DBGPRINT(RT_DEBUG_ERROR, ("pMeasureReqTab empty.\n"));
223 pEntry = MeasureReqLookUp(pAd, DialogToken);
226 PMEASURE_REQ_ENTRY pPrevEntry = NULL;
227 ULONG HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken);
228 PMEASURE_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx];
230 RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock);
234 if (pProbeEntry == pEntry)
236 if (pPrevEntry == NULL)
238 pTab->Hash[HashIdx] = pEntry->pNext;
242 pPrevEntry->pNext = pEntry->pNext;
247 pPrevEntry = pProbeEntry;
248 pProbeEntry = pProbeEntry->pNext;
249 } while (pProbeEntry);
251 NdisZeroMemory(pEntry, sizeof(MEASURE_REQ_ENTRY));
254 RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock);
261 IN PRTMP_ADAPTER pAd)
263 NdisAllocateSpinLock(&pAd->CommonCfg.TpcReqTabLock);
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));
269 DBGPRINT(RT_DEBUG_ERROR, ("%s Fail to alloc memory for pAd->CommonCfg.pTpcReqTab.\n", __func__));
275 IN PRTMP_ADAPTER pAd)
277 NdisFreeSpinLock(pAd->CommonCfg.TpcReqTabLock);
279 if (pAd->CommonCfg.pTpcReqTab)
280 kfree(pAd->CommonCfg.pTpcReqTab);
281 pAd->CommonCfg.pTpcReqTab = NULL;
286 static PTPC_REQ_ENTRY TpcReqLookUp(
287 IN PRTMP_ADAPTER pAd,
288 IN UINT8 DialogToken)
291 PTPC_REQ_TAB pTab = pAd->CommonCfg.pTpcReqTab;
292 PTPC_REQ_ENTRY pEntry = NULL;
293 PTPC_REQ_ENTRY pPrevEntry = NULL;
297 DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab doesn't exist.\n", __func__));
301 RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock);
303 HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(DialogToken);
304 pEntry = pTab->Hash[HashIdx];
308 if (pEntry->DialogToken == DialogToken)
313 pEntry = pEntry->pNext;
317 RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock);
323 static PTPC_REQ_ENTRY TpcReqInsert(
324 IN PRTMP_ADAPTER pAd,
325 IN UINT8 DialogToken)
329 PTPC_REQ_TAB pTab = pAd->CommonCfg.pTpcReqTab;
330 PTPC_REQ_ENTRY pEntry = NULL, pCurrEntry;
335 DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab doesn't exist.\n", __func__));
339 pEntry = TpcReqLookUp(pAd, DialogToken);
342 RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock);
343 for (i = 0; i < MAX_TPC_REQ_TAB_SIZE; i++)
345 NdisGetSystemUpTime(&Now);
346 pEntry = &pTab->Content[i];
348 if ((pEntry->Valid == TRUE)
349 && RTMP_TIME_AFTER((unsigned long)Now, (unsigned long)(pEntry->lastTime + TPC_REQ_AGE_OUT)))
351 PTPC_REQ_ENTRY pPrevEntry = NULL;
352 ULONG HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken);
353 PTPC_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx];
358 if (pProbeEntry == pEntry)
360 if (pPrevEntry == NULL)
362 pTab->Hash[HashIdx] = pEntry->pNext;
366 pPrevEntry->pNext = pEntry->pNext;
371 pPrevEntry = pProbeEntry;
372 pProbeEntry = pProbeEntry->pNext;
373 } while (pProbeEntry);
375 NdisZeroMemory(pEntry, sizeof(TPC_REQ_ENTRY));
381 if (pEntry->Valid == FALSE)
385 if (i < MAX_TPC_REQ_TAB_SIZE)
387 NdisGetSystemUpTime(&Now);
388 pEntry->lastTime = Now;
389 pEntry->Valid = TRUE;
390 pEntry->DialogToken = DialogToken;
396 DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab tab full.\n", __func__));
399 // add this Neighbor entry into HASH table
402 HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(DialogToken);
403 if (pTab->Hash[HashIdx] == NULL)
405 pTab->Hash[HashIdx] = pEntry;
409 pCurrEntry = pTab->Hash[HashIdx];
410 while (pCurrEntry->pNext != NULL)
411 pCurrEntry = pCurrEntry->pNext;
412 pCurrEntry->pNext = pEntry;
416 RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock);
422 static VOID TpcReqDelete(
423 IN PRTMP_ADAPTER pAd,
424 IN UINT8 DialogToken)
426 PTPC_REQ_TAB pTab = pAd->CommonCfg.pTpcReqTab;
427 PTPC_REQ_ENTRY pEntry = NULL;
431 DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab doesn't exist.\n", __func__));
438 DBGPRINT(RT_DEBUG_ERROR, ("pTpcReqTab empty.\n"));
442 pEntry = TpcReqLookUp(pAd, DialogToken);
445 PTPC_REQ_ENTRY pPrevEntry = NULL;
446 ULONG HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken);
447 PTPC_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx];
449 RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock);
453 if (pProbeEntry == pEntry)
455 if (pPrevEntry == NULL)
457 pTab->Hash[HashIdx] = pEntry->pNext;
461 pPrevEntry->pNext = pEntry->pNext;
466 pPrevEntry = pProbeEntry;
467 pProbeEntry = pProbeEntry->pNext;
468 } while (pProbeEntry);
470 NdisZeroMemory(pEntry, sizeof(TPC_REQ_ENTRY));
473 RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock);
480 ==========================================================================
482 Get Current TimeS tamp.
486 Return : Current Time Stamp.
487 ==========================================================================
489 static UINT64 GetCurrentTimeStamp(
490 IN PRTMP_ADAPTER pAd)
492 // get current time stamp.
497 ==========================================================================
499 Get Current Transmit Power.
503 Return : Current Time Stamp.
504 ==========================================================================
506 static UINT8 GetCurTxPwr(
507 IN PRTMP_ADAPTER pAd,
510 return 16; /* 16 dBm */
514 ==========================================================================
516 Insert Dialog Token into frame.
519 1. frame buffer pointer.
524 ==========================================================================
526 static VOID InsertDialogToken(
527 IN PRTMP_ADAPTER pAd,
528 OUT PUCHAR pFrameBuf,
529 OUT PULONG pFrameLen,
530 IN UINT8 DialogToken)
533 MakeOutgoingFrame(pFrameBuf, &TempLen,
537 *pFrameLen = *pFrameLen + TempLen;
543 ==========================================================================
545 Insert TPC Request IE into frame.
548 1. frame buffer pointer.
552 ==========================================================================
554 static VOID InsertTpcReqIE(
555 IN PRTMP_ADAPTER pAd,
556 OUT PUCHAR pFrameBuf,
557 OUT PULONG pFrameLen)
561 UINT8 ElementID = IE_TPC_REQUEST;
563 MakeOutgoingFrame(pFrameBuf, &TempLen,
568 *pFrameLen = *pFrameLen + TempLen;
574 ==========================================================================
576 Insert TPC Report IE into frame.
579 1. frame buffer pointer.
585 ==========================================================================
587 static VOID InsertTpcReportIE(
588 IN PRTMP_ADAPTER pAd,
589 OUT PUCHAR pFrameBuf,
590 OUT PULONG pFrameLen,
595 ULONG Len = sizeof(TPC_REPORT_INFO);
596 UINT8 ElementID = IE_TPC_REPORT;
597 TPC_REPORT_INFO TpcReportIE;
599 TpcReportIE.TxPwr = TxPwr;
600 TpcReportIE.LinkMargin = LinkMargin;
602 MakeOutgoingFrame(pFrameBuf, &TempLen,
608 *pFrameLen = *pFrameLen + TempLen;
615 ==========================================================================
617 Insert Channel Switch Announcement IE into frame.
620 1. frame buffer pointer.
622 3. channel switch announcement mode.
623 4. new selected channel.
624 5. channel switch announcement count.
627 ==========================================================================
629 static VOID InsertChSwAnnIE(
630 IN PRTMP_ADAPTER pAd,
631 OUT PUCHAR pFrameBuf,
632 OUT PULONG pFrameLen,
638 ULONG Len = sizeof(CH_SW_ANN_INFO);
639 UINT8 ElementID = IE_CHANNEL_SWITCH_ANNOUNCEMENT;
640 CH_SW_ANN_INFO ChSwAnnIE;
642 ChSwAnnIE.ChSwMode = ChSwMode;
643 ChSwAnnIE.Channel = NewChannel;
644 ChSwAnnIE.ChSwCnt = ChSwCnt;
646 MakeOutgoingFrame(pFrameBuf, &TempLen,
652 *pFrameLen = *pFrameLen + TempLen;
659 ==========================================================================
661 Insert Measure Request IE into frame.
664 1. frame buffer pointer.
667 4. Measure Request Mode.
668 5. Measure Request Type.
670 7. Measure Start time.
675 ==========================================================================
677 static VOID InsertMeasureReqIE(
678 IN PRTMP_ADAPTER pAd,
679 OUT PUCHAR pFrameBuf,
680 OUT PULONG pFrameLen,
681 IN PMEASURE_REQ_INFO pMeasureReqIE)
684 UINT8 Len = sizeof(MEASURE_REQ_INFO);
685 UINT8 ElementID = IE_MEASUREMENT_REQUEST;
687 MakeOutgoingFrame(pFrameBuf, &TempLen,
693 *pFrameLen = *pFrameLen + TempLen;
699 ==========================================================================
701 Insert Measure Report IE into frame.
704 1. frame buffer pointer.
707 4. Measure Request Mode.
708 5. Measure Request Type.
709 6. Length of Report Infomation
710 7. Pointer of Report Infomation Buffer.
713 ==========================================================================
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)
725 UINT8 ElementID = IE_MEASUREMENT_REPORT;
727 Len = sizeof(MEASURE_REPORT_INFO) + ReportLnfoLen;
729 MakeOutgoingFrame(pFrameBuf, &TempLen,
732 Len, pMeasureReportIE,
735 *pFrameLen = *pFrameLen + TempLen;
737 if ((ReportLnfoLen > 0) && (pReportInfo != NULL))
739 MakeOutgoingFrame(pFrameBuf + *pFrameLen, &TempLen,
740 ReportLnfoLen, pReportInfo,
743 *pFrameLen = *pFrameLen + TempLen;
749 ==========================================================================
751 Prepare Measurement request action frame and enqueue it into
752 management queue waiting for transmition.
755 1. the destination mac address of the frame.
758 ==========================================================================
760 VOID EnqueueMeasurementReq(
761 IN PRTMP_ADAPTER pAd,
763 IN UINT8 MeasureToken,
764 IN UINT8 MeasureReqMode,
765 IN UINT8 MeasureReqType,
767 IN UINT16 MeasureDuration)
769 PUCHAR pOutBuffer = NULL;
772 HEADER_802_11 ActHdr;
773 MEASURE_REQ_INFO MeasureReqIE;
774 UINT8 RmReqDailogToken = RandomByte(pAd);
775 UINT64 MeasureStartTime = GetCurrentTimeStamp(pAd);
777 // build action frame header.
778 MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
779 pAd->CurrentAddress);
781 NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory
782 if(NStatus != NDIS_STATUS_SUCCESS)
784 DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __func__));
787 NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11));
788 FrameLen = sizeof(HEADER_802_11);
790 InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_MRQ);
793 InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, MeasureToken);
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);
805 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
806 MlmeFreeMemory(pAd, pOutBuffer);
812 ==========================================================================
814 Prepare Measurement report action frame and enqueue it into
815 management queue waiting for transmition.
818 1. the destination mac address of the frame.
821 ==========================================================================
823 VOID EnqueueMeasurementRep(
824 IN PRTMP_ADAPTER pAd,
826 IN UINT8 DialogToken,
827 IN UINT8 MeasureToken,
828 IN UINT8 MeasureReqMode,
829 IN UINT8 MeasureReqType,
830 IN UINT8 ReportInfoLen,
831 IN PUINT8 pReportInfo)
833 PUCHAR pOutBuffer = NULL;
836 HEADER_802_11 ActHdr;
837 MEASURE_REPORT_INFO MeasureRepIE;
839 // build action frame header.
840 MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
841 pAd->CurrentAddress);
843 NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory
844 if(NStatus != NDIS_STATUS_SUCCESS)
846 DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __func__));
849 NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11));
850 FrameLen = sizeof(HEADER_802_11);
852 InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_MRP);
855 InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken);
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);
864 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
865 MlmeFreeMemory(pAd, pOutBuffer);
871 ==========================================================================
873 Prepare TPC Request action frame and enqueue it into
874 management queue waiting for transmition.
877 1. the destination mac address of the frame.
880 ==========================================================================
883 IN PRTMP_ADAPTER pAd,
885 IN UCHAR DialogToken)
887 PUCHAR pOutBuffer = NULL;
891 HEADER_802_11 ActHdr;
893 // build action frame header.
894 MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
895 pAd->CurrentAddress);
897 NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory
898 if(NStatus != NDIS_STATUS_SUCCESS)
900 DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __func__));
903 NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11));
904 FrameLen = sizeof(HEADER_802_11);
906 InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_TPCRQ);
909 InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken);
911 // Insert TPC Request IE.
912 InsertTpcReqIE(pAd, (pOutBuffer + FrameLen), &FrameLen);
914 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
915 MlmeFreeMemory(pAd, pOutBuffer);
921 ==========================================================================
923 Prepare TPC Report action frame and enqueue it into
924 management queue waiting for transmition.
927 1. the destination mac address of the frame.
930 ==========================================================================
933 IN PRTMP_ADAPTER pAd,
935 IN UINT8 DialogToken,
939 PUCHAR pOutBuffer = NULL;
943 HEADER_802_11 ActHdr;
945 // build action frame header.
946 MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
947 pAd->CurrentAddress);
949 NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory
950 if(NStatus != NDIS_STATUS_SUCCESS)
952 DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __func__));
955 NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11));
956 FrameLen = sizeof(HEADER_802_11);
958 InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_TPCRP);
961 InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken);
963 // Insert TPC Request IE.
964 InsertTpcReportIE(pAd, (pOutBuffer + FrameLen), &FrameLen, TxPwr, LinkMargin);
966 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
967 MlmeFreeMemory(pAd, pOutBuffer);
973 ==========================================================================
975 Prepare Channel Switch Announcement action frame and enqueue it into
976 management queue waiting for transmition.
979 1. the destination mac address of the frame.
980 2. Channel switch announcement mode.
981 2. a New selected channel.
984 ==========================================================================
987 IN PRTMP_ADAPTER pAd,
992 PUCHAR pOutBuffer = NULL;
996 HEADER_802_11 ActHdr;
998 // build action frame header.
999 MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
1000 pAd->CurrentAddress);
1002 NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory
1003 if(NStatus != NDIS_STATUS_SUCCESS)
1005 DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __func__));
1008 NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11));
1009 FrameLen = sizeof(HEADER_802_11);
1011 InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_CHANNEL_SWITCH);
1013 InsertChSwAnnIE(pAd, (pOutBuffer + FrameLen), &FrameLen, ChSwMode, NewCh, 0);
1015 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1016 MlmeFreeMemory(pAd, pOutBuffer);
1021 static BOOLEAN DfsRequirementCheck(
1022 IN PRTMP_ADAPTER pAd,
1025 BOOLEAN Result = FALSE;
1030 // check DFS procedure is running.
1031 // make sure DFS procedure won't start twice.
1032 if (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)
1038 // check the new channel carried from Channel Switch Announcemnet is valid.
1039 for (i=0; i<pAd->ChannelListNum; i++)
1041 if ((Channel == pAd->ChannelList[i].Channel)
1042 &&(pAd->ChannelList[i].RemainingTimeForUse == 0))
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
1055 VOID NotifyChSwAnnToPeerAPs(
1056 IN PRTMP_ADAPTER pAd,
1063 if (!((pRA[0] & 0xff) == 0xff)) // is pRA a broadcase address.
1066 // info neighbor APs that Radar signal found throgh WDS link.
1067 for (i = 0; i < MAX_WDS_ENTRY; i++)
1069 if (ValidWdsEntry(pAd, i))
1071 PUCHAR pDA = pAd->WdsTab.WdsEntry[i].PeerWdsAddr;
1073 // DA equal to SA. have no necessary orignal AP which found Radar signal.
1074 if (MAC_ADDR_EQUAL(pTA, pDA))
1077 // send Channel Switch Action frame to info Neighbro APs.
1078 EnqueueChSwAnn(pAd, pDA, ChSwMode, Channel);
1082 #endif // WDS_SUPPORT //
1085 static VOID StartDFSProcedure(
1086 IN PRTMP_ADAPTER pAd,
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;
1100 ==========================================================================
1102 Channel Switch Announcement action frame sanity check.
1105 1. MLME message containing the received frame
1107 3. Channel switch announcement infomation buffer.
1111 ==========================================================================
1115 Channel Switch Announcement IE.
1116 +----+-----+-----------+------------+-----------+
1117 | ID | Len |Ch Sw Mode | New Ch Num | Ch Sw Cnt |
1118 +----+-----+-----------+------------+-----------+
1121 static BOOLEAN PeerChSwAnnSanity(
1122 IN PRTMP_ADAPTER pAd,
1125 OUT PCH_SW_ANN_INFO pChSwAnnInfo)
1127 PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
1128 PUCHAR pFramePtr = Fr->Octet;
1129 BOOLEAN result = FALSE;
1130 PEID_STRUCT eid_ptr;
1132 // skip 802.11 header.
1133 MsgLen -= sizeof(HEADER_802_11);
1135 // skip category and action code.
1139 if (pChSwAnnInfo == NULL)
1142 eid_ptr = (PEID_STRUCT)pFramePtr;
1143 while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
1145 switch(eid_ptr->Eid)
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);
1158 eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
1165 ==========================================================================
1167 Measurement request action frame sanity check.
1170 1. MLME message containing the received frame
1172 3. Measurement request infomation buffer.
1175 ==========================================================================
1177 static BOOLEAN PeerMeasureReqSanity(
1178 IN PRTMP_ADAPTER pAd,
1181 OUT PUINT8 pDialogToken,
1182 OUT PMEASURE_REQ_INFO pMeasureReqInfo)
1184 PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
1185 PUCHAR pFramePtr = Fr->Octet;
1186 BOOLEAN result = FALSE;
1187 PEID_STRUCT eid_ptr;
1189 UINT64 MeasureStartTime;
1190 UINT16 MeasureDuration;
1192 // skip 802.11 header.
1193 MsgLen -= sizeof(HEADER_802_11);
1195 // skip category and action code.
1199 if (pMeasureReqInfo == NULL)
1202 NdisMoveMemory(pDialogToken, pFramePtr, 1);
1206 eid_ptr = (PEID_STRUCT)pFramePtr;
1207 while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
1209 switch(eid_ptr->Eid)
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);
1228 eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
1235 ==========================================================================
1237 Measurement report action frame sanity check.
1240 1. MLME message containing the received frame
1242 3. Measurement report infomation buffer.
1243 4. basic report infomation buffer.
1246 ==========================================================================
1250 Measurement Report IE.
1251 +----+-----+-------+-------------+--------------+----------------+
1252 | ID | Len | Token | Report Mode | Measure Type | Measure Report |
1253 +----+-----+-------+-------------+--------------+----------------+
1257 +--------+------------+----------+-----+
1258 | Ch Num | Start Time | Duration | Map |
1259 +--------+------------+----------+-----+
1262 Map Field Bit Format.
1263 +-----+---------------+---------------------+-------+------------+----------+
1264 | Bss | OFDM Preamble | Unidentified signal | Radar | Unmeasured | Reserved |
1265 +-----+---------------+---------------------+-------+------------+----------+
1268 static BOOLEAN PeerMeasureReportSanity(
1269 IN PRTMP_ADAPTER pAd,
1272 OUT PUINT8 pDialogToken,
1273 OUT PMEASURE_REPORT_INFO pMeasureReportInfo,
1274 OUT PUINT8 pReportBuf)
1276 PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
1277 PUCHAR pFramePtr = Fr->Octet;
1278 BOOLEAN result = FALSE;
1279 PEID_STRUCT eid_ptr;
1282 // skip 802.11 header.
1283 MsgLen -= sizeof(HEADER_802_11);
1285 // skip category and action code.
1289 if (pMeasureReportInfo == NULL)
1292 NdisMoveMemory(pDialogToken, pFramePtr, 1);
1296 eid_ptr = (PEID_STRUCT)pFramePtr;
1297 while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
1299 switch(eid_ptr->Eid)
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)
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);
1315 else if (pMeasureReportInfo->ReportType == RM_CCA)
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);
1325 else if (pMeasureReportInfo->ReportType == RM_RPI_HISTOGRAM)
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);
1340 eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
1347 ==========================================================================
1349 TPC Request action frame sanity check.
1352 1. MLME message containing the received frame
1357 ==========================================================================
1359 static BOOLEAN PeerTpcReqSanity(
1360 IN PRTMP_ADAPTER pAd,
1363 OUT PUINT8 pDialogToken)
1365 PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
1366 PUCHAR pFramePtr = Fr->Octet;
1367 BOOLEAN result = FALSE;
1368 PEID_STRUCT eid_ptr;
1370 MsgLen -= sizeof(HEADER_802_11);
1372 // skip category and action code.
1376 if (pDialogToken == NULL)
1379 NdisMoveMemory(pDialogToken, pFramePtr, 1);
1383 eid_ptr = (PEID_STRUCT)pFramePtr;
1384 while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
1386 switch(eid_ptr->Eid)
1388 case IE_TPC_REQUEST:
1395 eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
1402 ==========================================================================
1404 TPC Report action frame sanity check.
1407 1. MLME message containing the received frame
1413 ==========================================================================
1415 static BOOLEAN PeerTpcRepSanity(
1416 IN PRTMP_ADAPTER pAd,
1419 OUT PUINT8 pDialogToken,
1420 OUT PTPC_REPORT_INFO pTpcRepInfo)
1422 PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
1423 PUCHAR pFramePtr = Fr->Octet;
1424 BOOLEAN result = FALSE;
1425 PEID_STRUCT eid_ptr;
1427 MsgLen -= sizeof(HEADER_802_11);
1429 // skip category and action code.
1433 if (pDialogToken == NULL)
1436 NdisMoveMemory(pDialogToken, pFramePtr, 1);
1440 eid_ptr = (PEID_STRUCT)pFramePtr;
1441 while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
1443 switch(eid_ptr->Eid)
1446 NdisMoveMemory(&pTpcRepInfo->TxPwr, eid_ptr->Octet, 1);
1447 NdisMoveMemory(&pTpcRepInfo->LinkMargin, eid_ptr->Octet + 1, 1);
1454 eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
1461 ==========================================================================
1463 Channel Switch Announcement action frame handler.
1466 Elme - MLME message containing the received frame
1469 ==========================================================================
1471 static VOID PeerChSwAnnAction(
1472 IN PRTMP_ADAPTER pAd,
1473 IN MLME_QUEUE_ELEM *Elem)
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;
1480 #endif // CONFIG_STA_SUPPORT //
1482 NdisZeroMemory(&ChSwAnnInfo, sizeof(CH_SW_ANN_INFO));
1483 if (! PeerChSwAnnSanity(pAd, Elem->Msg, Elem->MsgLen, &ChSwAnnInfo))
1485 DBGPRINT(RT_DEBUG_TRACE, ("Invalid Channel Switch Action Frame.\n"));
1490 #ifdef CONFIG_STA_SUPPORT
1491 if (pAd->OpMode == OPMODE_STA)
1493 Bssidx = BssTableSearch(&pAd->ScanTab, pFr->Hdr.Addr3, pAd->CommonCfg.Channel);
1494 if (Bssidx == BSS_NOT_FOUND)
1496 DBGPRINT(RT_DEBUG_TRACE, ("PeerChSwAnnAction - Bssidx is not found\n"));
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);
1503 Channel = pAd->CommonCfg.Channel;
1504 NewChannel = ChSwAnnInfo.Channel;
1506 if ((pAd->CommonCfg.bIEEE80211H == 1) && (NewChannel != 0) && (Channel != NewChannel))
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
1517 // channel sanity check
1518 for (index = 0 ; index < pAd->ChannelListNum; index++)
1520 if (pAd->ChannelList[index].Channel == NewChannel)
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));
1531 if (index >= pAd->ChannelListNum)
1533 DBGPRINT_ERR(("&&&&&&&&&&&&&&&&&&&&&&&&&&PeerChSwAnnAction(can not find New Channel=%d in ChannelList[%d]\n", pAd->CommonCfg.Channel, pAd->ChannelListNum));
1537 #endif // CONFIG_STA_SUPPORT //
1544 ==========================================================================
1546 Measurement Request action frame handler.
1549 Elme - MLME message containing the received frame
1552 ==========================================================================
1554 static VOID PeerMeasureReqAction(
1555 IN PRTMP_ADAPTER pAd,
1556 IN MLME_QUEUE_ELEM *Elem)
1558 PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg;
1560 MEASURE_REQ_INFO MeasureReqInfo;
1561 MEASURE_REPORT_MODE ReportMode;
1563 if(PeerMeasureReqSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &MeasureReqInfo))
1565 ReportMode.word = 0;
1566 ReportMode.field.Incapable = 1;
1567 EnqueueMeasurementRep(pAd, pFr->Hdr.Addr2, DialogToken, MeasureReqInfo.Token, ReportMode.word, MeasureReqInfo.ReqType, 0, NULL);
1574 ==========================================================================
1576 Measurement Report action frame handler.
1579 Elme - MLME message containing the received frame
1582 ==========================================================================
1584 static VOID PeerMeasureReportAction(
1585 IN PRTMP_ADAPTER pAd,
1586 IN MLME_QUEUE_ELEM *Elem)
1588 MEASURE_REPORT_INFO MeasureReportInfo;
1589 PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg;
1591 PUINT8 pMeasureReportInfo;
1593 // if (pAd->CommonCfg.bIEEE80211H != TRUE)
1596 if ((pMeasureReportInfo = kmalloc(sizeof(MEASURE_RPI_REPORT), GFP_ATOMIC)) == NULL)
1598 DBGPRINT(RT_DEBUG_ERROR, ("%s unable to alloc memory for measure report buffer (size=%d).\n", __func__, sizeof(MEASURE_RPI_REPORT)));
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))
1607 PMEASURE_REQ_ENTRY pEntry = NULL;
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))
1616 MeasureReqDelete(pAd, pEntry->DialogToken);
1618 if (MeasureReportInfo.ReportType == RM_BASIC)
1620 PMEASURE_BASIC_REPORT pBasicReport = (PMEASURE_BASIC_REPORT)pMeasureReportInfo;
1621 if ((pBasicReport->Map.field.Radar)
1622 && (DfsRequirementCheck(pAd, pBasicReport->ChNum) == TRUE))
1624 NotifyChSwAnnToPeerAPs(pAd, pFr->Hdr.Addr1, pFr->Hdr.Addr2, 1, pBasicReport->ChNum);
1625 StartDFSProcedure(pAd, pBasicReport->ChNum, 1);
1631 DBGPRINT(RT_DEBUG_TRACE, ("Invalid Measurement Report Frame.\n"));
1633 kfree(pMeasureReportInfo);
1639 ==========================================================================
1641 TPC Request action frame handler.
1644 Elme - MLME message containing the received frame
1647 ==========================================================================
1649 static VOID PeerTpcReqAction(
1650 IN PRTMP_ADAPTER pAd,
1651 IN MLME_QUEUE_ELEM *Elem)
1653 PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg;
1654 PUCHAR pFramePtr = pFr->Octet;
1656 UINT8 TxPwr = GetCurTxPwr(pAd, Elem->Wcid);
1657 UINT8 LinkMargin = 0;
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
1664 RealRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0),
1665 ConvertToRssi(pAd, Elem->Rssi1, RSSI_1),
1666 ConvertToRssi(pAd, Elem->Rssi2, RSSI_2));
1668 // skip Category and action code.
1672 NdisMoveMemory(&DialogToken, pFramePtr, 1);
1674 LinkMargin = (RealRssi / MIN_RCV_PWR);
1675 if (PeerTpcReqSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken))
1676 EnqueueTPCRep(pAd, pFr->Hdr.Addr2, DialogToken, TxPwr, LinkMargin);
1682 ==========================================================================
1684 TPC Report action frame handler.
1687 Elme - MLME message containing the received frame
1690 ==========================================================================
1692 static VOID PeerTpcRepAction(
1693 IN PRTMP_ADAPTER pAd,
1694 IN MLME_QUEUE_ELEM *Elem)
1697 TPC_REPORT_INFO TpcRepInfo;
1698 PTPC_REQ_ENTRY pEntry = NULL;
1700 NdisZeroMemory(&TpcRepInfo, sizeof(TPC_REPORT_INFO));
1701 if (PeerTpcRepSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &TpcRepInfo))
1703 if ((pEntry = TpcReqLookUp(pAd, DialogToken)) != NULL)
1705 TpcReqDelete(pAd, pEntry->DialogToken);
1706 DBGPRINT(RT_DEBUG_TRACE, ("%s: DialogToken=%x, TxPwr=%d, LinkMargin=%d\n",
1707 __func__, DialogToken, TpcRepInfo.TxPwr, TpcRepInfo.LinkMargin));
1715 ==========================================================================
1717 Spectrun action frames Handler such as channel switch annoucement,
1718 measurement report, measurement request actions frames.
1721 Elme - MLME message containing the received frame
1724 ==========================================================================
1726 VOID PeerSpectrumAction(
1727 IN PRTMP_ADAPTER pAd,
1728 IN MLME_QUEUE_ELEM *Elem)
1731 UCHAR Action = Elem->Msg[LENGTH_802_11+1];
1733 if (pAd->CommonCfg.bIEEE80211H != TRUE)
1739 // current rt2860 unable do such measure specified in Measurement Request.
1740 // reject all measurement request.
1741 PeerMeasureReqAction(pAd, Elem);
1745 PeerMeasureReportAction(pAd, Elem);
1749 PeerTpcReqAction(pAd, Elem);
1753 PeerTpcRepAction(pAd, Elem);
1756 case SPEC_CHANNEL_SWITCH:
1758 #ifdef DOT11N_DRAFT3
1759 SEC_CHA_OFFSET_IE Secondary;
1760 CHA_SWITCH_ANNOUNCE_IE ChannelSwitch;
1762 // 802.11h only has Channel Switch Announcement IE.
1763 RTMPMoveMemory(&ChannelSwitch, &Elem->Msg[LENGTH_802_11+4], sizeof (CHA_SWITCH_ANNOUNCE_IE));
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)))
1768 RTMPMoveMemory(&Secondary, &Elem->Msg[LENGTH_802_11+9], sizeof (SEC_CHA_OFFSET_IE));
1772 Secondary.SecondaryChannelOffset = 0;
1775 if ((Elem->Msg[LENGTH_802_11+2] == IE_CHANNEL_SWITCH_ANNOUNCEMENT) && (Elem->Msg[LENGTH_802_11+3] == 3))
1777 ChannelSwitchAction(pAd, Elem->Wcid, ChannelSwitch.NewChannel, Secondary.SecondaryChannelOffset);
1779 #endif // DOT11N_DRAFT3 //
1781 PeerChSwAnnAction(pAd, Elem);
1789 ==========================================================================
1795 ==========================================================================
1797 INT Set_MeasureReq_Proc(
1798 IN PRTMP_ADAPTER pAd,
1805 MEASURE_REQ_MODE MeasureReqMode;
1806 UINT8 MeasureReqToken = RandomByte(pAd);
1807 UINT8 MeasureReqType = RM_BASIC;
1808 UINT8 MeasureCh = 1;
1811 while ((thisChar = strsep((char **)&arg, "-")) != NULL)
1816 Aid = simple_strtol(thisChar, 0, 16);
1819 case 2: // Measurement Request Type.
1820 MeasureReqType = simple_strtol(thisChar, 0, 16);
1821 if (MeasureReqType > 3)
1823 DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow MeasureReqType(%d)\n", __func__, MeasureReqType));
1828 case 3: // Measurement channel.
1829 MeasureCh = simple_strtol(thisChar, 0, 16);
1835 DBGPRINT(RT_DEBUG_TRACE, ("%s::Aid = %d, MeasureReqType=%d MeasureCh=%d\n", __func__, Aid, MeasureReqType, MeasureCh));
1836 if (!VALID_WCID(Aid))
1838 DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow sta of Aid(%d)\n", __func__, Aid));
1842 MeasureReqMode.word = 0;
1843 MeasureReqMode.field.Enable = 1;
1845 MeasureReqInsert(pAd, MeasureReqToken);
1847 EnqueueMeasurementReq(pAd, pAd->MacTab.Content[Aid].Addr,
1848 MeasureReqToken, MeasureReqMode.word, MeasureReqType, MeasureCh, 2000);
1853 INT Set_TpcReq_Proc(
1854 IN PRTMP_ADAPTER pAd,
1859 UINT8 TpcReqToken = RandomByte(pAd);
1861 Aid = simple_strtol(arg, 0, 16);
1863 DBGPRINT(RT_DEBUG_TRACE, ("%s::Aid = %d\n", __func__, Aid));
1864 if (!VALID_WCID(Aid))
1866 DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow sta of Aid(%d)\n", __func__, Aid));
1870 TpcReqInsert(pAd, TpcReqToken);
1872 EnqueueTPCReq(pAd, pAd->MacTab.Content[Aid].Addr, TpcReqToken);