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 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(DOT11_REGULATORY_INFORMATION))
100 /* The regulatory information in Europe */
101 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(DOT11_REGULATORY_INFORMATION))
126 /* The regulatory information in Japan */
127 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(DOT11_REGULATORY_INFORMATION))
264 char RTMP_GetTxPwr(IN PRTMP_ADAPTER pAd, IN HTTRANSMIT_SETTING HTTxMode)
266 typedef struct __TX_PWR_CFG {
280 unsigned long TxPwr[5];
282 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(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(IN PRTMP_ADAPTER pAd)
400 NdisAllocateSpinLock(&pAd->CommonCfg.MeasureReqTabLock);
402 pAd->CommonCfg.pMeasureReqTab =
403 kmalloc(sizeof(MEASURE_REQ_TAB), GFP_ATOMIC);
404 if (pAd->CommonCfg.pMeasureReqTab)
405 NdisZeroMemory(pAd->CommonCfg.pMeasureReqTab,
406 sizeof(MEASURE_REQ_TAB));
408 DBGPRINT(RT_DEBUG_ERROR,
409 ("%s Fail to alloc memory for pAd->CommonCfg.pMeasureReqTab.\n",
415 void MeasureReqTabExit(IN PRTMP_ADAPTER pAd)
417 NdisFreeSpinLock(&pAd->CommonCfg.MeasureReqTabLock);
419 if (pAd->CommonCfg.pMeasureReqTab)
420 kfree(pAd->CommonCfg.pMeasureReqTab);
421 pAd->CommonCfg.pMeasureReqTab = NULL;
426 PMEASURE_REQ_ENTRY MeasureReqLookUp(IN PRTMP_ADAPTER pAd, u8 DialogToken)
429 PMEASURE_REQ_TAB pTab = pAd->CommonCfg.pMeasureReqTab;
430 PMEASURE_REQ_ENTRY pEntry = NULL;
431 PMEASURE_REQ_ENTRY pPrevEntry = NULL;
434 DBGPRINT(RT_DEBUG_ERROR,
435 ("%s: pMeasureReqTab doesn't exist.\n", __func__));
439 RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock);
441 HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(DialogToken);
442 pEntry = pTab->Hash[HashIdx];
445 if (pEntry->DialogToken == DialogToken)
449 pEntry = pEntry->pNext;
453 RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock);
458 PMEASURE_REQ_ENTRY MeasureReqInsert(IN PRTMP_ADAPTER pAd, u8 DialogToken)
461 unsigned long HashIdx;
462 PMEASURE_REQ_TAB pTab = pAd->CommonCfg.pMeasureReqTab;
463 PMEASURE_REQ_ENTRY pEntry = NULL, pCurrEntry;
467 DBGPRINT(RT_DEBUG_ERROR,
468 ("%s: pMeasureReqTab doesn't exist.\n", __func__));
472 pEntry = MeasureReqLookUp(pAd, DialogToken);
473 if (pEntry == NULL) {
474 RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock);
475 for (i = 0; i < MAX_MEASURE_REQ_TAB_SIZE; i++) {
476 NdisGetSystemUpTime(&Now);
477 pEntry = &pTab->Content[i];
479 if ((pEntry->Valid == TRUE)
480 && RTMP_TIME_AFTER((unsigned long)Now,
481 (unsigned long)(pEntry->
485 PMEASURE_REQ_ENTRY pPrevEntry = NULL;
486 unsigned long HashIdx =
487 MQ_DIALOGTOKEN_HASH_INDEX(pEntry->
489 PMEASURE_REQ_ENTRY pProbeEntry =
492 /* update Hash list */
494 if (pProbeEntry == pEntry) {
495 if (pPrevEntry == NULL) {
496 pTab->Hash[HashIdx] =
505 pPrevEntry = pProbeEntry;
506 pProbeEntry = pProbeEntry->pNext;
507 } while (pProbeEntry);
509 NdisZeroMemory(pEntry,
510 sizeof(MEASURE_REQ_ENTRY));
516 if (pEntry->Valid == FALSE)
520 if (i < MAX_MEASURE_REQ_TAB_SIZE) {
521 NdisGetSystemUpTime(&Now);
522 pEntry->lastTime = Now;
523 pEntry->Valid = TRUE;
524 pEntry->DialogToken = DialogToken;
528 DBGPRINT(RT_DEBUG_ERROR,
529 ("%s: pMeasureReqTab tab full.\n", __func__));
532 /* add this Neighbor entry into HASH table */
534 HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(DialogToken);
535 if (pTab->Hash[HashIdx] == NULL) {
536 pTab->Hash[HashIdx] = pEntry;
538 pCurrEntry = pTab->Hash[HashIdx];
539 while (pCurrEntry->pNext != NULL)
540 pCurrEntry = pCurrEntry->pNext;
541 pCurrEntry->pNext = pEntry;
545 RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock);
551 void MeasureReqDelete(IN PRTMP_ADAPTER pAd, u8 DialogToken)
553 PMEASURE_REQ_TAB pTab = pAd->CommonCfg.pMeasureReqTab;
554 PMEASURE_REQ_ENTRY pEntry = NULL;
557 DBGPRINT(RT_DEBUG_ERROR,
558 ("%s: pMeasureReqTab doesn't exist.\n", __func__));
561 /* if empty, return */
562 if (pTab->Size == 0) {
563 DBGPRINT(RT_DEBUG_ERROR, ("pMeasureReqTab empty.\n"));
567 pEntry = MeasureReqLookUp(pAd, DialogToken);
568 if (pEntry != NULL) {
569 PMEASURE_REQ_ENTRY pPrevEntry = NULL;
570 unsigned long HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken);
571 PMEASURE_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx];
573 RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock);
574 /* update Hash list */
576 if (pProbeEntry == pEntry) {
577 if (pPrevEntry == NULL) {
578 pTab->Hash[HashIdx] = pEntry->pNext;
580 pPrevEntry->pNext = pEntry->pNext;
585 pPrevEntry = pProbeEntry;
586 pProbeEntry = pProbeEntry->pNext;
587 } while (pProbeEntry);
589 NdisZeroMemory(pEntry, sizeof(MEASURE_REQ_ENTRY));
592 RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock);
598 void TpcReqTabInit(IN PRTMP_ADAPTER pAd)
600 NdisAllocateSpinLock(&pAd->CommonCfg.TpcReqTabLock);
602 pAd->CommonCfg.pTpcReqTab = kmalloc(sizeof(TPC_REQ_TAB), GFP_ATOMIC);
603 if (pAd->CommonCfg.pTpcReqTab)
604 NdisZeroMemory(pAd->CommonCfg.pTpcReqTab, sizeof(TPC_REQ_TAB));
606 DBGPRINT(RT_DEBUG_ERROR,
607 ("%s Fail to alloc memory for pAd->CommonCfg.pTpcReqTab.\n",
613 void TpcReqTabExit(IN PRTMP_ADAPTER pAd)
615 NdisFreeSpinLock(&pAd->CommonCfg.TpcReqTabLock);
617 if (pAd->CommonCfg.pTpcReqTab)
618 kfree(pAd->CommonCfg.pTpcReqTab);
619 pAd->CommonCfg.pTpcReqTab = NULL;
624 static PTPC_REQ_ENTRY TpcReqLookUp(IN PRTMP_ADAPTER pAd, u8 DialogToken)
627 PTPC_REQ_TAB pTab = pAd->CommonCfg.pTpcReqTab;
628 PTPC_REQ_ENTRY pEntry = NULL;
629 PTPC_REQ_ENTRY pPrevEntry = NULL;
632 DBGPRINT(RT_DEBUG_ERROR,
633 ("%s: pTpcReqTab doesn't exist.\n", __func__));
637 RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock);
639 HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(DialogToken);
640 pEntry = pTab->Hash[HashIdx];
643 if (pEntry->DialogToken == DialogToken)
647 pEntry = pEntry->pNext;
651 RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock);
656 static PTPC_REQ_ENTRY TpcReqInsert(IN PRTMP_ADAPTER pAd, u8 DialogToken)
659 unsigned long HashIdx;
660 PTPC_REQ_TAB pTab = pAd->CommonCfg.pTpcReqTab;
661 PTPC_REQ_ENTRY pEntry = NULL, pCurrEntry;
665 DBGPRINT(RT_DEBUG_ERROR,
666 ("%s: pTpcReqTab doesn't exist.\n", __func__));
670 pEntry = TpcReqLookUp(pAd, DialogToken);
671 if (pEntry == NULL) {
672 RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock);
673 for (i = 0; i < MAX_TPC_REQ_TAB_SIZE; i++) {
674 NdisGetSystemUpTime(&Now);
675 pEntry = &pTab->Content[i];
677 if ((pEntry->Valid == TRUE)
678 && RTMP_TIME_AFTER((unsigned long)Now,
679 (unsigned long)(pEntry->
683 PTPC_REQ_ENTRY pPrevEntry = NULL;
684 unsigned long HashIdx =
685 TPC_DIALOGTOKEN_HASH_INDEX(pEntry->
687 PTPC_REQ_ENTRY pProbeEntry =
690 /* update Hash list */
692 if (pProbeEntry == pEntry) {
693 if (pPrevEntry == NULL) {
694 pTab->Hash[HashIdx] =
703 pPrevEntry = pProbeEntry;
704 pProbeEntry = pProbeEntry->pNext;
705 } while (pProbeEntry);
707 NdisZeroMemory(pEntry, sizeof(TPC_REQ_ENTRY));
713 if (pEntry->Valid == FALSE)
717 if (i < MAX_TPC_REQ_TAB_SIZE) {
718 NdisGetSystemUpTime(&Now);
719 pEntry->lastTime = Now;
720 pEntry->Valid = TRUE;
721 pEntry->DialogToken = DialogToken;
725 DBGPRINT(RT_DEBUG_ERROR,
726 ("%s: pTpcReqTab tab full.\n", __func__));
729 /* add this Neighbor entry into HASH table */
731 HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(DialogToken);
732 if (pTab->Hash[HashIdx] == NULL) {
733 pTab->Hash[HashIdx] = pEntry;
735 pCurrEntry = pTab->Hash[HashIdx];
736 while (pCurrEntry->pNext != NULL)
737 pCurrEntry = pCurrEntry->pNext;
738 pCurrEntry->pNext = pEntry;
742 RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock);
748 static void TpcReqDelete(IN PRTMP_ADAPTER pAd, u8 DialogToken)
750 PTPC_REQ_TAB pTab = pAd->CommonCfg.pTpcReqTab;
751 PTPC_REQ_ENTRY pEntry = NULL;
754 DBGPRINT(RT_DEBUG_ERROR,
755 ("%s: pTpcReqTab doesn't exist.\n", __func__));
758 /* if empty, return */
759 if (pTab->Size == 0) {
760 DBGPRINT(RT_DEBUG_ERROR, ("pTpcReqTab empty.\n"));
764 pEntry = TpcReqLookUp(pAd, DialogToken);
765 if (pEntry != NULL) {
766 PTPC_REQ_ENTRY pPrevEntry = NULL;
767 unsigned long HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken);
768 PTPC_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx];
770 RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock);
771 /* update Hash list */
773 if (pProbeEntry == pEntry) {
774 if (pPrevEntry == NULL) {
775 pTab->Hash[HashIdx] = pEntry->pNext;
777 pPrevEntry->pNext = pEntry->pNext;
782 pPrevEntry = pProbeEntry;
783 pProbeEntry = pProbeEntry->pNext;
784 } while (pProbeEntry);
786 NdisZeroMemory(pEntry, sizeof(TPC_REQ_ENTRY));
789 RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock);
796 ==========================================================================
798 Get Current TimeS tamp.
802 Return : Current Time Stamp.
803 ==========================================================================
805 static u64 GetCurrentTimeStamp(IN PRTMP_ADAPTER pAd)
807 /* get current time stamp. */
812 ==========================================================================
814 Get Current Transmit Power.
818 Return : Current Time Stamp.
819 ==========================================================================
821 static u8 GetCurTxPwr(IN PRTMP_ADAPTER pAd, u8 Wcid)
823 return 16; /* 16 dBm */
827 ==========================================================================
829 Get Current Transmit Power.
833 Return : Current Time Stamp.
834 ==========================================================================
836 void InsertChannelRepIE(IN PRTMP_ADAPTER pAd,
838 unsigned long *pFrameLen,
839 char *pCountry, u8 RegulatoryClass)
841 unsigned long TempLen;
843 u8 IEId = IE_AP_CHANNEL_REPORT;
844 u8 *pChListPtr = NULL;
847 if (strncmp(pCountry, "US", 2) == 0) {
848 if (RegulatoryClass >= USA_REGULATORY_INFO_SIZE) {
849 DBGPRINT(RT_DEBUG_ERROR,
850 ("%s: USA Unknow Requlatory class (%d)\n",
851 __func__, RegulatoryClass));
856 USARegulatoryInfo[RegulatoryClass].ChannelSet.
859 USARegulatoryInfo[RegulatoryClass].ChannelSet.ChannelList;
860 } else if (strncmp(pCountry, "JP", 2) == 0) {
861 if (RegulatoryClass >= JP_REGULATORY_INFO_SIZE) {
862 DBGPRINT(RT_DEBUG_ERROR,
863 ("%s: JP Unknow Requlatory class (%d)\n",
864 __func__, RegulatoryClass));
869 JapanRegulatoryInfo[RegulatoryClass].ChannelSet.
872 JapanRegulatoryInfo[RegulatoryClass].ChannelSet.ChannelList;
874 DBGPRINT(RT_DEBUG_ERROR, ("%s: Unknow Country (%s)\n",
875 __func__, pCountry));
879 MakeOutgoingFrame(pFrameBuf, &TempLen,
883 Len - 1, pChListPtr, END_OF_ARGS);
885 *pFrameLen = *pFrameLen + TempLen;
891 ==========================================================================
893 Insert Dialog Token into frame.
896 1. frame buffer pointer.
901 ==========================================================================
903 void InsertDialogToken(IN PRTMP_ADAPTER pAd,
905 unsigned long *pFrameLen, u8 DialogToken)
907 unsigned long TempLen;
908 MakeOutgoingFrame(pFrameBuf, &TempLen, 1, &DialogToken, END_OF_ARGS);
910 *pFrameLen = *pFrameLen + TempLen;
916 ==========================================================================
918 Insert TPC Request IE into frame.
921 1. frame buffer pointer.
925 ==========================================================================
927 static void InsertTpcReqIE(IN PRTMP_ADAPTER pAd,
928 u8 *pFrameBuf, unsigned long *pFrameLen)
930 unsigned long TempLen;
931 unsigned long Len = 0;
932 u8 ElementID = IE_TPC_REQUEST;
934 MakeOutgoingFrame(pFrameBuf, &TempLen,
935 1, &ElementID, 1, &Len, END_OF_ARGS);
937 *pFrameLen = *pFrameLen + TempLen;
943 ==========================================================================
945 Insert TPC Report IE into frame.
948 1. frame buffer pointer.
954 ==========================================================================
956 void InsertTpcReportIE(IN PRTMP_ADAPTER pAd,
958 unsigned long *pFrameLen,
959 u8 TxPwr, u8 LinkMargin)
961 unsigned long TempLen;
962 unsigned long Len = sizeof(TPC_REPORT_INFO);
963 u8 ElementID = IE_TPC_REPORT;
964 TPC_REPORT_INFO TpcReportIE;
966 TpcReportIE.TxPwr = TxPwr;
967 TpcReportIE.LinkMargin = LinkMargin;
969 MakeOutgoingFrame(pFrameBuf, &TempLen,
971 1, &Len, Len, &TpcReportIE, END_OF_ARGS);
973 *pFrameLen = *pFrameLen + TempLen;
979 ==========================================================================
981 Insert Channel Switch Announcement IE into frame.
984 1. frame buffer pointer.
986 3. channel switch announcement mode.
987 4. new selected channel.
988 5. channel switch announcement count.
991 ==========================================================================
993 static void InsertChSwAnnIE(IN PRTMP_ADAPTER pAd,
995 unsigned long *pFrameLen,
997 u8 NewChannel, u8 ChSwCnt)
999 unsigned long TempLen;
1000 unsigned long Len = sizeof(CH_SW_ANN_INFO);
1001 u8 ElementID = IE_CHANNEL_SWITCH_ANNOUNCEMENT;
1002 CH_SW_ANN_INFO ChSwAnnIE;
1004 ChSwAnnIE.ChSwMode = ChSwMode;
1005 ChSwAnnIE.Channel = NewChannel;
1006 ChSwAnnIE.ChSwCnt = ChSwCnt;
1008 MakeOutgoingFrame(pFrameBuf, &TempLen,
1009 1, &ElementID, 1, &Len, Len, &ChSwAnnIE, END_OF_ARGS);
1011 *pFrameLen = *pFrameLen + TempLen;
1017 ==========================================================================
1019 Insert Measure Request IE into frame.
1022 1. frame buffer pointer.
1025 4. Measure Request Mode.
1026 5. Measure Request Type.
1028 7. Measure Start time.
1029 8. Measure Duration.
1032 ==========================================================================
1034 static void InsertMeasureReqIE(IN PRTMP_ADAPTER pAd,
1036 unsigned long *pFrameLen,
1037 u8 Len, IN PMEASURE_REQ_INFO pMeasureReqIE)
1039 unsigned long TempLen;
1040 u8 ElementID = IE_MEASUREMENT_REQUEST;
1042 MakeOutgoingFrame(pFrameBuf, &TempLen,
1045 sizeof(MEASURE_REQ_INFO), pMeasureReqIE, END_OF_ARGS);
1047 *pFrameLen = *pFrameLen + TempLen;
1053 ==========================================================================
1055 Insert Measure Report IE into frame.
1058 1. frame buffer pointer.
1061 4. Measure Request Mode.
1062 5. Measure Request Type.
1063 6. Length of Report Infomation
1064 7. Pointer of Report Infomation Buffer.
1067 ==========================================================================
1069 static void InsertMeasureReportIE(IN PRTMP_ADAPTER pAd,
1071 unsigned long *pFrameLen,
1072 IN PMEASURE_REPORT_INFO pMeasureReportIE,
1073 u8 ReportLnfoLen, u8 *pReportInfo)
1075 unsigned long TempLen;
1077 u8 ElementID = IE_MEASUREMENT_REPORT;
1079 Len = sizeof(MEASURE_REPORT_INFO) + ReportLnfoLen;
1081 MakeOutgoingFrame(pFrameBuf, &TempLen,
1083 1, &Len, Len, pMeasureReportIE, END_OF_ARGS);
1085 *pFrameLen = *pFrameLen + TempLen;
1087 if ((ReportLnfoLen > 0) && (pReportInfo != NULL)) {
1088 MakeOutgoingFrame(pFrameBuf + *pFrameLen, &TempLen,
1089 ReportLnfoLen, pReportInfo, END_OF_ARGS);
1091 *pFrameLen = *pFrameLen + TempLen;
1097 ==========================================================================
1099 Prepare Measurement request action frame and enqueue it into
1100 management queue waiting for transmition.
1103 1. the destination mac address of the frame.
1106 ==========================================================================
1108 void MakeMeasurementReqFrame(IN PRTMP_ADAPTER pAd,
1110 unsigned long *pFrameLen,
1116 u8 MeasureReqType, u8 NumOfRepetitions)
1118 unsigned long TempLen;
1119 MEASURE_REQ_INFO MeasureReqIE;
1121 InsertActField(pAd, (pOutBuffer + *pFrameLen), pFrameLen, Category,
1124 /* fill Dialog Token */
1125 InsertDialogToken(pAd, (pOutBuffer + *pFrameLen), pFrameLen,
1128 /* fill Number of repetitions. */
1129 if (Category == CATEGORY_RM) {
1130 MakeOutgoingFrame((pOutBuffer + *pFrameLen), &TempLen,
1131 2, &NumOfRepetitions, END_OF_ARGS);
1133 *pFrameLen += TempLen;
1135 /* prepare Measurement IE. */
1136 NdisZeroMemory(&MeasureReqIE, sizeof(MEASURE_REQ_INFO));
1137 MeasureReqIE.Token = MeasureToken;
1138 MeasureReqIE.ReqMode.word = MeasureReqMode;
1139 MeasureReqIE.ReqType = MeasureReqType;
1140 InsertMeasureReqIE(pAd, (pOutBuffer + *pFrameLen), pFrameLen,
1141 TotalLen, &MeasureReqIE);
1147 ==========================================================================
1149 Prepare Measurement report action frame and enqueue it into
1150 management queue waiting for transmition.
1153 1. the destination mac address of the frame.
1156 ==========================================================================
1158 void EnqueueMeasurementRep(IN PRTMP_ADAPTER pAd,
1164 u8 ReportInfoLen, u8 *pReportInfo)
1166 u8 *pOutBuffer = NULL;
1168 unsigned long FrameLen;
1169 HEADER_802_11 ActHdr;
1170 MEASURE_REPORT_INFO MeasureRepIE;
1172 /* build action frame header. */
1173 MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
1174 pAd->CurrentAddress);
1176 NStatus = MlmeAllocateMemory(pAd, (void *)& pOutBuffer); /*Get an unused nonpaged memory */
1177 if (NStatus != NDIS_STATUS_SUCCESS) {
1178 DBGPRINT(RT_DEBUG_TRACE,
1179 ("%s() allocate memory failed \n", __func__));
1182 NdisMoveMemory(pOutBuffer, (char *)& ActHdr, sizeof(HEADER_802_11));
1183 FrameLen = sizeof(HEADER_802_11);
1185 InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen,
1186 CATEGORY_SPECTRUM, SPEC_MRP);
1188 /* fill Dialog Token */
1189 InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken);
1191 /* prepare Measurement IE. */
1192 NdisZeroMemory(&MeasureRepIE, sizeof(MEASURE_REPORT_INFO));
1193 MeasureRepIE.Token = MeasureToken;
1194 MeasureRepIE.ReportMode = MeasureReqMode;
1195 MeasureRepIE.ReportType = MeasureReqType;
1196 InsertMeasureReportIE(pAd, (pOutBuffer + FrameLen), &FrameLen,
1197 &MeasureRepIE, ReportInfoLen, pReportInfo);
1199 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1200 MlmeFreeMemory(pAd, pOutBuffer);
1206 ==========================================================================
1208 Prepare TPC Request action frame and enqueue it into
1209 management queue waiting for transmition.
1212 1. the destination mac address of the frame.
1215 ==========================================================================
1217 void EnqueueTPCReq(IN PRTMP_ADAPTER pAd, u8 *pDA, u8 DialogToken)
1219 u8 *pOutBuffer = NULL;
1221 unsigned long FrameLen;
1223 HEADER_802_11 ActHdr;
1225 /* build action frame header. */
1226 MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
1227 pAd->CurrentAddress);
1229 NStatus = MlmeAllocateMemory(pAd, (void *)& pOutBuffer); /*Get an unused nonpaged memory */
1230 if (NStatus != NDIS_STATUS_SUCCESS) {
1231 DBGPRINT(RT_DEBUG_TRACE,
1232 ("%s() allocate memory failed \n", __func__));
1235 NdisMoveMemory(pOutBuffer, (char *)& ActHdr, sizeof(HEADER_802_11));
1236 FrameLen = sizeof(HEADER_802_11);
1238 InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen,
1239 CATEGORY_SPECTRUM, SPEC_TPCRQ);
1241 /* fill Dialog Token */
1242 InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken);
1244 /* Insert TPC Request IE. */
1245 InsertTpcReqIE(pAd, (pOutBuffer + FrameLen), &FrameLen);
1247 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1248 MlmeFreeMemory(pAd, pOutBuffer);
1254 ==========================================================================
1256 Prepare TPC Report action frame and enqueue it into
1257 management queue waiting for transmition.
1260 1. the destination mac address of the frame.
1263 ==========================================================================
1265 void EnqueueTPCRep(IN PRTMP_ADAPTER pAd,
1267 u8 DialogToken, u8 TxPwr, u8 LinkMargin)
1269 u8 *pOutBuffer = NULL;
1271 unsigned long FrameLen;
1273 HEADER_802_11 ActHdr;
1275 /* build action frame header. */
1276 MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
1277 pAd->CurrentAddress);
1279 NStatus = MlmeAllocateMemory(pAd, (void *)& pOutBuffer); /*Get an unused nonpaged memory */
1280 if (NStatus != NDIS_STATUS_SUCCESS) {
1281 DBGPRINT(RT_DEBUG_TRACE,
1282 ("%s() allocate memory failed \n", __func__));
1285 NdisMoveMemory(pOutBuffer, (char *)& ActHdr, sizeof(HEADER_802_11));
1286 FrameLen = sizeof(HEADER_802_11);
1288 InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen,
1289 CATEGORY_SPECTRUM, SPEC_TPCRP);
1291 /* fill Dialog Token */
1292 InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken);
1294 /* Insert TPC Request IE. */
1295 InsertTpcReportIE(pAd, (pOutBuffer + FrameLen), &FrameLen, TxPwr,
1298 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1299 MlmeFreeMemory(pAd, pOutBuffer);
1305 ==========================================================================
1307 Prepare Channel Switch Announcement action frame and enqueue it into
1308 management queue waiting for transmition.
1311 1. the destination mac address of the frame.
1312 2. Channel switch announcement mode.
1313 2. a New selected channel.
1316 ==========================================================================
1318 void EnqueueChSwAnn(IN PRTMP_ADAPTER pAd,
1319 u8 *pDA, u8 ChSwMode, u8 NewCh)
1321 u8 *pOutBuffer = NULL;
1323 unsigned long FrameLen;
1325 HEADER_802_11 ActHdr;
1327 /* build action frame header. */
1328 MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
1329 pAd->CurrentAddress);
1331 NStatus = MlmeAllocateMemory(pAd, (void *)& pOutBuffer); /*Get an unused nonpaged memory */
1332 if (NStatus != NDIS_STATUS_SUCCESS) {
1333 DBGPRINT(RT_DEBUG_TRACE,
1334 ("%s() allocate memory failed \n", __func__));
1337 NdisMoveMemory(pOutBuffer, (char *)& ActHdr, sizeof(HEADER_802_11));
1338 FrameLen = sizeof(HEADER_802_11);
1340 InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen,
1341 CATEGORY_SPECTRUM, SPEC_CHANNEL_SWITCH);
1343 InsertChSwAnnIE(pAd, (pOutBuffer + FrameLen), &FrameLen, ChSwMode,
1346 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1347 MlmeFreeMemory(pAd, pOutBuffer);
1352 static BOOLEAN DfsRequirementCheck(IN PRTMP_ADAPTER pAd, u8 Channel)
1354 BOOLEAN Result = FALSE;
1358 /* check DFS procedure is running. */
1359 /* make sure DFS procedure won't start twice. */
1360 if (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE) {
1364 /* check the new channel carried from Channel Switch Announcemnet is valid. */
1365 for (i = 0; i < pAd->ChannelListNum; i++) {
1366 if ((Channel == pAd->ChannelList[i].Channel)
1367 && (pAd->ChannelList[i].RemainingTimeForUse == 0)) {
1368 /* found radar signal in the channel. the channel can't use at least for 30 minutes. */
1369 pAd->ChannelList[i].RemainingTimeForUse = 1800; /*30 min = 1800 sec */
1379 void NotifyChSwAnnToPeerAPs(IN PRTMP_ADAPTER pAd,
1381 u8 *pTA, u8 ChSwMode, u8 Channel)
1385 static void StartDFSProcedure(IN PRTMP_ADAPTER pAd,
1386 u8 Channel, u8 ChSwMode)
1388 /* start DFS procedure */
1389 pAd->CommonCfg.Channel = Channel;
1391 N_ChannelCheck(pAd);
1393 pAd->CommonCfg.RadarDetect.RDMode = RD_SWITCHING_MODE;
1394 pAd->CommonCfg.RadarDetect.CSCount = 0;
1398 ==========================================================================
1400 Channel Switch Announcement action frame sanity check.
1403 1. MLME message containing the received frame
1405 3. Channel switch announcement infomation buffer.
1408 ==========================================================================
1412 Channel Switch Announcement IE.
1413 +----+-----+-----------+------------+-----------+
1414 | ID | Len |Ch Sw Mode | New Ch Num | Ch Sw Cnt |
1415 +----+-----+-----------+------------+-----------+
1418 static BOOLEAN PeerChSwAnnSanity(IN PRTMP_ADAPTER pAd,
1420 unsigned long MsgLen,
1421 OUT PCH_SW_ANN_INFO pChSwAnnInfo)
1423 PFRAME_802_11 Fr = (PFRAME_802_11) pMsg;
1424 u8 *pFramePtr = Fr->Octet;
1425 BOOLEAN result = FALSE;
1426 PEID_STRUCT eid_ptr;
1428 /* skip 802.11 header. */
1429 MsgLen -= sizeof(HEADER_802_11);
1431 /* skip category and action code. */
1435 if (pChSwAnnInfo == NULL)
1438 eid_ptr = (PEID_STRUCT) pFramePtr;
1439 while (((u8 *) eid_ptr + eid_ptr->Len + 1) <
1440 ((u8 *)pFramePtr + MsgLen)) {
1441 switch (eid_ptr->Eid) {
1442 case IE_CHANNEL_SWITCH_ANNOUNCEMENT:
1443 NdisMoveMemory(&pChSwAnnInfo->ChSwMode, eid_ptr->Octet,
1445 NdisMoveMemory(&pChSwAnnInfo->Channel,
1446 eid_ptr->Octet + 1, 1);
1447 NdisMoveMemory(&pChSwAnnInfo->ChSwCnt,
1448 eid_ptr->Octet + 2, 1);
1456 eid_ptr = (PEID_STRUCT) ((u8 *) eid_ptr + 2 + eid_ptr->Len);
1463 ==========================================================================
1465 Measurement request action frame sanity check.
1468 1. MLME message containing the received frame
1470 3. Measurement request infomation buffer.
1473 ==========================================================================
1475 static BOOLEAN PeerMeasureReqSanity(IN PRTMP_ADAPTER pAd,
1477 unsigned long MsgLen,
1479 OUT PMEASURE_REQ_INFO pMeasureReqInfo,
1480 OUT PMEASURE_REQ pMeasureReq)
1482 PFRAME_802_11 Fr = (PFRAME_802_11) pMsg;
1483 u8 *pFramePtr = Fr->Octet;
1484 BOOLEAN result = FALSE;
1485 PEID_STRUCT eid_ptr;
1487 u64 MeasureStartTime;
1488 u16 MeasureDuration;
1490 /* skip 802.11 header. */
1491 MsgLen -= sizeof(HEADER_802_11);
1493 /* skip category and action code. */
1497 if (pMeasureReqInfo == NULL)
1500 NdisMoveMemory(pDialogToken, pFramePtr, 1);
1504 eid_ptr = (PEID_STRUCT) pFramePtr;
1505 while (((u8 *) eid_ptr + eid_ptr->Len + 1) <
1506 ((u8 *)pFramePtr + MsgLen)) {
1507 switch (eid_ptr->Eid) {
1508 case IE_MEASUREMENT_REQUEST:
1509 NdisMoveMemory(&pMeasureReqInfo->Token, eid_ptr->Octet,
1511 NdisMoveMemory(&pMeasureReqInfo->ReqMode.word,
1512 eid_ptr->Octet + 1, 1);
1513 NdisMoveMemory(&pMeasureReqInfo->ReqType,
1514 eid_ptr->Octet + 2, 1);
1515 ptr = (u8 *)(eid_ptr->Octet + 3);
1516 NdisMoveMemory(&pMeasureReq->ChNum, ptr, 1);
1517 NdisMoveMemory(&MeasureStartTime, ptr + 1, 8);
1518 pMeasureReq->MeasureStartTime =
1519 SWAP64(MeasureStartTime);
1520 NdisMoveMemory(&MeasureDuration, ptr + 9, 2);
1521 pMeasureReq->MeasureDuration = SWAP16(MeasureDuration);
1529 eid_ptr = (PEID_STRUCT) ((u8 *) eid_ptr + 2 + eid_ptr->Len);
1536 ==========================================================================
1538 Measurement report action frame sanity check.
1541 1. MLME message containing the received frame
1543 3. Measurement report infomation buffer.
1544 4. basic report infomation buffer.
1547 ==========================================================================
1551 Measurement Report IE.
1552 +----+-----+-------+-------------+--------------+----------------+
1553 | ID | Len | Token | Report Mode | Measure Type | Measure Report |
1554 +----+-----+-------+-------------+--------------+----------------+
1558 +--------+------------+----------+-----+
1559 | Ch Num | Start Time | Duration | Map |
1560 +--------+------------+----------+-----+
1563 Map Field Bit Format.
1564 +-----+---------------+---------------------+-------+------------+----------+
1565 | Bss | OFDM Preamble | Unidentified signal | Radar | Unmeasured | Reserved |
1566 +-----+---------------+---------------------+-------+------------+----------+
1569 static BOOLEAN PeerMeasureReportSanity(IN PRTMP_ADAPTER pAd,
1571 unsigned long MsgLen,
1573 OUT PMEASURE_REPORT_INFO
1577 PFRAME_802_11 Fr = (PFRAME_802_11) pMsg;
1578 u8 *pFramePtr = Fr->Octet;
1579 BOOLEAN result = FALSE;
1580 PEID_STRUCT eid_ptr;
1583 /* skip 802.11 header. */
1584 MsgLen -= sizeof(HEADER_802_11);
1586 /* skip category and action code. */
1590 if (pMeasureReportInfo == NULL)
1593 NdisMoveMemory(pDialogToken, pFramePtr, 1);
1597 eid_ptr = (PEID_STRUCT) pFramePtr;
1598 while (((u8 *) eid_ptr + eid_ptr->Len + 1) <
1599 ((u8 *)pFramePtr + MsgLen)) {
1600 switch (eid_ptr->Eid) {
1601 case IE_MEASUREMENT_REPORT:
1602 NdisMoveMemory(&pMeasureReportInfo->Token,
1604 NdisMoveMemory(&pMeasureReportInfo->ReportMode,
1605 eid_ptr->Octet + 1, 1);
1606 NdisMoveMemory(&pMeasureReportInfo->ReportType,
1607 eid_ptr->Octet + 2, 1);
1608 if (pMeasureReportInfo->ReportType == RM_BASIC) {
1609 PMEASURE_BASIC_REPORT pReport =
1610 (PMEASURE_BASIC_REPORT) pReportBuf;
1611 ptr = (u8 *)(eid_ptr->Octet + 3);
1612 NdisMoveMemory(&pReport->ChNum, ptr, 1);
1613 NdisMoveMemory(&pReport->MeasureStartTime,
1615 NdisMoveMemory(&pReport->MeasureDuration,
1617 NdisMoveMemory(&pReport->Map, ptr + 11, 1);
1619 } else if (pMeasureReportInfo->ReportType == RM_CCA) {
1620 PMEASURE_CCA_REPORT pReport =
1621 (PMEASURE_CCA_REPORT) pReportBuf;
1622 ptr = (u8 *)(eid_ptr->Octet + 3);
1623 NdisMoveMemory(&pReport->ChNum, ptr, 1);
1624 NdisMoveMemory(&pReport->MeasureStartTime,
1626 NdisMoveMemory(&pReport->MeasureDuration,
1628 NdisMoveMemory(&pReport->CCA_Busy_Fraction,
1631 } else if (pMeasureReportInfo->ReportType ==
1633 PMEASURE_RPI_REPORT pReport =
1634 (PMEASURE_RPI_REPORT) pReportBuf;
1635 ptr = (u8 *)(eid_ptr->Octet + 3);
1636 NdisMoveMemory(&pReport->ChNum, ptr, 1);
1637 NdisMoveMemory(&pReport->MeasureStartTime,
1639 NdisMoveMemory(&pReport->MeasureDuration,
1641 NdisMoveMemory(&pReport->RPI_Density, ptr + 11,
1650 eid_ptr = (PEID_STRUCT) ((u8 *) eid_ptr + 2 + eid_ptr->Len);
1657 ==========================================================================
1659 TPC Request action frame sanity check.
1662 1. MLME message containing the received frame
1667 ==========================================================================
1669 static BOOLEAN PeerTpcReqSanity(IN PRTMP_ADAPTER pAd,
1671 unsigned long MsgLen, u8 *pDialogToken)
1673 PFRAME_802_11 Fr = (PFRAME_802_11) pMsg;
1674 u8 *pFramePtr = Fr->Octet;
1675 BOOLEAN result = FALSE;
1676 PEID_STRUCT eid_ptr;
1678 MsgLen -= sizeof(HEADER_802_11);
1680 /* skip category and action code. */
1684 if (pDialogToken == NULL)
1687 NdisMoveMemory(pDialogToken, pFramePtr, 1);
1691 eid_ptr = (PEID_STRUCT) pFramePtr;
1692 while (((u8 *) eid_ptr + eid_ptr->Len + 1) <
1693 ((u8 *)pFramePtr + MsgLen)) {
1694 switch (eid_ptr->Eid) {
1695 case IE_TPC_REQUEST:
1702 eid_ptr = (PEID_STRUCT) ((u8 *) eid_ptr + 2 + eid_ptr->Len);
1709 ==========================================================================
1711 TPC Report action frame sanity check.
1714 1. MLME message containing the received frame
1720 ==========================================================================
1722 static BOOLEAN PeerTpcRepSanity(IN PRTMP_ADAPTER pAd,
1724 unsigned long MsgLen,
1726 OUT PTPC_REPORT_INFO pTpcRepInfo)
1728 PFRAME_802_11 Fr = (PFRAME_802_11) pMsg;
1729 u8 *pFramePtr = Fr->Octet;
1730 BOOLEAN result = FALSE;
1731 PEID_STRUCT eid_ptr;
1733 MsgLen -= sizeof(HEADER_802_11);
1735 /* skip category and action code. */
1739 if (pDialogToken == NULL)
1742 NdisMoveMemory(pDialogToken, pFramePtr, 1);
1746 eid_ptr = (PEID_STRUCT) pFramePtr;
1747 while (((u8 *) eid_ptr + eid_ptr->Len + 1) <
1748 ((u8 *)pFramePtr + MsgLen)) {
1749 switch (eid_ptr->Eid) {
1751 NdisMoveMemory(&pTpcRepInfo->TxPwr, eid_ptr->Octet, 1);
1752 NdisMoveMemory(&pTpcRepInfo->LinkMargin,
1753 eid_ptr->Octet + 1, 1);
1760 eid_ptr = (PEID_STRUCT) ((u8 *) eid_ptr + 2 + eid_ptr->Len);
1767 ==========================================================================
1769 Channel Switch Announcement action frame handler.
1772 Elme - MLME message containing the received frame
1775 ==========================================================================
1777 static void PeerChSwAnnAction(IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM * Elem)
1779 CH_SW_ANN_INFO ChSwAnnInfo;
1780 PFRAME_802_11 pFr = (PFRAME_802_11) Elem->Msg;
1781 u8 index = 0, Channel = 0, NewChannel = 0;
1782 unsigned long Bssidx = 0;
1784 NdisZeroMemory(&ChSwAnnInfo, sizeof(CH_SW_ANN_INFO));
1785 if (!PeerChSwAnnSanity(pAd, Elem->Msg, Elem->MsgLen, &ChSwAnnInfo)) {
1786 DBGPRINT(RT_DEBUG_TRACE,
1787 ("Invalid Channel Switch Action Frame.\n"));
1791 if (pAd->OpMode == OPMODE_STA) {
1793 BssTableSearch(&pAd->ScanTab, pFr->Hdr.Addr3,
1794 pAd->CommonCfg.Channel);
1795 if (Bssidx == BSS_NOT_FOUND) {
1796 DBGPRINT(RT_DEBUG_TRACE,
1797 ("PeerChSwAnnAction - Bssidx is not found\n"));
1801 DBGPRINT(RT_DEBUG_TRACE,
1802 ("\n****Bssidx is %d, Channel = %d\n", index,
1803 pAd->ScanTab.BssEntry[Bssidx].Channel));
1804 hex_dump("SSID", pAd->ScanTab.BssEntry[Bssidx].Bssid, 6);
1806 Channel = pAd->CommonCfg.Channel;
1807 NewChannel = ChSwAnnInfo.Channel;
1809 if ((pAd->CommonCfg.bIEEE80211H == 1) && (NewChannel != 0)
1810 && (Channel != NewChannel)) {
1811 /* Switching to channel 1 can prevent from rescanning the current channel immediately (by auto reconnection). */
1812 /* In addition, clear the MLME queue and the scan table to discard the RX packets and previous scanning results. */
1813 AsicSwitchChannel(pAd, 1, FALSE);
1814 AsicLockChannel(pAd, 1);
1815 LinkDown(pAd, FALSE);
1816 MlmeQueueInit(&pAd->Mlme.Queue);
1817 BssTableInit(&pAd->ScanTab);
1818 RTMPusecDelay(1000000); /* use delay to prevent STA do reassoc */
1820 /* channel sanity check */
1821 for (index = 0; index < pAd->ChannelListNum; index++) {
1822 if (pAd->ChannelList[index].Channel ==
1824 pAd->ScanTab.BssEntry[Bssidx].Channel =
1826 pAd->CommonCfg.Channel = NewChannel;
1827 AsicSwitchChannel(pAd,
1830 AsicLockChannel(pAd,
1831 pAd->CommonCfg.Channel);
1832 DBGPRINT(RT_DEBUG_TRACE,
1833 ("&&&&&&&&&&&&&&&&PeerChSwAnnAction - STA receive channel switch announcement IE (New Channel =%d)\n",
1839 if (index >= pAd->ChannelListNum) {
1840 DBGPRINT_ERR(("&&&&&&&&&&&&&&&&&&&&&&&&&&PeerChSwAnnAction(can not find New Channel=%d in ChannelList[%d]\n", pAd->CommonCfg.Channel, pAd->ChannelListNum));
1849 ==========================================================================
1851 Measurement Request action frame handler.
1854 Elme - MLME message containing the received frame
1857 ==========================================================================
1859 static void PeerMeasureReqAction(IN PRTMP_ADAPTER pAd,
1860 IN MLME_QUEUE_ELEM * Elem)
1862 PFRAME_802_11 pFr = (PFRAME_802_11) Elem->Msg;
1864 MEASURE_REQ_INFO MeasureReqInfo;
1865 MEASURE_REQ MeasureReq;
1866 MEASURE_REPORT_MODE ReportMode;
1868 if (PeerMeasureReqSanity
1869 (pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &MeasureReqInfo,
1871 ReportMode.word = 0;
1872 ReportMode.field.Incapable = 1;
1873 EnqueueMeasurementRep(pAd, pFr->Hdr.Addr2, DialogToken,
1874 MeasureReqInfo.Token, ReportMode.word,
1875 MeasureReqInfo.ReqType, 0, NULL);
1882 ==========================================================================
1884 Measurement Report action frame handler.
1887 Elme - MLME message containing the received frame
1890 ==========================================================================
1892 static void PeerMeasureReportAction(IN PRTMP_ADAPTER pAd,
1893 IN MLME_QUEUE_ELEM * Elem)
1895 MEASURE_REPORT_INFO MeasureReportInfo;
1896 PFRAME_802_11 pFr = (PFRAME_802_11) Elem->Msg;
1898 u8 *pMeasureReportInfo;
1900 /* if (pAd->CommonCfg.bIEEE80211H != TRUE) */
1903 if ((pMeasureReportInfo =
1904 kmalloc(sizeof(MEASURE_RPI_REPORT), GFP_ATOMIC)) == NULL) {
1905 DBGPRINT(RT_DEBUG_ERROR,
1906 ("%s unable to alloc memory for measure report buffer (size=%zu).\n",
1907 __func__, sizeof(MEASURE_RPI_REPORT)));
1911 NdisZeroMemory(&MeasureReportInfo, sizeof(MEASURE_REPORT_INFO));
1912 NdisZeroMemory(pMeasureReportInfo, sizeof(MEASURE_RPI_REPORT));
1913 if (PeerMeasureReportSanity
1914 (pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &MeasureReportInfo,
1915 pMeasureReportInfo)) {
1917 PMEASURE_REQ_ENTRY pEntry = NULL;
1919 /* Not a autonomous measure report. */
1920 /* check the dialog token field. drop it if the dialog token doesn't match. */
1921 if ((DialogToken != 0)
1922 && ((pEntry = MeasureReqLookUp(pAd, DialogToken)) ==
1927 MeasureReqDelete(pAd, pEntry->DialogToken);
1929 if (MeasureReportInfo.ReportType == RM_BASIC) {
1930 PMEASURE_BASIC_REPORT pBasicReport =
1931 (PMEASURE_BASIC_REPORT) pMeasureReportInfo;
1932 if ((pBasicReport->Map.field.Radar)
1934 (DfsRequirementCheck
1935 (pAd, pBasicReport->ChNum) == TRUE)) {
1936 NotifyChSwAnnToPeerAPs(pAd,
1942 StartDFSProcedure(pAd,
1943 pBasicReport->ChNum,
1949 DBGPRINT(RT_DEBUG_TRACE,
1950 ("Invalid Measurement Report Frame.\n"));
1952 kfree(pMeasureReportInfo);
1958 ==========================================================================
1960 TPC Request action frame handler.
1963 Elme - MLME message containing the received frame
1966 ==========================================================================
1968 static void PeerTpcReqAction(IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM * Elem)
1970 PFRAME_802_11 pFr = (PFRAME_802_11) Elem->Msg;
1971 u8 *pFramePtr = pFr->Octet;
1973 u8 TxPwr = GetCurTxPwr(pAd, Elem->Wcid);
1977 /* link margin: Ratio of the received signal power to the minimum desired by the station (STA). The */
1978 /* STA may incorporate rate information and channel conditions, including interference, into its computation */
1979 /* of link margin. */
1981 RealRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0),
1982 ConvertToRssi(pAd, Elem->Rssi1, RSSI_1),
1983 ConvertToRssi(pAd, Elem->Rssi2, RSSI_2));
1985 /* skip Category and action code. */
1989 NdisMoveMemory(&DialogToken, pFramePtr, 1);
1991 LinkMargin = (RealRssi / MIN_RCV_PWR);
1992 if (PeerTpcReqSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken))
1993 EnqueueTPCRep(pAd, pFr->Hdr.Addr2, DialogToken, TxPwr,
2000 ==========================================================================
2002 TPC Report action frame handler.
2005 Elme - MLME message containing the received frame
2008 ==========================================================================
2010 static void PeerTpcRepAction(IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM * Elem)
2013 TPC_REPORT_INFO TpcRepInfo;
2014 PTPC_REQ_ENTRY pEntry = NULL;
2016 NdisZeroMemory(&TpcRepInfo, sizeof(TPC_REPORT_INFO));
2017 if (PeerTpcRepSanity
2018 (pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &TpcRepInfo)) {
2019 if ((pEntry = TpcReqLookUp(pAd, DialogToken)) != NULL) {
2020 TpcReqDelete(pAd, pEntry->DialogToken);
2021 DBGPRINT(RT_DEBUG_TRACE,
2022 ("%s: DialogToken=%x, TxPwr=%d, LinkMargin=%d\n",
2023 __func__, DialogToken, TpcRepInfo.TxPwr,
2024 TpcRepInfo.LinkMargin));
2032 ==========================================================================
2034 Spectrun action frames Handler such as channel switch annoucement,
2035 measurement report, measurement request actions frames.
2038 Elme - MLME message containing the received frame
2041 ==========================================================================
2043 void PeerSpectrumAction(IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM * Elem)
2046 u8 Action = Elem->Msg[LENGTH_802_11 + 1];
2048 if (pAd->CommonCfg.bIEEE80211H != TRUE)
2053 /* current rt2860 unable do such measure specified in Measurement Request. */
2054 /* reject all measurement request. */
2055 PeerMeasureReqAction(pAd, Elem);
2059 PeerMeasureReportAction(pAd, Elem);
2063 PeerTpcReqAction(pAd, Elem);
2067 PeerTpcRepAction(pAd, Elem);
2070 case SPEC_CHANNEL_SWITCH:
2072 PeerChSwAnnAction(pAd, Elem);
2080 ==========================================================================
2086 ==========================================================================
2088 int Set_MeasureReq_Proc(IN PRTMP_ADAPTER pAd, char *arg)
2094 MEASURE_REQ_MODE MeasureReqMode;
2095 u8 MeasureReqToken = RandomByte(pAd);
2096 u8 MeasureReqType = RM_BASIC;
2098 u64 MeasureStartTime = GetCurrentTimeStamp(pAd);
2099 MEASURE_REQ MeasureReq;
2102 HEADER_802_11 ActHdr;
2103 u8 *pOutBuffer = NULL;
2105 unsigned long FrameLen;
2107 NStatus = MlmeAllocateMemory(pAd, (void *)& pOutBuffer); /*Get an unused nonpaged memory */
2108 if (NStatus != NDIS_STATUS_SUCCESS) {
2109 DBGPRINT(RT_DEBUG_TRACE,
2110 ("%s() allocate memory failed \n", __func__));
2111 goto END_OF_MEASURE_REQ;
2115 while ((thisChar = strsep((char **)&arg, "-")) != NULL) {
2118 Aid = (u8)simple_strtol(thisChar, 0, 16);
2121 case 2: /* Measurement Request Type. */
2122 MeasureReqType = simple_strtol(thisChar, 0, 16);
2123 if (MeasureReqType > 3) {
2124 DBGPRINT(RT_DEBUG_ERROR,
2125 ("%s: unknow MeasureReqType(%d)\n",
2126 __func__, MeasureReqType));
2127 goto END_OF_MEASURE_REQ;
2131 case 3: /* Measurement channel. */
2132 MeasureCh = (u8)simple_strtol(thisChar, 0, 16);
2138 DBGPRINT(RT_DEBUG_TRACE,
2139 ("%s::Aid = %d, MeasureReqType=%d MeasureCh=%d\n", __func__,
2140 Aid, MeasureReqType, MeasureCh));
2141 if (!VALID_WCID(Aid)) {
2142 DBGPRINT(RT_DEBUG_ERROR,
2143 ("%s: unknow sta of Aid(%d)\n", __func__, Aid));
2144 goto END_OF_MEASURE_REQ;
2147 MeasureReqMode.word = 0;
2148 MeasureReqMode.field.Enable = 1;
2150 MeasureReqInsert(pAd, MeasureReqToken);
2152 /* build action frame header. */
2153 MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0,
2154 pAd->MacTab.Content[Aid].Addr, pAd->CurrentAddress);
2156 NdisMoveMemory(pOutBuffer, (char *)& ActHdr, sizeof(HEADER_802_11));
2157 FrameLen = sizeof(HEADER_802_11);
2159 TotalLen = sizeof(MEASURE_REQ_INFO) + sizeof(MEASURE_REQ);
2161 MakeMeasurementReqFrame(pAd, pOutBuffer, &FrameLen,
2162 sizeof(MEASURE_REQ_INFO), CATEGORY_RM, RM_BASIC,
2163 MeasureReqToken, MeasureReqMode.word,
2166 MeasureReq.ChNum = MeasureCh;
2167 MeasureReq.MeasureStartTime = cpu2le64(MeasureStartTime);
2168 MeasureReq.MeasureDuration = cpu2le16(2000);
2171 unsigned long TempLen;
2172 MakeOutgoingFrame(pOutBuffer + FrameLen, &TempLen,
2173 sizeof(MEASURE_REQ), &MeasureReq,
2175 FrameLen += TempLen;
2178 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, (u32)FrameLen);
2181 MlmeFreeMemory(pAd, pOutBuffer);
2186 int Set_TpcReq_Proc(IN PRTMP_ADAPTER pAd, char *arg)
2190 u8 TpcReqToken = RandomByte(pAd);
2192 Aid = (u32)simple_strtol(arg, 0, 16);
2194 DBGPRINT(RT_DEBUG_TRACE, ("%s::Aid = %d\n", __func__, Aid));
2195 if (!VALID_WCID(Aid)) {
2196 DBGPRINT(RT_DEBUG_ERROR,
2197 ("%s: unknow sta of Aid(%d)\n", __func__, Aid));
2201 TpcReqInsert(pAd, TpcReqToken);
2203 EnqueueTPCReq(pAd, pAd->MacTab.Content[Aid].Addr, TpcReqToken);