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 /* The regulatory information in the USA (US) */
43 struct rt_dot11_regulatory_information USARegulatoryInfo[] = {
44 /* "regulatory class" "number of channels" "Max Tx Pwr" "channel list" */
49 {1, {4, 16, {36, 40, 44, 48}
53 {2, {4, 23, {52, 56, 60, 64}
57 {3, {4, 29, {149, 153, 157, 161}
61 {4, {11, 23, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}
65 {5, {5, 30, {149, 153, 157, 161, 165}
69 {6, {10, 14, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
73 {7, {10, 27, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
77 {8, {5, 17, {11, 13, 15, 17, 19}
81 {9, {5, 30, {11, 13, 15, 17, 19}
93 {12, {11, 30, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}
98 #define USA_REGULATORY_INFO_SIZE (sizeof(USARegulatoryInfo) / sizeof(struct rt_dot11_regulatory_information))
100 /* The regulatory information in Europe */
101 struct rt_dot11_regulatory_information EuropeRegulatoryInfo[] = {
102 /* "regulatory class" "number of channels" "Max Tx Pwr" "channel list" */
106 , /* Invalid entry */
107 {1, {4, 20, {36, 40, 44, 48}
111 {2, {4, 20, {52, 56, 60, 64}
115 {3, {11, 30, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}
119 {4, {13, 20, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}
124 #define EU_REGULATORY_INFO_SIZE (sizeof(EuropeRegulatoryInfo) / sizeof(struct rt_dot11_regulatory_information))
126 /* The regulatory information in Japan */
127 struct rt_dot11_regulatory_information JapanRegulatoryInfo[] = {
128 /* "regulatory class" "number of channels" "Max Tx Pwr" "channel list" */
132 , /* Invalid entry */
133 {1, {4, 22, {34, 38, 42, 46}
137 {2, {3, 24, {8, 12, 16}
141 {3, {3, 24, {8, 12, 16}
145 {4, {3, 24, {8, 12, 16}
149 {5, {3, 24, {8, 12, 16}
153 {6, {3, 22, {8, 12, 16}
157 {7, {4, 24, {184, 188, 192, 196}
161 {8, {4, 24, {184, 188, 192, 196}
165 {9, {4, 24, {184, 188, 192, 196}
169 {10, {4, 24, {184, 188, 192, 196}
173 {11, {4, 22, {184, 188, 192, 196}
177 {12, {4, 24, {7, 8, 9, 11}
181 {13, {4, 24, {7, 8, 9, 11}
185 {14, {4, 24, {7, 8, 9, 11}
189 {15, {4, 24, {7, 8, 9, 11}
193 {16, {6, 24, {183, 184, 185, 187, 188, 189}
197 {17, {6, 24, {183, 184, 185, 187, 188, 189}
201 {18, {6, 24, {183, 184, 185, 187, 188, 189}
205 {19, {6, 24, {183, 184, 185, 187, 188, 189}
209 {20, {6, 17, {183, 184, 185, 187, 188, 189}
213 {21, {6, 24, {6, 7, 8, 9, 10, 11}
217 {22, {6, 24, {6, 7, 8, 9, 10, 11}
221 {23, {6, 24, {6, 7, 8, 9, 10, 11}
225 {24, {6, 24, {6, 7, 8, 9, 10, 11}
229 {25, {8, 24, {182, 183, 184, 185, 186, 187, 188, 189}
233 {26, {8, 24, {182, 183, 184, 185, 186, 187, 188, 189}
237 {27, {8, 24, {182, 183, 184, 185, 186, 187, 188, 189}
241 {28, {8, 24, {182, 183, 184, 185, 186, 187, 188, 189}
245 {29, {8, 17, {182, 183, 184, 185, 186, 187, 188, 189}
249 {30, {13, 23, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}
257 {32, {4, 22, {52, 56, 60, 64}
262 #define JP_REGULATORY_INFO_SIZE (sizeof(JapanRegulatoryInfo) / sizeof(struct rt_dot11_regulatory_information))
264 char RTMP_GetTxPwr(struct rt_rtmp_adapter *pAd, IN HTTRANSMIT_SETTING HTTxMode)
280 unsigned long TxPwr[5];
282 struct tx_pwr_cfg TxPwrCfg[] = {
283 {MODE_CCK, 0, 0, 4, 0x000000f0},
284 {MODE_CCK, 1, 0, 0, 0x0000000f},
285 {MODE_CCK, 2, 0, 12, 0x0000f000},
286 {MODE_CCK, 3, 0, 8, 0x00000f00},
288 {MODE_OFDM, 0, 0, 20, 0x00f00000},
289 {MODE_OFDM, 1, 0, 16, 0x000f0000},
290 {MODE_OFDM, 2, 0, 28, 0xf0000000},
291 {MODE_OFDM, 3, 0, 24, 0x0f000000},
292 {MODE_OFDM, 4, 1, 4, 0x000000f0},
293 {MODE_OFDM, 5, 1, 0, 0x0000000f},
294 {MODE_OFDM, 6, 1, 12, 0x0000f000},
295 {MODE_OFDM, 7, 1, 8, 0x00000f00}
296 , {MODE_HTMIX, 0, 1, 20, 0x00f00000},
297 {MODE_HTMIX, 1, 1, 16, 0x000f0000},
298 {MODE_HTMIX, 2, 1, 28, 0xf0000000},
299 {MODE_HTMIX, 3, 1, 24, 0x0f000000},
300 {MODE_HTMIX, 4, 2, 4, 0x000000f0},
301 {MODE_HTMIX, 5, 2, 0, 0x0000000f},
302 {MODE_HTMIX, 6, 2, 12, 0x0000f000},
303 {MODE_HTMIX, 7, 2, 8, 0x00000f00},
304 {MODE_HTMIX, 8, 2, 20, 0x00f00000},
305 {MODE_HTMIX, 9, 2, 16, 0x000f0000},
306 {MODE_HTMIX, 10, 2, 28, 0xf0000000},
307 {MODE_HTMIX, 11, 2, 24, 0x0f000000},
308 {MODE_HTMIX, 12, 3, 4, 0x000000f0},
309 {MODE_HTMIX, 13, 3, 0, 0x0000000f},
310 {MODE_HTMIX, 14, 3, 12, 0x0000f000},
311 {MODE_HTMIX, 15, 3, 8, 0x00000f00}
313 #define MAX_TXPWR_TAB_SIZE (sizeof(TxPwrCfg) / sizeof(struct tx_pwr_cfg))
317 /* check Tx Power setting from UI. */
318 if (pAd->CommonCfg.TxPowerPercentage > 90) ;
319 else if (pAd->CommonCfg.TxPowerPercentage > 60) /* reduce Pwr for 1 dB. */
321 else if (pAd->CommonCfg.TxPowerPercentage > 30) /* reduce Pwr for 3 dB. */
323 else if (pAd->CommonCfg.TxPowerPercentage > 15) /* reduce Pwr for 6 dB. */
325 else if (pAd->CommonCfg.TxPowerPercentage > 9) /* reduce Pwr for 9 dB. */
327 else /* reduce Pwr for 12 dB. */
330 if (pAd->CommonCfg.BBPCurrentBW == BW_40) {
331 if (pAd->CommonCfg.CentralChannel > 14) {
332 TxPwr[0] = pAd->Tx40MPwrCfgABand[0];
333 TxPwr[1] = pAd->Tx40MPwrCfgABand[1];
334 TxPwr[2] = pAd->Tx40MPwrCfgABand[2];
335 TxPwr[3] = pAd->Tx40MPwrCfgABand[3];
336 TxPwr[4] = pAd->Tx40MPwrCfgABand[4];
338 TxPwr[0] = pAd->Tx40MPwrCfgGBand[0];
339 TxPwr[1] = pAd->Tx40MPwrCfgGBand[1];
340 TxPwr[2] = pAd->Tx40MPwrCfgGBand[2];
341 TxPwr[3] = pAd->Tx40MPwrCfgGBand[3];
342 TxPwr[4] = pAd->Tx40MPwrCfgGBand[4];
345 if (pAd->CommonCfg.Channel > 14) {
346 TxPwr[0] = pAd->Tx20MPwrCfgABand[0];
347 TxPwr[1] = pAd->Tx20MPwrCfgABand[1];
348 TxPwr[2] = pAd->Tx20MPwrCfgABand[2];
349 TxPwr[3] = pAd->Tx20MPwrCfgABand[3];
350 TxPwr[4] = pAd->Tx20MPwrCfgABand[4];
352 TxPwr[0] = pAd->Tx20MPwrCfgGBand[0];
353 TxPwr[1] = pAd->Tx20MPwrCfgGBand[1];
354 TxPwr[2] = pAd->Tx20MPwrCfgGBand[2];
355 TxPwr[3] = pAd->Tx20MPwrCfgGBand[3];
356 TxPwr[4] = pAd->Tx20MPwrCfgGBand[4];
360 switch (HTTxMode.field.MODE) {
364 TxPwrRef = (Value & 0x00000f00) >> 8;
369 case MODE_HTGREENFIELD:
370 if (pAd->CommonCfg.TxStream == 1) {
372 TxPwrRef = (Value & 0x00000f00) >> 8;
373 } else if (pAd->CommonCfg.TxStream == 2) {
375 TxPwrRef = (Value & 0x00000f00) >> 8;
380 PhyMode = (HTTxMode.field.MODE == MODE_HTGREENFIELD)
381 ? MODE_HTMIX : HTTxMode.field.MODE;
383 for (Idx = 0; Idx < MAX_TXPWR_TAB_SIZE; Idx++) {
384 if ((TxPwrCfg[Idx].Mode == PhyMode)
385 && (TxPwrCfg[Idx].MCS == HTTxMode.field.MCS)) {
386 Value = TxPwr[TxPwrCfg[Idx].req];
388 TxPwrRef - (char)((Value & TxPwrCfg[Idx].BitMask)
389 >> TxPwrCfg[Idx].shift);
390 CurTxPwr -= DaltaPwr;
398 void MeasureReqTabInit(struct rt_rtmp_adapter *pAd)
400 NdisAllocateSpinLock(&pAd->CommonCfg.MeasureReqTabLock);
402 pAd->CommonCfg.pMeasureReqTab =
403 kmalloc(sizeof(struct rt_measure_req_tab), GFP_ATOMIC);
404 if (pAd->CommonCfg.pMeasureReqTab)
405 NdisZeroMemory(pAd->CommonCfg.pMeasureReqTab,
406 sizeof(struct rt_measure_req_tab));
408 DBGPRINT(RT_DEBUG_ERROR,
409 ("%s Fail to alloc memory for pAd->CommonCfg.pMeasureReqTab.\n",
415 void MeasureReqTabExit(struct rt_rtmp_adapter *pAd)
417 NdisFreeSpinLock(&pAd->CommonCfg.MeasureReqTabLock);
419 kfree(pAd->CommonCfg.pMeasureReqTab);
420 pAd->CommonCfg.pMeasureReqTab = NULL;
425 struct rt_measure_req_entry *MeasureReqLookUp(struct rt_rtmp_adapter *pAd, u8 DialogToken)
428 struct rt_measure_req_tab *pTab = pAd->CommonCfg.pMeasureReqTab;
429 struct rt_measure_req_entry *pEntry = NULL;
430 struct rt_measure_req_entry *pPrevEntry = NULL;
433 DBGPRINT(RT_DEBUG_ERROR,
434 ("%s: pMeasureReqTab doesn't exist.\n", __func__));
438 RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock);
440 HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(DialogToken);
441 pEntry = pTab->Hash[HashIdx];
444 if (pEntry->DialogToken == DialogToken)
448 pEntry = pEntry->pNext;
452 RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock);
457 struct rt_measure_req_entry *MeasureReqInsert(struct rt_rtmp_adapter *pAd, u8 DialogToken)
460 unsigned long HashIdx;
461 struct rt_measure_req_tab *pTab = pAd->CommonCfg.pMeasureReqTab;
462 struct rt_measure_req_entry *pEntry = NULL, *pCurrEntry;
466 DBGPRINT(RT_DEBUG_ERROR,
467 ("%s: pMeasureReqTab doesn't exist.\n", __func__));
471 pEntry = MeasureReqLookUp(pAd, DialogToken);
472 if (pEntry == NULL) {
473 RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock);
474 for (i = 0; i < MAX_MEASURE_REQ_TAB_SIZE; i++) {
475 NdisGetSystemUpTime(&Now);
476 pEntry = &pTab->Content[i];
478 if ((pEntry->Valid == TRUE)
479 && RTMP_TIME_AFTER((unsigned long)Now,
480 (unsigned long)(pEntry->
484 struct rt_measure_req_entry *pPrevEntry = NULL;
485 unsigned long HashIdx =
486 MQ_DIALOGTOKEN_HASH_INDEX(pEntry->
488 struct rt_measure_req_entry *pProbeEntry =
491 /* update Hash list */
493 if (pProbeEntry == pEntry) {
494 if (pPrevEntry == NULL) {
495 pTab->Hash[HashIdx] =
504 pPrevEntry = pProbeEntry;
505 pProbeEntry = pProbeEntry->pNext;
506 } while (pProbeEntry);
508 NdisZeroMemory(pEntry,
509 sizeof(struct rt_measure_req_entry));
515 if (pEntry->Valid == FALSE)
519 if (i < MAX_MEASURE_REQ_TAB_SIZE) {
520 NdisGetSystemUpTime(&Now);
521 pEntry->lastTime = Now;
522 pEntry->Valid = TRUE;
523 pEntry->DialogToken = DialogToken;
527 DBGPRINT(RT_DEBUG_ERROR,
528 ("%s: pMeasureReqTab tab full.\n", __func__));
531 /* add this Neighbor entry into HASH table */
533 HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(DialogToken);
534 if (pTab->Hash[HashIdx] == NULL) {
535 pTab->Hash[HashIdx] = pEntry;
537 pCurrEntry = pTab->Hash[HashIdx];
538 while (pCurrEntry->pNext != NULL)
539 pCurrEntry = pCurrEntry->pNext;
540 pCurrEntry->pNext = pEntry;
544 RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock);
550 void MeasureReqDelete(struct rt_rtmp_adapter *pAd, u8 DialogToken)
552 struct rt_measure_req_tab *pTab = pAd->CommonCfg.pMeasureReqTab;
553 struct rt_measure_req_entry *pEntry = NULL;
556 DBGPRINT(RT_DEBUG_ERROR,
557 ("%s: pMeasureReqTab doesn't exist.\n", __func__));
560 /* if empty, return */
561 if (pTab->Size == 0) {
562 DBGPRINT(RT_DEBUG_ERROR, ("pMeasureReqTab empty.\n"));
566 pEntry = MeasureReqLookUp(pAd, DialogToken);
567 if (pEntry != NULL) {
568 struct rt_measure_req_entry *pPrevEntry = NULL;
569 unsigned long HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken);
570 struct rt_measure_req_entry *pProbeEntry = pTab->Hash[HashIdx];
572 RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock);
573 /* update Hash list */
575 if (pProbeEntry == pEntry) {
576 if (pPrevEntry == NULL) {
577 pTab->Hash[HashIdx] = pEntry->pNext;
579 pPrevEntry->pNext = pEntry->pNext;
584 pPrevEntry = pProbeEntry;
585 pProbeEntry = pProbeEntry->pNext;
586 } while (pProbeEntry);
588 NdisZeroMemory(pEntry, sizeof(struct rt_measure_req_entry));
591 RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock);
597 void TpcReqTabInit(struct rt_rtmp_adapter *pAd)
599 NdisAllocateSpinLock(&pAd->CommonCfg.TpcReqTabLock);
601 pAd->CommonCfg.pTpcReqTab = kmalloc(sizeof(struct rt_tpc_req_tab), GFP_ATOMIC);
602 if (pAd->CommonCfg.pTpcReqTab)
603 NdisZeroMemory(pAd->CommonCfg.pTpcReqTab, sizeof(struct rt_tpc_req_tab));
605 DBGPRINT(RT_DEBUG_ERROR,
606 ("%s Fail to alloc memory for pAd->CommonCfg.pTpcReqTab.\n",
612 void TpcReqTabExit(struct rt_rtmp_adapter *pAd)
614 NdisFreeSpinLock(&pAd->CommonCfg.TpcReqTabLock);
616 kfree(pAd->CommonCfg.pTpcReqTab);
617 pAd->CommonCfg.pTpcReqTab = NULL;
622 static struct rt_tpc_req_entry *TpcReqLookUp(struct rt_rtmp_adapter *pAd, u8 DialogToken)
625 struct rt_tpc_req_tab *pTab = pAd->CommonCfg.pTpcReqTab;
626 struct rt_tpc_req_entry *pEntry = NULL;
627 struct rt_tpc_req_entry *pPrevEntry = NULL;
630 DBGPRINT(RT_DEBUG_ERROR,
631 ("%s: pTpcReqTab doesn't exist.\n", __func__));
635 RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock);
637 HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(DialogToken);
638 pEntry = pTab->Hash[HashIdx];
641 if (pEntry->DialogToken == DialogToken)
645 pEntry = pEntry->pNext;
649 RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock);
654 static struct rt_tpc_req_entry *TpcReqInsert(struct rt_rtmp_adapter *pAd, u8 DialogToken)
657 unsigned long HashIdx;
658 struct rt_tpc_req_tab *pTab = pAd->CommonCfg.pTpcReqTab;
659 struct rt_tpc_req_entry *pEntry = NULL, *pCurrEntry;
663 DBGPRINT(RT_DEBUG_ERROR,
664 ("%s: pTpcReqTab doesn't exist.\n", __func__));
668 pEntry = TpcReqLookUp(pAd, DialogToken);
669 if (pEntry == NULL) {
670 RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock);
671 for (i = 0; i < MAX_TPC_REQ_TAB_SIZE; i++) {
672 NdisGetSystemUpTime(&Now);
673 pEntry = &pTab->Content[i];
675 if ((pEntry->Valid == TRUE)
676 && RTMP_TIME_AFTER((unsigned long)Now,
677 (unsigned long)(pEntry->
681 struct rt_tpc_req_entry *pPrevEntry = NULL;
682 unsigned long HashIdx =
683 TPC_DIALOGTOKEN_HASH_INDEX(pEntry->
685 struct rt_tpc_req_entry *pProbeEntry =
688 /* update Hash list */
690 if (pProbeEntry == pEntry) {
691 if (pPrevEntry == NULL) {
692 pTab->Hash[HashIdx] =
701 pPrevEntry = pProbeEntry;
702 pProbeEntry = pProbeEntry->pNext;
703 } while (pProbeEntry);
705 NdisZeroMemory(pEntry, sizeof(struct rt_tpc_req_entry));
711 if (pEntry->Valid == FALSE)
715 if (i < MAX_TPC_REQ_TAB_SIZE) {
716 NdisGetSystemUpTime(&Now);
717 pEntry->lastTime = Now;
718 pEntry->Valid = TRUE;
719 pEntry->DialogToken = DialogToken;
723 DBGPRINT(RT_DEBUG_ERROR,
724 ("%s: pTpcReqTab tab full.\n", __func__));
727 /* add this Neighbor entry into HASH table */
729 HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(DialogToken);
730 if (pTab->Hash[HashIdx] == NULL) {
731 pTab->Hash[HashIdx] = pEntry;
733 pCurrEntry = pTab->Hash[HashIdx];
734 while (pCurrEntry->pNext != NULL)
735 pCurrEntry = pCurrEntry->pNext;
736 pCurrEntry->pNext = pEntry;
740 RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock);
746 static void TpcReqDelete(struct rt_rtmp_adapter *pAd, u8 DialogToken)
748 struct rt_tpc_req_tab *pTab = pAd->CommonCfg.pTpcReqTab;
749 struct rt_tpc_req_entry *pEntry = NULL;
752 DBGPRINT(RT_DEBUG_ERROR,
753 ("%s: pTpcReqTab doesn't exist.\n", __func__));
756 /* if empty, return */
757 if (pTab->Size == 0) {
758 DBGPRINT(RT_DEBUG_ERROR, ("pTpcReqTab empty.\n"));
762 pEntry = TpcReqLookUp(pAd, DialogToken);
763 if (pEntry != NULL) {
764 struct rt_tpc_req_entry *pPrevEntry = NULL;
765 unsigned long HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken);
766 struct rt_tpc_req_entry *pProbeEntry = pTab->Hash[HashIdx];
768 RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock);
769 /* update Hash list */
771 if (pProbeEntry == pEntry) {
772 if (pPrevEntry == NULL) {
773 pTab->Hash[HashIdx] = pEntry->pNext;
775 pPrevEntry->pNext = pEntry->pNext;
780 pPrevEntry = pProbeEntry;
781 pProbeEntry = pProbeEntry->pNext;
782 } while (pProbeEntry);
784 NdisZeroMemory(pEntry, sizeof(struct rt_tpc_req_entry));
787 RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock);
794 ==========================================================================
796 Get Current TimeS tamp.
800 Return : Current Time Stamp.
801 ==========================================================================
803 static u64 GetCurrentTimeStamp(struct rt_rtmp_adapter *pAd)
805 /* get current time stamp. */
810 ==========================================================================
812 Get Current Transmit Power.
816 Return : Current Time Stamp.
817 ==========================================================================
819 static u8 GetCurTxPwr(struct rt_rtmp_adapter *pAd, u8 Wcid)
821 return 16; /* 16 dBm */
825 ==========================================================================
827 Get Current Transmit Power.
831 Return : Current Time Stamp.
832 ==========================================================================
834 void InsertChannelRepIE(struct rt_rtmp_adapter *pAd,
836 unsigned long *pFrameLen,
837 char *pCountry, u8 RegulatoryClass)
839 unsigned long TempLen;
841 u8 IEId = IE_AP_CHANNEL_REPORT;
842 u8 *pChListPtr = NULL;
845 if (strncmp(pCountry, "US", 2) == 0) {
846 if (RegulatoryClass >= USA_REGULATORY_INFO_SIZE) {
847 DBGPRINT(RT_DEBUG_ERROR,
848 ("%s: USA Unknow Requlatory class (%d)\n",
849 __func__, RegulatoryClass));
854 USARegulatoryInfo[RegulatoryClass].ChannelSet.
857 USARegulatoryInfo[RegulatoryClass].ChannelSet.ChannelList;
858 } else if (strncmp(pCountry, "JP", 2) == 0) {
859 if (RegulatoryClass >= JP_REGULATORY_INFO_SIZE) {
860 DBGPRINT(RT_DEBUG_ERROR,
861 ("%s: JP Unknow Requlatory class (%d)\n",
862 __func__, RegulatoryClass));
867 JapanRegulatoryInfo[RegulatoryClass].ChannelSet.
870 JapanRegulatoryInfo[RegulatoryClass].ChannelSet.ChannelList;
872 DBGPRINT(RT_DEBUG_ERROR, ("%s: Unknow Country (%s)\n",
873 __func__, pCountry));
877 MakeOutgoingFrame(pFrameBuf, &TempLen,
881 Len - 1, pChListPtr, END_OF_ARGS);
883 *pFrameLen = *pFrameLen + TempLen;
889 ==========================================================================
891 Insert Dialog Token into frame.
894 1. frame buffer pointer.
899 ==========================================================================
901 void InsertDialogToken(struct rt_rtmp_adapter *pAd,
903 unsigned long *pFrameLen, u8 DialogToken)
905 unsigned long TempLen;
906 MakeOutgoingFrame(pFrameBuf, &TempLen, 1, &DialogToken, END_OF_ARGS);
908 *pFrameLen = *pFrameLen + TempLen;
914 ==========================================================================
916 Insert TPC Request IE into frame.
919 1. frame buffer pointer.
923 ==========================================================================
925 static void InsertTpcReqIE(struct rt_rtmp_adapter *pAd,
926 u8 *pFrameBuf, unsigned long *pFrameLen)
928 unsigned long TempLen;
929 unsigned long Len = 0;
930 u8 ElementID = IE_TPC_REQUEST;
932 MakeOutgoingFrame(pFrameBuf, &TempLen,
933 1, &ElementID, 1, &Len, END_OF_ARGS);
935 *pFrameLen = *pFrameLen + TempLen;
941 ==========================================================================
943 Insert TPC Report IE into frame.
946 1. frame buffer pointer.
952 ==========================================================================
954 void InsertTpcReportIE(struct rt_rtmp_adapter *pAd,
956 unsigned long *pFrameLen,
957 u8 TxPwr, u8 LinkMargin)
959 unsigned long TempLen;
960 unsigned long Len = sizeof(struct rt_tpc_report_info);
961 u8 ElementID = IE_TPC_REPORT;
962 struct rt_tpc_report_info TpcReportIE;
964 TpcReportIE.TxPwr = TxPwr;
965 TpcReportIE.LinkMargin = LinkMargin;
967 MakeOutgoingFrame(pFrameBuf, &TempLen,
969 1, &Len, Len, &TpcReportIE, END_OF_ARGS);
971 *pFrameLen = *pFrameLen + TempLen;
977 ==========================================================================
979 Insert Channel Switch Announcement IE into frame.
982 1. frame buffer pointer.
984 3. channel switch announcement mode.
985 4. new selected channel.
986 5. channel switch announcement count.
989 ==========================================================================
991 static void InsertChSwAnnIE(struct rt_rtmp_adapter *pAd,
993 unsigned long *pFrameLen,
995 u8 NewChannel, u8 ChSwCnt)
997 unsigned long TempLen;
998 unsigned long Len = sizeof(struct rt_ch_sw_ann_info);
999 u8 ElementID = IE_CHANNEL_SWITCH_ANNOUNCEMENT;
1000 struct rt_ch_sw_ann_info ChSwAnnIE;
1002 ChSwAnnIE.ChSwMode = ChSwMode;
1003 ChSwAnnIE.Channel = NewChannel;
1004 ChSwAnnIE.ChSwCnt = ChSwCnt;
1006 MakeOutgoingFrame(pFrameBuf, &TempLen,
1007 1, &ElementID, 1, &Len, Len, &ChSwAnnIE, END_OF_ARGS);
1009 *pFrameLen = *pFrameLen + TempLen;
1015 ==========================================================================
1017 Insert Measure Request IE into frame.
1020 1. frame buffer pointer.
1023 4. Measure Request Mode.
1024 5. Measure Request Type.
1026 7. Measure Start time.
1027 8. Measure Duration.
1030 ==========================================================================
1032 static void InsertMeasureReqIE(struct rt_rtmp_adapter *pAd,
1034 unsigned long *pFrameLen,
1035 u8 Len, struct rt_measure_req_info * pMeasureReqIE)
1037 unsigned long TempLen;
1038 u8 ElementID = IE_MEASUREMENT_REQUEST;
1040 MakeOutgoingFrame(pFrameBuf, &TempLen,
1043 sizeof(struct rt_measure_req_info), pMeasureReqIE, END_OF_ARGS);
1045 *pFrameLen = *pFrameLen + TempLen;
1051 ==========================================================================
1053 Insert Measure Report IE into frame.
1056 1. frame buffer pointer.
1059 4. Measure Request Mode.
1060 5. Measure Request Type.
1061 6. Length of Report Information
1062 7. Pointer of Report Information Buffer.
1065 ==========================================================================
1067 static void InsertMeasureReportIE(struct rt_rtmp_adapter *pAd,
1069 unsigned long *pFrameLen,
1070 struct rt_measure_report_info * pMeasureReportIE,
1071 u8 ReportLnfoLen, u8 *pReportInfo)
1073 unsigned long TempLen;
1075 u8 ElementID = IE_MEASUREMENT_REPORT;
1077 Len = sizeof(struct rt_measure_report_info) + ReportLnfoLen;
1079 MakeOutgoingFrame(pFrameBuf, &TempLen,
1081 1, &Len, Len, pMeasureReportIE, END_OF_ARGS);
1083 *pFrameLen = *pFrameLen + TempLen;
1085 if ((ReportLnfoLen > 0) && (pReportInfo != NULL)) {
1086 MakeOutgoingFrame(pFrameBuf + *pFrameLen, &TempLen,
1087 ReportLnfoLen, pReportInfo, END_OF_ARGS);
1089 *pFrameLen = *pFrameLen + TempLen;
1095 ==========================================================================
1097 Prepare Measurement request action frame and enqueue it into
1098 management queue waiting for transmition.
1101 1. the destination mac address of the frame.
1104 ==========================================================================
1106 void MakeMeasurementReqFrame(struct rt_rtmp_adapter *pAd,
1108 unsigned long *pFrameLen,
1114 u8 MeasureReqType, u8 NumOfRepetitions)
1116 unsigned long TempLen;
1117 struct rt_measure_req_info MeasureReqIE;
1119 InsertActField(pAd, (pOutBuffer + *pFrameLen), pFrameLen, Category,
1122 /* fill Dialog Token */
1123 InsertDialogToken(pAd, (pOutBuffer + *pFrameLen), pFrameLen,
1126 /* fill Number of repetitions. */
1127 if (Category == CATEGORY_RM) {
1128 MakeOutgoingFrame((pOutBuffer + *pFrameLen), &TempLen,
1129 2, &NumOfRepetitions, END_OF_ARGS);
1131 *pFrameLen += TempLen;
1133 /* prepare Measurement IE. */
1134 NdisZeroMemory(&MeasureReqIE, sizeof(struct rt_measure_req_info));
1135 MeasureReqIE.Token = MeasureToken;
1136 MeasureReqIE.ReqMode.word = MeasureReqMode;
1137 MeasureReqIE.ReqType = MeasureReqType;
1138 InsertMeasureReqIE(pAd, (pOutBuffer + *pFrameLen), pFrameLen,
1139 TotalLen, &MeasureReqIE);
1145 ==========================================================================
1147 Prepare Measurement report action frame and enqueue it into
1148 management queue waiting for transmition.
1151 1. the destination mac address of the frame.
1154 ==========================================================================
1156 void EnqueueMeasurementRep(struct rt_rtmp_adapter *pAd,
1162 u8 ReportInfoLen, u8 *pReportInfo)
1164 u8 *pOutBuffer = NULL;
1166 unsigned long FrameLen;
1167 struct rt_header_802_11 ActHdr;
1168 struct rt_measure_report_info MeasureRepIE;
1170 /* build action frame header. */
1171 MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
1172 pAd->CurrentAddress);
1174 NStatus = MlmeAllocateMemory(pAd, (void *)& pOutBuffer); /*Get an unused nonpaged memory */
1175 if (NStatus != NDIS_STATUS_SUCCESS) {
1176 DBGPRINT(RT_DEBUG_TRACE,
1177 ("%s() allocate memory failed \n", __func__));
1180 NdisMoveMemory(pOutBuffer, (char *)& ActHdr, sizeof(struct rt_header_802_11));
1181 FrameLen = sizeof(struct rt_header_802_11);
1183 InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen,
1184 CATEGORY_SPECTRUM, SPEC_MRP);
1186 /* fill Dialog Token */
1187 InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken);
1189 /* prepare Measurement IE. */
1190 NdisZeroMemory(&MeasureRepIE, sizeof(struct rt_measure_report_info));
1191 MeasureRepIE.Token = MeasureToken;
1192 MeasureRepIE.ReportMode = MeasureReqMode;
1193 MeasureRepIE.ReportType = MeasureReqType;
1194 InsertMeasureReportIE(pAd, (pOutBuffer + FrameLen), &FrameLen,
1195 &MeasureRepIE, ReportInfoLen, pReportInfo);
1197 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1198 MlmeFreeMemory(pAd, pOutBuffer);
1204 ==========================================================================
1206 Prepare TPC Request action frame and enqueue it into
1207 management queue waiting for transmition.
1210 1. the destination mac address of the frame.
1213 ==========================================================================
1215 void EnqueueTPCReq(struct rt_rtmp_adapter *pAd, u8 *pDA, u8 DialogToken)
1217 u8 *pOutBuffer = NULL;
1219 unsigned long FrameLen;
1221 struct rt_header_802_11 ActHdr;
1223 /* build action frame header. */
1224 MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
1225 pAd->CurrentAddress);
1227 NStatus = MlmeAllocateMemory(pAd, (void *)& pOutBuffer); /*Get an unused nonpaged memory */
1228 if (NStatus != NDIS_STATUS_SUCCESS) {
1229 DBGPRINT(RT_DEBUG_TRACE,
1230 ("%s() allocate memory failed \n", __func__));
1233 NdisMoveMemory(pOutBuffer, (char *)& ActHdr, sizeof(struct rt_header_802_11));
1234 FrameLen = sizeof(struct rt_header_802_11);
1236 InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen,
1237 CATEGORY_SPECTRUM, SPEC_TPCRQ);
1239 /* fill Dialog Token */
1240 InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken);
1242 /* Insert TPC Request IE. */
1243 InsertTpcReqIE(pAd, (pOutBuffer + FrameLen), &FrameLen);
1245 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1246 MlmeFreeMemory(pAd, pOutBuffer);
1252 ==========================================================================
1254 Prepare TPC Report action frame and enqueue it into
1255 management queue waiting for transmition.
1258 1. the destination mac address of the frame.
1261 ==========================================================================
1263 void EnqueueTPCRep(struct rt_rtmp_adapter *pAd,
1265 u8 DialogToken, u8 TxPwr, u8 LinkMargin)
1267 u8 *pOutBuffer = NULL;
1269 unsigned long FrameLen;
1271 struct rt_header_802_11 ActHdr;
1273 /* build action frame header. */
1274 MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
1275 pAd->CurrentAddress);
1277 NStatus = MlmeAllocateMemory(pAd, (void *)& pOutBuffer); /*Get an unused nonpaged memory */
1278 if (NStatus != NDIS_STATUS_SUCCESS) {
1279 DBGPRINT(RT_DEBUG_TRACE,
1280 ("%s() allocate memory failed \n", __func__));
1283 NdisMoveMemory(pOutBuffer, (char *)& ActHdr, sizeof(struct rt_header_802_11));
1284 FrameLen = sizeof(struct rt_header_802_11);
1286 InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen,
1287 CATEGORY_SPECTRUM, SPEC_TPCRP);
1289 /* fill Dialog Token */
1290 InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken);
1292 /* Insert TPC Request IE. */
1293 InsertTpcReportIE(pAd, (pOutBuffer + FrameLen), &FrameLen, TxPwr,
1296 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1297 MlmeFreeMemory(pAd, pOutBuffer);
1303 ==========================================================================
1305 Prepare Channel Switch Announcement action frame and enqueue it into
1306 management queue waiting for transmition.
1309 1. the destination mac address of the frame.
1310 2. Channel switch announcement mode.
1311 2. a New selected channel.
1314 ==========================================================================
1316 void EnqueueChSwAnn(struct rt_rtmp_adapter *pAd,
1317 u8 *pDA, u8 ChSwMode, u8 NewCh)
1319 u8 *pOutBuffer = NULL;
1321 unsigned long FrameLen;
1323 struct rt_header_802_11 ActHdr;
1325 /* build action frame header. */
1326 MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
1327 pAd->CurrentAddress);
1329 NStatus = MlmeAllocateMemory(pAd, (void *)& pOutBuffer); /*Get an unused nonpaged memory */
1330 if (NStatus != NDIS_STATUS_SUCCESS) {
1331 DBGPRINT(RT_DEBUG_TRACE,
1332 ("%s() allocate memory failed \n", __func__));
1335 NdisMoveMemory(pOutBuffer, (char *)& ActHdr, sizeof(struct rt_header_802_11));
1336 FrameLen = sizeof(struct rt_header_802_11);
1338 InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen,
1339 CATEGORY_SPECTRUM, SPEC_CHANNEL_SWITCH);
1341 InsertChSwAnnIE(pAd, (pOutBuffer + FrameLen), &FrameLen, ChSwMode,
1344 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1345 MlmeFreeMemory(pAd, pOutBuffer);
1350 static BOOLEAN DfsRequirementCheck(struct rt_rtmp_adapter *pAd, u8 Channel)
1352 BOOLEAN Result = FALSE;
1356 /* check DFS procedure is running. */
1357 /* make sure DFS procedure won't start twice. */
1358 if (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE) {
1362 /* check the new channel carried from Channel Switch Announcemnet is valid. */
1363 for (i = 0; i < pAd->ChannelListNum; i++) {
1364 if ((Channel == pAd->ChannelList[i].Channel)
1365 && (pAd->ChannelList[i].RemainingTimeForUse == 0)) {
1366 /* found radar signal in the channel. the channel can't use at least for 30 minutes. */
1367 pAd->ChannelList[i].RemainingTimeForUse = 1800; /*30 min = 1800 sec */
1377 void NotifyChSwAnnToPeerAPs(struct rt_rtmp_adapter *pAd,
1379 u8 *pTA, u8 ChSwMode, u8 Channel)
1383 static void StartDFSProcedure(struct rt_rtmp_adapter *pAd,
1384 u8 Channel, u8 ChSwMode)
1386 /* start DFS procedure */
1387 pAd->CommonCfg.Channel = Channel;
1389 N_ChannelCheck(pAd);
1391 pAd->CommonCfg.RadarDetect.RDMode = RD_SWITCHING_MODE;
1392 pAd->CommonCfg.RadarDetect.CSCount = 0;
1396 ==========================================================================
1398 Channel Switch Announcement action frame sanity check.
1401 1. MLME message containing the received frame
1403 3. Channel switch announcement information buffer.
1406 ==========================================================================
1410 Channel Switch Announcement IE.
1411 +----+-----+-----------+------------+-----------+
1412 | ID | Len |Ch Sw Mode | New Ch Num | Ch Sw Cnt |
1413 +----+-----+-----------+------------+-----------+
1416 static BOOLEAN PeerChSwAnnSanity(struct rt_rtmp_adapter *pAd,
1418 unsigned long MsgLen,
1419 struct rt_ch_sw_ann_info * pChSwAnnInfo)
1421 struct rt_frame_802_11 * Fr = (struct rt_frame_802_11 *) pMsg;
1422 u8 *pFramePtr = Fr->Octet;
1423 BOOLEAN result = FALSE;
1424 struct rt_eid * eid_ptr;
1426 /* skip 802.11 header. */
1427 MsgLen -= sizeof(struct rt_header_802_11);
1429 /* skip category and action code. */
1433 if (pChSwAnnInfo == NULL)
1436 eid_ptr = (struct rt_eid *) pFramePtr;
1437 while (((u8 *) eid_ptr + eid_ptr->Len + 1) <
1438 ((u8 *)pFramePtr + MsgLen)) {
1439 switch (eid_ptr->Eid) {
1440 case IE_CHANNEL_SWITCH_ANNOUNCEMENT:
1441 NdisMoveMemory(&pChSwAnnInfo->ChSwMode, eid_ptr->Octet,
1443 NdisMoveMemory(&pChSwAnnInfo->Channel,
1444 eid_ptr->Octet + 1, 1);
1445 NdisMoveMemory(&pChSwAnnInfo->ChSwCnt,
1446 eid_ptr->Octet + 2, 1);
1454 eid_ptr = (struct rt_eid *) ((u8 *) eid_ptr + 2 + eid_ptr->Len);
1461 ==========================================================================
1463 Measurement request action frame sanity check.
1466 1. MLME message containing the received frame
1468 3. Measurement request information buffer.
1471 ==========================================================================
1473 static BOOLEAN PeerMeasureReqSanity(struct rt_rtmp_adapter *pAd,
1475 unsigned long MsgLen,
1477 struct rt_measure_req_info * pMeasureReqInfo,
1478 struct rt_measure_req * pMeasureReq)
1480 struct rt_frame_802_11 * Fr = (struct rt_frame_802_11 *) pMsg;
1481 u8 *pFramePtr = Fr->Octet;
1482 BOOLEAN result = FALSE;
1483 struct rt_eid * eid_ptr;
1485 u64 MeasureStartTime;
1486 u16 MeasureDuration;
1488 /* skip 802.11 header. */
1489 MsgLen -= sizeof(struct rt_header_802_11);
1491 /* skip category and action code. */
1495 if (pMeasureReqInfo == NULL)
1498 NdisMoveMemory(pDialogToken, pFramePtr, 1);
1502 eid_ptr = (struct rt_eid *) pFramePtr;
1503 while (((u8 *) eid_ptr + eid_ptr->Len + 1) <
1504 ((u8 *)pFramePtr + MsgLen)) {
1505 switch (eid_ptr->Eid) {
1506 case IE_MEASUREMENT_REQUEST:
1507 NdisMoveMemory(&pMeasureReqInfo->Token, eid_ptr->Octet,
1509 NdisMoveMemory(&pMeasureReqInfo->ReqMode.word,
1510 eid_ptr->Octet + 1, 1);
1511 NdisMoveMemory(&pMeasureReqInfo->ReqType,
1512 eid_ptr->Octet + 2, 1);
1513 ptr = (u8 *)(eid_ptr->Octet + 3);
1514 NdisMoveMemory(&pMeasureReq->ChNum, ptr, 1);
1515 NdisMoveMemory(&MeasureStartTime, ptr + 1, 8);
1516 pMeasureReq->MeasureStartTime =
1517 SWAP64(MeasureStartTime);
1518 NdisMoveMemory(&MeasureDuration, ptr + 9, 2);
1519 pMeasureReq->MeasureDuration = SWAP16(MeasureDuration);
1527 eid_ptr = (struct rt_eid *) ((u8 *) eid_ptr + 2 + eid_ptr->Len);
1534 ==========================================================================
1536 Measurement report action frame sanity check.
1539 1. MLME message containing the received frame
1541 3. Measurement report information buffer.
1542 4. basic report information buffer.
1545 ==========================================================================
1549 Measurement Report IE.
1550 +----+-----+-------+-------------+--------------+----------------+
1551 | ID | Len | Token | Report Mode | Measure Type | Measure Report |
1552 +----+-----+-------+-------------+--------------+----------------+
1556 +--------+------------+----------+-----+
1557 | Ch Num | Start Time | Duration | Map |
1558 +--------+------------+----------+-----+
1561 Map Field Bit Format.
1562 +-----+---------------+---------------------+-------+------------+----------+
1563 | Bss | OFDM Preamble | Unidentified signal | Radar | Unmeasured | Reserved |
1564 +-----+---------------+---------------------+-------+------------+----------+
1567 static BOOLEAN PeerMeasureReportSanity(struct rt_rtmp_adapter *pAd,
1569 unsigned long MsgLen,
1571 struct rt_measure_report_info *
1575 struct rt_frame_802_11 * Fr = (struct rt_frame_802_11 *) pMsg;
1576 u8 *pFramePtr = Fr->Octet;
1577 BOOLEAN result = FALSE;
1578 struct rt_eid * eid_ptr;
1581 /* skip 802.11 header. */
1582 MsgLen -= sizeof(struct rt_header_802_11);
1584 /* skip category and action code. */
1588 if (pMeasureReportInfo == NULL)
1591 NdisMoveMemory(pDialogToken, pFramePtr, 1);
1595 eid_ptr = (struct rt_eid *) pFramePtr;
1596 while (((u8 *) eid_ptr + eid_ptr->Len + 1) <
1597 ((u8 *)pFramePtr + MsgLen)) {
1598 switch (eid_ptr->Eid) {
1599 case IE_MEASUREMENT_REPORT:
1600 NdisMoveMemory(&pMeasureReportInfo->Token,
1602 NdisMoveMemory(&pMeasureReportInfo->ReportMode,
1603 eid_ptr->Octet + 1, 1);
1604 NdisMoveMemory(&pMeasureReportInfo->ReportType,
1605 eid_ptr->Octet + 2, 1);
1606 if (pMeasureReportInfo->ReportType == RM_BASIC) {
1607 struct rt_measure_basic_report * pReport =
1608 (struct rt_measure_basic_report *) pReportBuf;
1609 ptr = (u8 *)(eid_ptr->Octet + 3);
1610 NdisMoveMemory(&pReport->ChNum, ptr, 1);
1611 NdisMoveMemory(&pReport->MeasureStartTime,
1613 NdisMoveMemory(&pReport->MeasureDuration,
1615 NdisMoveMemory(&pReport->Map, ptr + 11, 1);
1617 } else if (pMeasureReportInfo->ReportType == RM_CCA) {
1618 struct rt_measure_cca_report * pReport =
1619 (struct rt_measure_cca_report *) pReportBuf;
1620 ptr = (u8 *)(eid_ptr->Octet + 3);
1621 NdisMoveMemory(&pReport->ChNum, ptr, 1);
1622 NdisMoveMemory(&pReport->MeasureStartTime,
1624 NdisMoveMemory(&pReport->MeasureDuration,
1626 NdisMoveMemory(&pReport->CCA_Busy_Fraction,
1629 } else if (pMeasureReportInfo->ReportType ==
1631 struct rt_measure_rpi_report * pReport =
1632 (struct rt_measure_rpi_report *) pReportBuf;
1633 ptr = (u8 *)(eid_ptr->Octet + 3);
1634 NdisMoveMemory(&pReport->ChNum, ptr, 1);
1635 NdisMoveMemory(&pReport->MeasureStartTime,
1637 NdisMoveMemory(&pReport->MeasureDuration,
1639 NdisMoveMemory(&pReport->RPI_Density, ptr + 11,
1648 eid_ptr = (struct rt_eid *) ((u8 *) eid_ptr + 2 + eid_ptr->Len);
1655 ==========================================================================
1657 TPC Request action frame sanity check.
1660 1. MLME message containing the received frame
1665 ==========================================================================
1667 static BOOLEAN PeerTpcReqSanity(struct rt_rtmp_adapter *pAd,
1669 unsigned long MsgLen, u8 *pDialogToken)
1671 struct rt_frame_802_11 * Fr = (struct rt_frame_802_11 *) pMsg;
1672 u8 *pFramePtr = Fr->Octet;
1673 BOOLEAN result = FALSE;
1674 struct rt_eid * eid_ptr;
1676 MsgLen -= sizeof(struct rt_header_802_11);
1678 /* skip category and action code. */
1682 if (pDialogToken == NULL)
1685 NdisMoveMemory(pDialogToken, pFramePtr, 1);
1689 eid_ptr = (struct rt_eid *) pFramePtr;
1690 while (((u8 *) eid_ptr + eid_ptr->Len + 1) <
1691 ((u8 *)pFramePtr + MsgLen)) {
1692 switch (eid_ptr->Eid) {
1693 case IE_TPC_REQUEST:
1700 eid_ptr = (struct rt_eid *) ((u8 *) eid_ptr + 2 + eid_ptr->Len);
1707 ==========================================================================
1709 TPC Report action frame sanity check.
1712 1. MLME message containing the received frame
1718 ==========================================================================
1720 static BOOLEAN PeerTpcRepSanity(struct rt_rtmp_adapter *pAd,
1722 unsigned long MsgLen,
1724 struct rt_tpc_report_info * pTpcRepInfo)
1726 struct rt_frame_802_11 * Fr = (struct rt_frame_802_11 *) pMsg;
1727 u8 *pFramePtr = Fr->Octet;
1728 BOOLEAN result = FALSE;
1729 struct rt_eid * eid_ptr;
1731 MsgLen -= sizeof(struct rt_header_802_11);
1733 /* skip category and action code. */
1737 if (pDialogToken == NULL)
1740 NdisMoveMemory(pDialogToken, pFramePtr, 1);
1744 eid_ptr = (struct rt_eid *) pFramePtr;
1745 while (((u8 *) eid_ptr + eid_ptr->Len + 1) <
1746 ((u8 *)pFramePtr + MsgLen)) {
1747 switch (eid_ptr->Eid) {
1749 NdisMoveMemory(&pTpcRepInfo->TxPwr, eid_ptr->Octet, 1);
1750 NdisMoveMemory(&pTpcRepInfo->LinkMargin,
1751 eid_ptr->Octet + 1, 1);
1758 eid_ptr = (struct rt_eid *) ((u8 *) eid_ptr + 2 + eid_ptr->Len);
1765 ==========================================================================
1767 Channel Switch Announcement action frame handler.
1770 Elme - MLME message containing the received frame
1773 ==========================================================================
1775 static void PeerChSwAnnAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
1777 struct rt_ch_sw_ann_info ChSwAnnInfo;
1778 struct rt_frame_802_11 * pFr = (struct rt_frame_802_11 *) Elem->Msg;
1779 u8 index = 0, Channel = 0, NewChannel = 0;
1780 unsigned long Bssidx = 0;
1782 NdisZeroMemory(&ChSwAnnInfo, sizeof(struct rt_ch_sw_ann_info));
1783 if (!PeerChSwAnnSanity(pAd, Elem->Msg, Elem->MsgLen, &ChSwAnnInfo)) {
1784 DBGPRINT(RT_DEBUG_TRACE,
1785 ("Invalid Channel Switch Action Frame.\n"));
1789 if (pAd->OpMode == OPMODE_STA) {
1791 BssTableSearch(&pAd->ScanTab, pFr->Hdr.Addr3,
1792 pAd->CommonCfg.Channel);
1793 if (Bssidx == BSS_NOT_FOUND) {
1794 DBGPRINT(RT_DEBUG_TRACE,
1795 ("PeerChSwAnnAction - Bssidx is not found\n"));
1799 DBGPRINT(RT_DEBUG_TRACE,
1800 ("\n****Bssidx is %d, Channel = %d\n", index,
1801 pAd->ScanTab.BssEntry[Bssidx].Channel));
1802 hex_dump("SSID", pAd->ScanTab.BssEntry[Bssidx].Bssid, 6);
1804 Channel = pAd->CommonCfg.Channel;
1805 NewChannel = ChSwAnnInfo.Channel;
1807 if ((pAd->CommonCfg.bIEEE80211H == 1) && (NewChannel != 0)
1808 && (Channel != NewChannel)) {
1809 /* Switching to channel 1 can prevent from rescanning the current channel immediately (by auto reconnection). */
1810 /* In addition, clear the MLME queue and the scan table to discard the RX packets and previous scanning results. */
1811 AsicSwitchChannel(pAd, 1, FALSE);
1812 AsicLockChannel(pAd, 1);
1813 LinkDown(pAd, FALSE);
1814 MlmeQueueInit(&pAd->Mlme.Queue);
1815 BssTableInit(&pAd->ScanTab);
1816 RTMPusecDelay(1000000); /* use delay to prevent STA do reassoc */
1818 /* channel sanity check */
1819 for (index = 0; index < pAd->ChannelListNum; index++) {
1820 if (pAd->ChannelList[index].Channel ==
1822 pAd->ScanTab.BssEntry[Bssidx].Channel =
1824 pAd->CommonCfg.Channel = NewChannel;
1825 AsicSwitchChannel(pAd,
1828 AsicLockChannel(pAd,
1829 pAd->CommonCfg.Channel);
1830 DBGPRINT(RT_DEBUG_TRACE,
1831 ("&&&&&&&&&&&&&&&&PeerChSwAnnAction - STA receive channel switch announcement IE (New Channel =%d)\n",
1837 if (index >= pAd->ChannelListNum) {
1838 DBGPRINT_ERR("&&&&&&&&&&&&&&&&&&&&&&&&&&PeerChSwAnnAction(can not find New Channel=%d in ChannelList[%d]\n", pAd->CommonCfg.Channel, pAd->ChannelListNum);
1847 ==========================================================================
1849 Measurement Request action frame handler.
1852 Elme - MLME message containing the received frame
1855 ==========================================================================
1857 static void PeerMeasureReqAction(struct rt_rtmp_adapter *pAd,
1858 struct rt_mlme_queue_elem *Elem)
1860 struct rt_frame_802_11 * pFr = (struct rt_frame_802_11 *) Elem->Msg;
1862 struct rt_measure_req_info MeasureReqInfo;
1863 struct rt_measure_req MeasureReq;
1864 MEASURE_REPORT_MODE ReportMode;
1866 if (PeerMeasureReqSanity
1867 (pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &MeasureReqInfo,
1869 ReportMode.word = 0;
1870 ReportMode.field.Incapable = 1;
1871 EnqueueMeasurementRep(pAd, pFr->Hdr.Addr2, DialogToken,
1872 MeasureReqInfo.Token, ReportMode.word,
1873 MeasureReqInfo.ReqType, 0, NULL);
1880 ==========================================================================
1882 Measurement Report action frame handler.
1885 Elme - MLME message containing the received frame
1888 ==========================================================================
1890 static void PeerMeasureReportAction(struct rt_rtmp_adapter *pAd,
1891 struct rt_mlme_queue_elem *Elem)
1893 struct rt_measure_report_info MeasureReportInfo;
1894 struct rt_frame_802_11 * pFr = (struct rt_frame_802_11 *) Elem->Msg;
1896 u8 *pMeasureReportInfo;
1898 /* if (pAd->CommonCfg.bIEEE80211H != TRUE) */
1901 pMeasureReportInfo = kmalloc(sizeof(struct rt_measure_rpi_report), GFP_ATOMIC);
1902 if (pMeasureReportInfo == NULL) {
1903 DBGPRINT(RT_DEBUG_ERROR,
1904 ("%s unable to alloc memory for measure report buffer (size=%zu).\n",
1905 __func__, sizeof(struct rt_measure_rpi_report)));
1909 NdisZeroMemory(&MeasureReportInfo, sizeof(struct rt_measure_report_info));
1910 NdisZeroMemory(pMeasureReportInfo, sizeof(struct rt_measure_rpi_report));
1911 if (PeerMeasureReportSanity
1912 (pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &MeasureReportInfo,
1913 pMeasureReportInfo)) {
1915 struct rt_measure_req_entry *pEntry = NULL;
1917 /* Not a autonomous measure report. */
1918 /* check the dialog token field. drop it if the dialog token doesn't match. */
1919 if ((DialogToken != 0)
1920 && ((pEntry = MeasureReqLookUp(pAd, DialogToken)) ==
1925 MeasureReqDelete(pAd, pEntry->DialogToken);
1927 if (MeasureReportInfo.ReportType == RM_BASIC) {
1928 struct rt_measure_basic_report * pBasicReport =
1929 (struct rt_measure_basic_report *) pMeasureReportInfo;
1930 if ((pBasicReport->Map.field.Radar)
1932 (DfsRequirementCheck
1933 (pAd, pBasicReport->ChNum) == TRUE)) {
1934 NotifyChSwAnnToPeerAPs(pAd,
1940 StartDFSProcedure(pAd,
1941 pBasicReport->ChNum,
1947 DBGPRINT(RT_DEBUG_TRACE,
1948 ("Invalid Measurement Report Frame.\n"));
1950 kfree(pMeasureReportInfo);
1956 ==========================================================================
1958 TPC Request action frame handler.
1961 Elme - MLME message containing the received frame
1964 ==========================================================================
1966 static void PeerTpcReqAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
1968 struct rt_frame_802_11 * pFr = (struct rt_frame_802_11 *) Elem->Msg;
1969 u8 *pFramePtr = pFr->Octet;
1971 u8 TxPwr = GetCurTxPwr(pAd, Elem->Wcid);
1975 /* link margin: Ratio of the received signal power to the minimum desired by the station (STA). The */
1976 /* STA may incorporate rate information and channel conditions, including interference, into its computation */
1977 /* of link margin. */
1979 RealRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0),
1980 ConvertToRssi(pAd, Elem->Rssi1, RSSI_1),
1981 ConvertToRssi(pAd, Elem->Rssi2, RSSI_2));
1983 /* skip Category and action code. */
1987 NdisMoveMemory(&DialogToken, pFramePtr, 1);
1989 LinkMargin = (RealRssi / MIN_RCV_PWR);
1990 if (PeerTpcReqSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken))
1991 EnqueueTPCRep(pAd, pFr->Hdr.Addr2, DialogToken, TxPwr,
1998 ==========================================================================
2000 TPC Report action frame handler.
2003 Elme - MLME message containing the received frame
2006 ==========================================================================
2008 static void PeerTpcRepAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
2011 struct rt_tpc_report_info TpcRepInfo;
2012 struct rt_tpc_req_entry *pEntry = NULL;
2014 NdisZeroMemory(&TpcRepInfo, sizeof(struct rt_tpc_report_info));
2015 if (PeerTpcRepSanity
2016 (pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &TpcRepInfo)) {
2017 pEntry = TpcReqLookUp(pAd, DialogToken);
2018 if (pEntry != NULL) {
2019 TpcReqDelete(pAd, pEntry->DialogToken);
2020 DBGPRINT(RT_DEBUG_TRACE,
2021 ("%s: DialogToken=%x, TxPwr=%d, LinkMargin=%d\n",
2022 __func__, DialogToken, TpcRepInfo.TxPwr,
2023 TpcRepInfo.LinkMargin));
2031 ==========================================================================
2033 Spectrun action frames Handler such as channel switch annoucement,
2034 measurement report, measurement request actions frames.
2037 Elme - MLME message containing the received frame
2040 ==========================================================================
2042 void PeerSpectrumAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
2045 u8 Action = Elem->Msg[LENGTH_802_11 + 1];
2047 if (pAd->CommonCfg.bIEEE80211H != TRUE)
2052 /* current rt2860 unable do such measure specified in Measurement Request. */
2053 /* reject all measurement request. */
2054 PeerMeasureReqAction(pAd, Elem);
2058 PeerMeasureReportAction(pAd, Elem);
2062 PeerTpcReqAction(pAd, Elem);
2066 PeerTpcRepAction(pAd, Elem);
2069 case SPEC_CHANNEL_SWITCH:
2071 PeerChSwAnnAction(pAd, Elem);
2079 ==========================================================================
2085 ==========================================================================
2087 int Set_MeasureReq_Proc(struct rt_rtmp_adapter *pAd, char *arg)
2093 MEASURE_REQ_MODE MeasureReqMode;
2094 u8 MeasureReqToken = RandomByte(pAd);
2095 u8 MeasureReqType = RM_BASIC;
2097 u64 MeasureStartTime = GetCurrentTimeStamp(pAd);
2098 struct rt_measure_req MeasureReq;
2101 struct rt_header_802_11 ActHdr;
2102 u8 *pOutBuffer = NULL;
2104 unsigned long FrameLen;
2106 NStatus = MlmeAllocateMemory(pAd, (void *)& pOutBuffer); /*Get an unused nonpaged memory */
2107 if (NStatus != NDIS_STATUS_SUCCESS) {
2108 DBGPRINT(RT_DEBUG_TRACE,
2109 ("%s() allocate memory failed \n", __func__));
2110 goto END_OF_MEASURE_REQ;
2114 while ((thisChar = strsep((char **)&arg, "-")) != NULL) {
2117 Aid = (u8)simple_strtol(thisChar, 0, 16);
2120 case 2: /* Measurement Request Type. */
2121 MeasureReqType = simple_strtol(thisChar, 0, 16);
2122 if (MeasureReqType > 3) {
2123 DBGPRINT(RT_DEBUG_ERROR,
2124 ("%s: unknow MeasureReqType(%d)\n",
2125 __func__, MeasureReqType));
2126 goto END_OF_MEASURE_REQ;
2130 case 3: /* Measurement channel. */
2131 MeasureCh = (u8)simple_strtol(thisChar, 0, 16);
2137 DBGPRINT(RT_DEBUG_TRACE,
2138 ("%s::Aid = %d, MeasureReqType=%d MeasureCh=%d\n", __func__,
2139 Aid, MeasureReqType, MeasureCh));
2140 if (!VALID_WCID(Aid)) {
2141 DBGPRINT(RT_DEBUG_ERROR,
2142 ("%s: unknow sta of Aid(%d)\n", __func__, Aid));
2143 goto END_OF_MEASURE_REQ;
2146 MeasureReqMode.word = 0;
2147 MeasureReqMode.field.Enable = 1;
2149 MeasureReqInsert(pAd, MeasureReqToken);
2151 /* build action frame header. */
2152 MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0,
2153 pAd->MacTab.Content[Aid].Addr, pAd->CurrentAddress);
2155 NdisMoveMemory(pOutBuffer, (char *)& ActHdr, sizeof(struct rt_header_802_11));
2156 FrameLen = sizeof(struct rt_header_802_11);
2158 TotalLen = sizeof(struct rt_measure_req_info) + sizeof(struct rt_measure_req);
2160 MakeMeasurementReqFrame(pAd, pOutBuffer, &FrameLen,
2161 sizeof(struct rt_measure_req_info), CATEGORY_RM, RM_BASIC,
2162 MeasureReqToken, MeasureReqMode.word,
2165 MeasureReq.ChNum = MeasureCh;
2166 MeasureReq.MeasureStartTime = cpu2le64(MeasureStartTime);
2167 MeasureReq.MeasureDuration = cpu2le16(2000);
2170 unsigned long TempLen;
2171 MakeOutgoingFrame(pOutBuffer + FrameLen, &TempLen,
2172 sizeof(struct rt_measure_req), &MeasureReq,
2174 FrameLen += TempLen;
2177 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, (u32)FrameLen);
2180 MlmeFreeMemory(pAd, pOutBuffer);
2185 int Set_TpcReq_Proc(struct rt_rtmp_adapter *pAd, char *arg)
2189 u8 TpcReqToken = RandomByte(pAd);
2191 Aid = (u32)simple_strtol(arg, 0, 16);
2193 DBGPRINT(RT_DEBUG_TRACE, ("%s::Aid = %d\n", __func__, Aid));
2194 if (!VALID_WCID(Aid)) {
2195 DBGPRINT(RT_DEBUG_ERROR,
2196 ("%s: unknow sta of Aid(%d)\n", __func__, Aid));
2200 TpcReqInsert(pAd, TpcReqToken);
2202 EnqueueTPCReq(pAd, pAd->MacTab.Content[Aid].Addr, TpcReqToken);