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,
1064 if (!((pRA[0] & 0xff) == 0xff)) // is pRA a broadcase address.
1067 // info neighbor APs that Radar signal found throgh WDS link.
1068 for (i = 0; i < MAX_WDS_ENTRY; i++)
1070 if (ValidWdsEntry(pAd, i))
1072 PUCHAR pDA = pAd->WdsTab.WdsEntry[i].PeerWdsAddr;
1074 // DA equal to SA. have no necessary orignal AP which found Radar signal.
1075 if (MAC_ADDR_EQUAL(pTA, pDA))
1078 // send Channel Switch Action frame to info Neighbro APs.
1079 EnqueueChSwAnn(pAd, pDA, ChSwMode, Channel);
1083 #endif // WDS_SUPPORT //
1086 static VOID StartDFSProcedure(
1087 IN PRTMP_ADAPTER pAd,
1091 // start DFS procedure
1092 pAd->CommonCfg.Channel = Channel;
1093 #ifdef DOT11_N_SUPPORT
1094 N_ChannelCheck(pAd);
1095 #endif // DOT11_N_SUPPORT //
1096 pAd->CommonCfg.RadarDetect.RDMode = RD_SWITCHING_MODE;
1097 pAd->CommonCfg.RadarDetect.CSCount = 0;
1101 ==========================================================================
1103 Channel Switch Announcement action frame sanity check.
1106 1. MLME message containing the received frame
1108 3. Channel switch announcement infomation buffer.
1112 ==========================================================================
1116 Channel Switch Announcement IE.
1117 +----+-----+-----------+------------+-----------+
1118 | ID | Len |Ch Sw Mode | New Ch Num | Ch Sw Cnt |
1119 +----+-----+-----------+------------+-----------+
1122 static BOOLEAN PeerChSwAnnSanity(
1123 IN PRTMP_ADAPTER pAd,
1126 OUT PCH_SW_ANN_INFO pChSwAnnInfo)
1128 PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
1129 PUCHAR pFramePtr = Fr->Octet;
1130 BOOLEAN result = FALSE;
1131 PEID_STRUCT eid_ptr;
1133 // skip 802.11 header.
1134 MsgLen -= sizeof(HEADER_802_11);
1136 // skip category and action code.
1140 if (pChSwAnnInfo == NULL)
1143 eid_ptr = (PEID_STRUCT)pFramePtr;
1144 while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
1146 switch(eid_ptr->Eid)
1148 case IE_CHANNEL_SWITCH_ANNOUNCEMENT:
1149 NdisMoveMemory(&pChSwAnnInfo->ChSwMode, eid_ptr->Octet, 1);
1150 NdisMoveMemory(&pChSwAnnInfo->Channel, eid_ptr->Octet + 1, 1);
1151 NdisMoveMemory(&pChSwAnnInfo->ChSwCnt, eid_ptr->Octet + 2, 1);
1159 eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
1166 ==========================================================================
1168 Measurement request action frame sanity check.
1171 1. MLME message containing the received frame
1173 3. Measurement request infomation buffer.
1176 ==========================================================================
1178 static BOOLEAN PeerMeasureReqSanity(
1179 IN PRTMP_ADAPTER pAd,
1182 OUT PUINT8 pDialogToken,
1183 OUT PMEASURE_REQ_INFO pMeasureReqInfo)
1185 PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
1186 PUCHAR pFramePtr = Fr->Octet;
1187 BOOLEAN result = FALSE;
1188 PEID_STRUCT eid_ptr;
1190 UINT64 MeasureStartTime;
1191 UINT16 MeasureDuration;
1193 // skip 802.11 header.
1194 MsgLen -= sizeof(HEADER_802_11);
1196 // skip category and action code.
1200 if (pMeasureReqInfo == NULL)
1203 NdisMoveMemory(pDialogToken, pFramePtr, 1);
1207 eid_ptr = (PEID_STRUCT)pFramePtr;
1208 while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
1210 switch(eid_ptr->Eid)
1212 case IE_MEASUREMENT_REQUEST:
1213 NdisMoveMemory(&pMeasureReqInfo->Token, eid_ptr->Octet, 1);
1214 NdisMoveMemory(&pMeasureReqInfo->ReqMode.word, eid_ptr->Octet + 1, 1);
1215 NdisMoveMemory(&pMeasureReqInfo->ReqType, eid_ptr->Octet + 2, 1);
1216 ptr = eid_ptr->Octet + 3;
1217 NdisMoveMemory(&pMeasureReqInfo->MeasureReq.ChNum, ptr, 1);
1218 NdisMoveMemory(&MeasureStartTime, ptr + 1, 8);
1219 pMeasureReqInfo->MeasureReq.MeasureStartTime = SWAP64(MeasureStartTime);
1220 NdisMoveMemory(&MeasureDuration, ptr + 9, 2);
1221 pMeasureReqInfo->MeasureReq.MeasureDuration = SWAP16(MeasureDuration);
1229 eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
1236 ==========================================================================
1238 Measurement report action frame sanity check.
1241 1. MLME message containing the received frame
1243 3. Measurement report infomation buffer.
1244 4. basic report infomation buffer.
1247 ==========================================================================
1251 Measurement Report IE.
1252 +----+-----+-------+-------------+--------------+----------------+
1253 | ID | Len | Token | Report Mode | Measure Type | Measure Report |
1254 +----+-----+-------+-------------+--------------+----------------+
1258 +--------+------------+----------+-----+
1259 | Ch Num | Start Time | Duration | Map |
1260 +--------+------------+----------+-----+
1263 Map Field Bit Format.
1264 +-----+---------------+---------------------+-------+------------+----------+
1265 | Bss | OFDM Preamble | Unidentified signal | Radar | Unmeasured | Reserved |
1266 +-----+---------------+---------------------+-------+------------+----------+
1269 static BOOLEAN PeerMeasureReportSanity(
1270 IN PRTMP_ADAPTER pAd,
1273 OUT PUINT8 pDialogToken,
1274 OUT PMEASURE_REPORT_INFO pMeasureReportInfo,
1275 OUT PUINT8 pReportBuf)
1277 PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
1278 PUCHAR pFramePtr = Fr->Octet;
1279 BOOLEAN result = FALSE;
1280 PEID_STRUCT eid_ptr;
1283 // skip 802.11 header.
1284 MsgLen -= sizeof(HEADER_802_11);
1286 // skip category and action code.
1290 if (pMeasureReportInfo == NULL)
1293 NdisMoveMemory(pDialogToken, pFramePtr, 1);
1297 eid_ptr = (PEID_STRUCT)pFramePtr;
1298 while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
1300 switch(eid_ptr->Eid)
1302 case IE_MEASUREMENT_REPORT:
1303 NdisMoveMemory(&pMeasureReportInfo->Token, eid_ptr->Octet, 1);
1304 NdisMoveMemory(&pMeasureReportInfo->ReportMode, eid_ptr->Octet + 1, 1);
1305 NdisMoveMemory(&pMeasureReportInfo->ReportType, eid_ptr->Octet + 2, 1);
1306 if (pMeasureReportInfo->ReportType == RM_BASIC)
1308 PMEASURE_BASIC_REPORT pReport = (PMEASURE_BASIC_REPORT)pReportBuf;
1309 ptr = eid_ptr->Octet + 3;
1310 NdisMoveMemory(&pReport->ChNum, ptr, 1);
1311 NdisMoveMemory(&pReport->MeasureStartTime, ptr + 1, 8);
1312 NdisMoveMemory(&pReport->MeasureDuration, ptr + 9, 2);
1313 NdisMoveMemory(&pReport->Map, ptr + 11, 1);
1316 else if (pMeasureReportInfo->ReportType == RM_CCA)
1318 PMEASURE_CCA_REPORT pReport = (PMEASURE_CCA_REPORT)pReportBuf;
1319 ptr = eid_ptr->Octet + 3;
1320 NdisMoveMemory(&pReport->ChNum, ptr, 1);
1321 NdisMoveMemory(&pReport->MeasureStartTime, ptr + 1, 8);
1322 NdisMoveMemory(&pReport->MeasureDuration, ptr + 9, 2);
1323 NdisMoveMemory(&pReport->CCA_Busy_Fraction, ptr + 11, 1);
1326 else if (pMeasureReportInfo->ReportType == RM_RPI_HISTOGRAM)
1328 PMEASURE_RPI_REPORT pReport = (PMEASURE_RPI_REPORT)pReportBuf;
1329 ptr = eid_ptr->Octet + 3;
1330 NdisMoveMemory(&pReport->ChNum, ptr, 1);
1331 NdisMoveMemory(&pReport->MeasureStartTime, ptr + 1, 8);
1332 NdisMoveMemory(&pReport->MeasureDuration, ptr + 9, 2);
1333 NdisMoveMemory(&pReport->RPI_Density, ptr + 11, 8);
1341 eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
1348 ==========================================================================
1350 TPC Request action frame sanity check.
1353 1. MLME message containing the received frame
1358 ==========================================================================
1360 static BOOLEAN PeerTpcReqSanity(
1361 IN PRTMP_ADAPTER pAd,
1364 OUT PUINT8 pDialogToken)
1366 PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
1367 PUCHAR pFramePtr = Fr->Octet;
1368 BOOLEAN result = FALSE;
1369 PEID_STRUCT eid_ptr;
1371 MsgLen -= sizeof(HEADER_802_11);
1373 // skip category and action code.
1377 if (pDialogToken == NULL)
1380 NdisMoveMemory(pDialogToken, pFramePtr, 1);
1384 eid_ptr = (PEID_STRUCT)pFramePtr;
1385 while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
1387 switch(eid_ptr->Eid)
1389 case IE_TPC_REQUEST:
1396 eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
1403 ==========================================================================
1405 TPC Report action frame sanity check.
1408 1. MLME message containing the received frame
1414 ==========================================================================
1416 static BOOLEAN PeerTpcRepSanity(
1417 IN PRTMP_ADAPTER pAd,
1420 OUT PUINT8 pDialogToken,
1421 OUT PTPC_REPORT_INFO pTpcRepInfo)
1423 PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
1424 PUCHAR pFramePtr = Fr->Octet;
1425 BOOLEAN result = FALSE;
1426 PEID_STRUCT eid_ptr;
1428 MsgLen -= sizeof(HEADER_802_11);
1430 // skip category and action code.
1434 if (pDialogToken == NULL)
1437 NdisMoveMemory(pDialogToken, pFramePtr, 1);
1441 eid_ptr = (PEID_STRUCT)pFramePtr;
1442 while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
1444 switch(eid_ptr->Eid)
1447 NdisMoveMemory(&pTpcRepInfo->TxPwr, eid_ptr->Octet, 1);
1448 NdisMoveMemory(&pTpcRepInfo->LinkMargin, eid_ptr->Octet + 1, 1);
1455 eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
1462 ==========================================================================
1464 Channel Switch Announcement action frame handler.
1467 Elme - MLME message containing the received frame
1470 ==========================================================================
1472 static VOID PeerChSwAnnAction(
1473 IN PRTMP_ADAPTER pAd,
1474 IN MLME_QUEUE_ELEM *Elem)
1476 CH_SW_ANN_INFO ChSwAnnInfo;
1477 PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg;
1478 #ifdef CONFIG_STA_SUPPORT
1479 UCHAR index = 0, Channel = 0, NewChannel = 0;
1481 #endif // CONFIG_STA_SUPPORT //
1483 NdisZeroMemory(&ChSwAnnInfo, sizeof(CH_SW_ANN_INFO));
1484 if (! PeerChSwAnnSanity(pAd, Elem->Msg, Elem->MsgLen, &ChSwAnnInfo))
1486 DBGPRINT(RT_DEBUG_TRACE, ("Invalid Channel Switch Action Frame.\n"));
1491 #ifdef CONFIG_STA_SUPPORT
1492 if (pAd->OpMode == OPMODE_STA)
1494 Bssidx = BssTableSearch(&pAd->ScanTab, pFr->Hdr.Addr3, pAd->CommonCfg.Channel);
1495 if (Bssidx == BSS_NOT_FOUND)
1497 DBGPRINT(RT_DEBUG_TRACE, ("PeerChSwAnnAction - Bssidx is not found\n"));
1501 DBGPRINT(RT_DEBUG_TRACE, ("\n****Bssidx is %d, Channel = %d\n", index, pAd->ScanTab.BssEntry[Bssidx].Channel));
1502 hex_dump("SSID",pAd->ScanTab.BssEntry[Bssidx].Bssid ,6);
1504 Channel = pAd->CommonCfg.Channel;
1505 NewChannel = ChSwAnnInfo.Channel;
1507 if ((pAd->CommonCfg.bIEEE80211H == 1) && (NewChannel != 0) && (Channel != NewChannel))
1509 // Switching to channel 1 can prevent from rescanning the current channel immediately (by auto reconnection).
1510 // In addition, clear the MLME queue and the scan table to discard the RX packets and previous scanning results.
1511 AsicSwitchChannel(pAd, 1, FALSE);
1512 AsicLockChannel(pAd, 1);
1513 LinkDown(pAd, FALSE);
1514 MlmeQueueInit(&pAd->Mlme.Queue);
1515 BssTableInit(&pAd->ScanTab);
1516 RTMPusecDelay(1000000); // use delay to prevent STA do reassoc
1518 // channel sanity check
1519 for (index = 0 ; index < pAd->ChannelListNum; index++)
1521 if (pAd->ChannelList[index].Channel == NewChannel)
1523 pAd->ScanTab.BssEntry[Bssidx].Channel = NewChannel;
1524 pAd->CommonCfg.Channel = NewChannel;
1525 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
1526 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
1527 DBGPRINT(RT_DEBUG_TRACE, ("&&&&&&&&&&&&&&&&PeerChSwAnnAction - STA receive channel switch announcement IE (New Channel =%d)\n", NewChannel));
1532 if (index >= pAd->ChannelListNum)
1534 DBGPRINT_ERR(("&&&&&&&&&&&&&&&&&&&&&&&&&&PeerChSwAnnAction(can not find New Channel=%d in ChannelList[%d]\n", pAd->CommonCfg.Channel, pAd->ChannelListNum));
1538 #endif // CONFIG_STA_SUPPORT //
1545 ==========================================================================
1547 Measurement Request action frame handler.
1550 Elme - MLME message containing the received frame
1553 ==========================================================================
1555 static VOID PeerMeasureReqAction(
1556 IN PRTMP_ADAPTER pAd,
1557 IN MLME_QUEUE_ELEM *Elem)
1559 PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg;
1561 MEASURE_REQ_INFO MeasureReqInfo;
1562 MEASURE_REPORT_MODE ReportMode;
1564 if(PeerMeasureReqSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &MeasureReqInfo))
1566 ReportMode.word = 0;
1567 ReportMode.field.Incapable = 1;
1568 EnqueueMeasurementRep(pAd, pFr->Hdr.Addr2, DialogToken, MeasureReqInfo.Token, ReportMode.word, MeasureReqInfo.ReqType, 0, NULL);
1575 ==========================================================================
1577 Measurement Report action frame handler.
1580 Elme - MLME message containing the received frame
1583 ==========================================================================
1585 static VOID PeerMeasureReportAction(
1586 IN PRTMP_ADAPTER pAd,
1587 IN MLME_QUEUE_ELEM *Elem)
1589 MEASURE_REPORT_INFO MeasureReportInfo;
1590 PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg;
1592 PUINT8 pMeasureReportInfo;
1594 // if (pAd->CommonCfg.bIEEE80211H != TRUE)
1597 if ((pMeasureReportInfo = kmalloc(sizeof(MEASURE_RPI_REPORT), GFP_ATOMIC)) == NULL)
1599 DBGPRINT(RT_DEBUG_ERROR, ("%s unable to alloc memory for measure report buffer (size=%d).\n", __func__, sizeof(MEASURE_RPI_REPORT)));
1603 NdisZeroMemory(&MeasureReportInfo, sizeof(MEASURE_REPORT_INFO));
1604 NdisZeroMemory(pMeasureReportInfo, sizeof(MEASURE_RPI_REPORT));
1605 if (PeerMeasureReportSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &MeasureReportInfo, pMeasureReportInfo))
1608 PMEASURE_REQ_ENTRY pEntry = NULL;
1610 // Not a autonomous measure report.
1611 // check the dialog token field. drop it if the dialog token doesn't match.
1612 if ((DialogToken != 0)
1613 && ((pEntry = MeasureReqLookUp(pAd, DialogToken)) == NULL))
1617 MeasureReqDelete(pAd, pEntry->DialogToken);
1619 if (MeasureReportInfo.ReportType == RM_BASIC)
1621 PMEASURE_BASIC_REPORT pBasicReport = (PMEASURE_BASIC_REPORT)pMeasureReportInfo;
1622 if ((pBasicReport->Map.field.Radar)
1623 && (DfsRequirementCheck(pAd, pBasicReport->ChNum) == TRUE))
1625 NotifyChSwAnnToPeerAPs(pAd, pFr->Hdr.Addr1, pFr->Hdr.Addr2, 1, pBasicReport->ChNum);
1626 StartDFSProcedure(pAd, pBasicReport->ChNum, 1);
1632 DBGPRINT(RT_DEBUG_TRACE, ("Invalid Measurement Report Frame.\n"));
1634 kfree(pMeasureReportInfo);
1640 ==========================================================================
1642 TPC Request action frame handler.
1645 Elme - MLME message containing the received frame
1648 ==========================================================================
1650 static VOID PeerTpcReqAction(
1651 IN PRTMP_ADAPTER pAd,
1652 IN MLME_QUEUE_ELEM *Elem)
1654 PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg;
1655 PUCHAR pFramePtr = pFr->Octet;
1657 UINT8 TxPwr = GetCurTxPwr(pAd, Elem->Wcid);
1658 UINT8 LinkMargin = 0;
1661 // link margin: Ratio of the received signal power to the minimum desired by the station (STA). The
1662 // STA may incorporate rate information and channel conditions, including interference, into its computation
1665 RealRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0),
1666 ConvertToRssi(pAd, Elem->Rssi1, RSSI_1),
1667 ConvertToRssi(pAd, Elem->Rssi2, RSSI_2));
1669 // skip Category and action code.
1673 NdisMoveMemory(&DialogToken, pFramePtr, 1);
1675 LinkMargin = (RealRssi / MIN_RCV_PWR);
1676 if (PeerTpcReqSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken))
1677 EnqueueTPCRep(pAd, pFr->Hdr.Addr2, DialogToken, TxPwr, LinkMargin);
1683 ==========================================================================
1685 TPC Report action frame handler.
1688 Elme - MLME message containing the received frame
1691 ==========================================================================
1693 static VOID PeerTpcRepAction(
1694 IN PRTMP_ADAPTER pAd,
1695 IN MLME_QUEUE_ELEM *Elem)
1698 TPC_REPORT_INFO TpcRepInfo;
1699 PTPC_REQ_ENTRY pEntry = NULL;
1701 NdisZeroMemory(&TpcRepInfo, sizeof(TPC_REPORT_INFO));
1702 if (PeerTpcRepSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &TpcRepInfo))
1704 if ((pEntry = TpcReqLookUp(pAd, DialogToken)) != NULL)
1706 TpcReqDelete(pAd, pEntry->DialogToken);
1707 DBGPRINT(RT_DEBUG_TRACE, ("%s: DialogToken=%x, TxPwr=%d, LinkMargin=%d\n",
1708 __func__, DialogToken, TpcRepInfo.TxPwr, TpcRepInfo.LinkMargin));
1716 ==========================================================================
1718 Spectrun action frames Handler such as channel switch annoucement,
1719 measurement report, measurement request actions frames.
1722 Elme - MLME message containing the received frame
1725 ==========================================================================
1727 VOID PeerSpectrumAction(
1728 IN PRTMP_ADAPTER pAd,
1729 IN MLME_QUEUE_ELEM *Elem)
1732 UCHAR Action = Elem->Msg[LENGTH_802_11+1];
1734 if (pAd->CommonCfg.bIEEE80211H != TRUE)
1740 // current rt2860 unable do such measure specified in Measurement Request.
1741 // reject all measurement request.
1742 PeerMeasureReqAction(pAd, Elem);
1746 PeerMeasureReportAction(pAd, Elem);
1750 PeerTpcReqAction(pAd, Elem);
1754 PeerTpcRepAction(pAd, Elem);
1757 case SPEC_CHANNEL_SWITCH:
1759 #ifdef DOT11N_DRAFT3
1760 SEC_CHA_OFFSET_IE Secondary;
1761 CHA_SWITCH_ANNOUNCE_IE ChannelSwitch;
1763 // 802.11h only has Channel Switch Announcement IE.
1764 RTMPMoveMemory(&ChannelSwitch, &Elem->Msg[LENGTH_802_11+4], sizeof (CHA_SWITCH_ANNOUNCE_IE));
1766 // 802.11n D3.03 adds secondary channel offset element in the end.
1767 if (Elem->MsgLen == (LENGTH_802_11 + 2 + sizeof (CHA_SWITCH_ANNOUNCE_IE) + sizeof (SEC_CHA_OFFSET_IE)))
1769 RTMPMoveMemory(&Secondary, &Elem->Msg[LENGTH_802_11+9], sizeof (SEC_CHA_OFFSET_IE));
1773 Secondary.SecondaryChannelOffset = 0;
1776 if ((Elem->Msg[LENGTH_802_11+2] == IE_CHANNEL_SWITCH_ANNOUNCEMENT) && (Elem->Msg[LENGTH_802_11+3] == 3))
1778 ChannelSwitchAction(pAd, Elem->Wcid, ChannelSwitch.NewChannel, Secondary.SecondaryChannelOffset);
1780 #endif // DOT11N_DRAFT3 //
1782 PeerChSwAnnAction(pAd, Elem);
1790 ==========================================================================
1796 ==========================================================================
1798 INT Set_MeasureReq_Proc(
1799 IN PRTMP_ADAPTER pAd,
1806 MEASURE_REQ_MODE MeasureReqMode;
1807 UINT8 MeasureReqToken = RandomByte(pAd);
1808 UINT8 MeasureReqType = RM_BASIC;
1809 UINT8 MeasureCh = 1;
1812 while ((thisChar = strsep((char **)&arg, "-")) != NULL)
1817 Aid = simple_strtol(thisChar, 0, 16);
1820 case 2: // Measurement Request Type.
1821 MeasureReqType = simple_strtol(thisChar, 0, 16);
1822 if (MeasureReqType > 3)
1824 DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow MeasureReqType(%d)\n", __func__, MeasureReqType));
1829 case 3: // Measurement channel.
1830 MeasureCh = simple_strtol(thisChar, 0, 16);
1836 DBGPRINT(RT_DEBUG_TRACE, ("%s::Aid = %d, MeasureReqType=%d MeasureCh=%d\n", __func__, Aid, MeasureReqType, MeasureCh));
1837 if (!VALID_WCID(Aid))
1839 DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow sta of Aid(%d)\n", __func__, Aid));
1843 MeasureReqMode.word = 0;
1844 MeasureReqMode.field.Enable = 1;
1846 MeasureReqInsert(pAd, MeasureReqToken);
1848 EnqueueMeasurementReq(pAd, pAd->MacTab.Content[Aid].Addr,
1849 MeasureReqToken, MeasureReqMode.word, MeasureReqType, MeasureCh, 2000);
1854 INT Set_TpcReq_Proc(
1855 IN PRTMP_ADAPTER pAd,
1860 UINT8 TpcReqToken = RandomByte(pAd);
1862 Aid = simple_strtol(arg, 0, 16);
1864 DBGPRINT(RT_DEBUG_TRACE, ("%s::Aid = %d\n", __func__, Aid));
1865 if (!VALID_WCID(Aid))
1867 DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow sta of Aid(%d)\n", __func__, Aid));
1871 TpcReqInsert(pAd, TpcReqToken);
1873 EnqueueTPCReq(pAd, pAd->MacTab.Content[Aid].Addr, TpcReqToken);