2 *************************************************************************
4 * 5F., No.36, Taiyuan St., Jhubei City,
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
15 * This program is distributed in the hope that it will be useful, *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 * GNU General Public License for more details. *
20 * You should have received a copy of the GNU General Public License *
21 * along with this program; if not, write to the *
22 * Free Software Foundation, Inc., *
23 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
25 *************************************************************************
32 Handle association related requests either from WSTA or from local MLME
36 --------- ---------- ----------------------------------------------
37 Fonchi Wu 2008 created for 802.11h
40 #include "../rt_config.h"
44 /* The regulatory information in the USA (US) */
45 DOT11_REGULATORY_INFORMATION USARegulatoryInfo[] =
47 /* "regulatory class" "number of channels" "Max Tx Pwr" "channel list" */
48 {0, {0, 0, {0}}}, // Invlid entry
49 {1, {4, 16, {36, 40, 44, 48}}},
50 {2, {4, 23, {52, 56, 60, 64}}},
51 {3, {4, 29, {149, 153, 157, 161}}},
52 {4, {11, 23, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}}},
53 {5, {5, 30, {149, 153, 157, 161, 165}}},
54 {6, {10, 14, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}},
55 {7, {10, 27, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}},
56 {8, {5, 17, {11, 13, 15, 17, 19}}},
57 {9, {5, 30, {11, 13, 15, 17, 19}}},
58 {10, {2, 20, {21, 25}}},
59 {11, {2, 33, {21, 25}}},
60 {12, {11, 30, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}}}
62 #define USA_REGULATORY_INFO_SIZE (sizeof(USARegulatoryInfo) / sizeof(DOT11_REGULATORY_INFORMATION))
65 /* The regulatory information in Europe */
66 DOT11_REGULATORY_INFORMATION EuropeRegulatoryInfo[] =
68 /* "regulatory class" "number of channels" "Max Tx Pwr" "channel list" */
69 {0, {0, 0, {0}}}, // Invalid entry
70 {1, {4, 20, {36, 40, 44, 48}}},
71 {2, {4, 20, {52, 56, 60, 64}}},
72 {3, {11, 30, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}}},
73 {4, {13, 20, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}}}
75 #define EU_REGULATORY_INFO_SIZE (sizeof(EuropeRegulatoryInfo) / sizeof(DOT11_REGULATORY_INFORMATION))
78 /* The regulatory information in Japan */
79 DOT11_REGULATORY_INFORMATION JapanRegulatoryInfo[] =
81 /* "regulatory class" "number of channels" "Max Tx Pwr" "channel list" */
82 {0, {0, 0, {0}}}, // Invalid entry
83 {1, {4, 22, {34, 38, 42, 46}}},
84 {2, {3, 24, {8, 12, 16}}},
85 {3, {3, 24, {8, 12, 16}}},
86 {4, {3, 24, {8, 12, 16}}},
87 {5, {3, 24, {8, 12, 16}}},
88 {6, {3, 22, {8, 12, 16}}},
89 {7, {4, 24, {184, 188, 192, 196}}},
90 {8, {4, 24, {184, 188, 192, 196}}},
91 {9, {4, 24, {184, 188, 192, 196}}},
92 {10, {4, 24, {184, 188, 192, 196}}},
93 {11, {4, 22, {184, 188, 192, 196}}},
94 {12, {4, 24, {7, 8, 9, 11}}},
95 {13, {4, 24, {7, 8, 9, 11}}},
96 {14, {4, 24, {7, 8, 9, 11}}},
97 {15, {4, 24, {7, 8, 9, 11}}},
98 {16, {6, 24, {183, 184, 185, 187, 188, 189}}},
99 {17, {6, 24, {183, 184, 185, 187, 188, 189}}},
100 {18, {6, 24, {183, 184, 185, 187, 188, 189}}},
101 {19, {6, 24, {183, 184, 185, 187, 188, 189}}},
102 {20, {6, 17, {183, 184, 185, 187, 188, 189}}},
103 {21, {6, 24, {6, 7, 8, 9, 10, 11}}},
104 {22, {6, 24, {6, 7, 8, 9, 10, 11}}},
105 {23, {6, 24, {6, 7, 8, 9, 10, 11}}},
106 {24, {6, 24, {6, 7, 8, 9, 10, 11}}},
107 {25, {8, 24, {182, 183, 184, 185, 186, 187, 188, 189}}},
108 {26, {8, 24, {182, 183, 184, 185, 186, 187, 188, 189}}},
109 {27, {8, 24, {182, 183, 184, 185, 186, 187, 188, 189}}},
110 {28, {8, 24, {182, 183, 184, 185, 186, 187, 188, 189}}},
111 {29, {8, 17, {182, 183, 184, 185, 186, 187, 188, 189}}},
112 {30, {13, 23, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}}},
114 {32, {4, 22, {52, 56, 60, 64}}}
116 #define JP_REGULATORY_INFO_SIZE (sizeof(JapanRegulatoryInfo) / sizeof(DOT11_REGULATORY_INFORMATION))
120 IN PRTMP_ADAPTER pAd,
121 IN HTTRANSMIT_SETTING HTTxMode)
123 typedef struct __TX_PWR_CFG
141 TX_PWR_CFG TxPwrCfg[] = {
142 {MODE_CCK, 0, 0, 4, 0x000000f0},
143 {MODE_CCK, 1, 0, 0, 0x0000000f},
144 {MODE_CCK, 2, 0, 12, 0x0000f000},
145 {MODE_CCK, 3, 0, 8, 0x00000f00},
147 {MODE_OFDM, 0, 0, 20, 0x00f00000},
148 {MODE_OFDM, 1, 0, 16, 0x000f0000},
149 {MODE_OFDM, 2, 0, 28, 0xf0000000},
150 {MODE_OFDM, 3, 0, 24, 0x0f000000},
151 {MODE_OFDM, 4, 1, 4, 0x000000f0},
152 {MODE_OFDM, 5, 1, 0, 0x0000000f},
153 {MODE_OFDM, 6, 1, 12, 0x0000f000},
154 {MODE_OFDM, 7, 1, 8, 0x00000f00}
155 ,{MODE_HTMIX, 0, 1, 20, 0x00f00000},
156 {MODE_HTMIX, 1, 1, 16, 0x000f0000},
157 {MODE_HTMIX, 2, 1, 28, 0xf0000000},
158 {MODE_HTMIX, 3, 1, 24, 0x0f000000},
159 {MODE_HTMIX, 4, 2, 4, 0x000000f0},
160 {MODE_HTMIX, 5, 2, 0, 0x0000000f},
161 {MODE_HTMIX, 6, 2, 12, 0x0000f000},
162 {MODE_HTMIX, 7, 2, 8, 0x00000f00},
163 {MODE_HTMIX, 8, 2, 20, 0x00f00000},
164 {MODE_HTMIX, 9, 2, 16, 0x000f0000},
165 {MODE_HTMIX, 10, 2, 28, 0xf0000000},
166 {MODE_HTMIX, 11, 2, 24, 0x0f000000},
167 {MODE_HTMIX, 12, 3, 4, 0x000000f0},
168 {MODE_HTMIX, 13, 3, 0, 0x0000000f},
169 {MODE_HTMIX, 14, 3, 12, 0x0000f000},
170 {MODE_HTMIX, 15, 3, 8, 0x00000f00}
172 #define MAX_TXPWR_TAB_SIZE (sizeof(TxPwrCfg) / sizeof(TX_PWR_CFG))
176 /* check Tx Power setting from UI. */
177 if (pAd->CommonCfg.TxPowerPercentage > 90)
179 else if (pAd->CommonCfg.TxPowerPercentage > 60) /* reduce Pwr for 1 dB. */
181 else if (pAd->CommonCfg.TxPowerPercentage > 30) /* reduce Pwr for 3 dB. */
183 else if (pAd->CommonCfg.TxPowerPercentage > 15) /* reduce Pwr for 6 dB. */
185 else if (pAd->CommonCfg.TxPowerPercentage > 9) /* reduce Pwr for 9 dB. */
187 else /* reduce Pwr for 12 dB. */
190 if (pAd->CommonCfg.BBPCurrentBW == BW_40)
192 if (pAd->CommonCfg.CentralChannel > 14)
194 TxPwr[0] = pAd->Tx40MPwrCfgABand[0];
195 TxPwr[1] = pAd->Tx40MPwrCfgABand[1];
196 TxPwr[2] = pAd->Tx40MPwrCfgABand[2];
197 TxPwr[3] = pAd->Tx40MPwrCfgABand[3];
198 TxPwr[4] = pAd->Tx40MPwrCfgABand[4];
202 TxPwr[0] = pAd->Tx40MPwrCfgGBand[0];
203 TxPwr[1] = pAd->Tx40MPwrCfgGBand[1];
204 TxPwr[2] = pAd->Tx40MPwrCfgGBand[2];
205 TxPwr[3] = pAd->Tx40MPwrCfgGBand[3];
206 TxPwr[4] = pAd->Tx40MPwrCfgGBand[4];
211 if (pAd->CommonCfg.Channel > 14)
213 TxPwr[0] = pAd->Tx20MPwrCfgABand[0];
214 TxPwr[1] = pAd->Tx20MPwrCfgABand[1];
215 TxPwr[2] = pAd->Tx20MPwrCfgABand[2];
216 TxPwr[3] = pAd->Tx20MPwrCfgABand[3];
217 TxPwr[4] = pAd->Tx20MPwrCfgABand[4];
221 TxPwr[0] = pAd->Tx20MPwrCfgGBand[0];
222 TxPwr[1] = pAd->Tx20MPwrCfgGBand[1];
223 TxPwr[2] = pAd->Tx20MPwrCfgGBand[2];
224 TxPwr[3] = pAd->Tx20MPwrCfgGBand[3];
225 TxPwr[4] = pAd->Tx20MPwrCfgGBand[4];
230 switch(HTTxMode.field.MODE)
235 TxPwrRef = (Value & 0x00000f00) >> 8;
240 case MODE_HTGREENFIELD:
241 if (pAd->CommonCfg.TxStream == 1)
244 TxPwrRef = (Value & 0x00000f00) >> 8;
246 else if (pAd->CommonCfg.TxStream == 2)
249 TxPwrRef = (Value & 0x00000f00) >> 8;
255 (HTTxMode.field.MODE == MODE_HTGREENFIELD)
259 for (Idx = 0; Idx < MAX_TXPWR_TAB_SIZE; Idx++)
261 if ((TxPwrCfg[Idx].Mode == PhyMode)
262 && (TxPwrCfg[Idx].MCS == HTTxMode.field.MCS))
264 Value = TxPwr[TxPwrCfg[Idx].req];
265 DaltaPwr = TxPwrRef - (CHAR)((Value & TxPwrCfg[Idx].BitMask)
266 >> TxPwrCfg[Idx].shift);
267 CurTxPwr -= DaltaPwr;
276 VOID MeasureReqTabInit(
277 IN PRTMP_ADAPTER pAd)
279 NdisAllocateSpinLock(&pAd->CommonCfg.MeasureReqTabLock);
281 pAd->CommonCfg.pMeasureReqTab = kmalloc(sizeof(MEASURE_REQ_TAB), GFP_ATOMIC);
282 if (pAd->CommonCfg.pMeasureReqTab)
283 NdisZeroMemory(pAd->CommonCfg.pMeasureReqTab, sizeof(MEASURE_REQ_TAB));
285 DBGPRINT(RT_DEBUG_ERROR, ("%s Fail to alloc memory for pAd->CommonCfg.pMeasureReqTab.\n", __func__));
290 VOID MeasureReqTabExit(
291 IN PRTMP_ADAPTER pAd)
293 NdisFreeSpinLock(&pAd->CommonCfg.MeasureReqTabLock);
295 if (pAd->CommonCfg.pMeasureReqTab)
296 kfree(pAd->CommonCfg.pMeasureReqTab);
297 pAd->CommonCfg.pMeasureReqTab = NULL;
302 PMEASURE_REQ_ENTRY MeasureReqLookUp(
303 IN PRTMP_ADAPTER pAd,
304 IN UINT8 DialogToken)
307 PMEASURE_REQ_TAB pTab = pAd->CommonCfg.pMeasureReqTab;
308 PMEASURE_REQ_ENTRY pEntry = NULL;
309 PMEASURE_REQ_ENTRY pPrevEntry = NULL;
313 DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab doesn't exist.\n", __func__));
317 RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock);
319 HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(DialogToken);
320 pEntry = pTab->Hash[HashIdx];
324 if (pEntry->DialogToken == DialogToken)
329 pEntry = pEntry->pNext;
333 RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock);
338 PMEASURE_REQ_ENTRY MeasureReqInsert(
339 IN PRTMP_ADAPTER pAd,
340 IN UINT8 DialogToken)
344 PMEASURE_REQ_TAB pTab = pAd->CommonCfg.pMeasureReqTab;
345 PMEASURE_REQ_ENTRY pEntry = NULL, pCurrEntry;
350 DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab doesn't exist.\n", __func__));
354 pEntry = MeasureReqLookUp(pAd, DialogToken);
357 RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock);
358 for (i = 0; i < MAX_MEASURE_REQ_TAB_SIZE; i++)
360 NdisGetSystemUpTime(&Now);
361 pEntry = &pTab->Content[i];
363 if ((pEntry->Valid == TRUE)
364 && RTMP_TIME_AFTER((unsigned long)Now, (unsigned long)(pEntry->lastTime + MQ_REQ_AGE_OUT)))
366 PMEASURE_REQ_ENTRY pPrevEntry = NULL;
367 ULONG HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken);
368 PMEASURE_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx];
373 if (pProbeEntry == pEntry)
375 if (pPrevEntry == NULL)
377 pTab->Hash[HashIdx] = pEntry->pNext;
381 pPrevEntry->pNext = pEntry->pNext;
386 pPrevEntry = pProbeEntry;
387 pProbeEntry = pProbeEntry->pNext;
388 } while (pProbeEntry);
390 NdisZeroMemory(pEntry, sizeof(MEASURE_REQ_ENTRY));
396 if (pEntry->Valid == FALSE)
400 if (i < MAX_MEASURE_REQ_TAB_SIZE)
402 NdisGetSystemUpTime(&Now);
403 pEntry->lastTime = Now;
404 pEntry->Valid = TRUE;
405 pEntry->DialogToken = DialogToken;
411 DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab tab full.\n", __func__));
414 // add this Neighbor entry into HASH table
417 HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(DialogToken);
418 if (pTab->Hash[HashIdx] == NULL)
420 pTab->Hash[HashIdx] = pEntry;
424 pCurrEntry = pTab->Hash[HashIdx];
425 while (pCurrEntry->pNext != NULL)
426 pCurrEntry = pCurrEntry->pNext;
427 pCurrEntry->pNext = pEntry;
431 RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock);
437 VOID MeasureReqDelete(
438 IN PRTMP_ADAPTER pAd,
439 IN UINT8 DialogToken)
441 PMEASURE_REQ_TAB pTab = pAd->CommonCfg.pMeasureReqTab;
442 PMEASURE_REQ_ENTRY pEntry = NULL;
446 DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab doesn't exist.\n", __func__));
453 DBGPRINT(RT_DEBUG_ERROR, ("pMeasureReqTab empty.\n"));
457 pEntry = MeasureReqLookUp(pAd, DialogToken);
460 PMEASURE_REQ_ENTRY pPrevEntry = NULL;
461 ULONG HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken);
462 PMEASURE_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx];
464 RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock);
468 if (pProbeEntry == pEntry)
470 if (pPrevEntry == NULL)
472 pTab->Hash[HashIdx] = pEntry->pNext;
476 pPrevEntry->pNext = pEntry->pNext;
481 pPrevEntry = pProbeEntry;
482 pProbeEntry = pProbeEntry->pNext;
483 } while (pProbeEntry);
485 NdisZeroMemory(pEntry, sizeof(MEASURE_REQ_ENTRY));
488 RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock);
495 IN PRTMP_ADAPTER pAd)
497 NdisAllocateSpinLock(&pAd->CommonCfg.TpcReqTabLock);
499 pAd->CommonCfg.pTpcReqTab = kmalloc(sizeof(TPC_REQ_TAB), GFP_ATOMIC);
500 if (pAd->CommonCfg.pTpcReqTab)
501 NdisZeroMemory(pAd->CommonCfg.pTpcReqTab, sizeof(TPC_REQ_TAB));
503 DBGPRINT(RT_DEBUG_ERROR, ("%s Fail to alloc memory for pAd->CommonCfg.pTpcReqTab.\n", __func__));
509 IN PRTMP_ADAPTER pAd)
511 NdisFreeSpinLock(&pAd->CommonCfg.TpcReqTabLock);
513 if (pAd->CommonCfg.pTpcReqTab)
514 kfree(pAd->CommonCfg.pTpcReqTab);
515 pAd->CommonCfg.pTpcReqTab = NULL;
520 static PTPC_REQ_ENTRY TpcReqLookUp(
521 IN PRTMP_ADAPTER pAd,
522 IN UINT8 DialogToken)
525 PTPC_REQ_TAB pTab = pAd->CommonCfg.pTpcReqTab;
526 PTPC_REQ_ENTRY pEntry = NULL;
527 PTPC_REQ_ENTRY pPrevEntry = NULL;
531 DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab doesn't exist.\n", __func__));
535 RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock);
537 HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(DialogToken);
538 pEntry = pTab->Hash[HashIdx];
542 if (pEntry->DialogToken == DialogToken)
547 pEntry = pEntry->pNext;
551 RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock);
557 static PTPC_REQ_ENTRY TpcReqInsert(
558 IN PRTMP_ADAPTER pAd,
559 IN UINT8 DialogToken)
563 PTPC_REQ_TAB pTab = pAd->CommonCfg.pTpcReqTab;
564 PTPC_REQ_ENTRY pEntry = NULL, pCurrEntry;
569 DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab doesn't exist.\n", __func__));
573 pEntry = TpcReqLookUp(pAd, DialogToken);
576 RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock);
577 for (i = 0; i < MAX_TPC_REQ_TAB_SIZE; i++)
579 NdisGetSystemUpTime(&Now);
580 pEntry = &pTab->Content[i];
582 if ((pEntry->Valid == TRUE)
583 && RTMP_TIME_AFTER((unsigned long)Now, (unsigned long)(pEntry->lastTime + TPC_REQ_AGE_OUT)))
585 PTPC_REQ_ENTRY pPrevEntry = NULL;
586 ULONG HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken);
587 PTPC_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx];
592 if (pProbeEntry == pEntry)
594 if (pPrevEntry == NULL)
596 pTab->Hash[HashIdx] = pEntry->pNext;
600 pPrevEntry->pNext = pEntry->pNext;
605 pPrevEntry = pProbeEntry;
606 pProbeEntry = pProbeEntry->pNext;
607 } while (pProbeEntry);
609 NdisZeroMemory(pEntry, sizeof(TPC_REQ_ENTRY));
615 if (pEntry->Valid == FALSE)
619 if (i < MAX_TPC_REQ_TAB_SIZE)
621 NdisGetSystemUpTime(&Now);
622 pEntry->lastTime = Now;
623 pEntry->Valid = TRUE;
624 pEntry->DialogToken = DialogToken;
630 DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab tab full.\n", __func__));
633 // add this Neighbor entry into HASH table
636 HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(DialogToken);
637 if (pTab->Hash[HashIdx] == NULL)
639 pTab->Hash[HashIdx] = pEntry;
643 pCurrEntry = pTab->Hash[HashIdx];
644 while (pCurrEntry->pNext != NULL)
645 pCurrEntry = pCurrEntry->pNext;
646 pCurrEntry->pNext = pEntry;
650 RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock);
656 static VOID TpcReqDelete(
657 IN PRTMP_ADAPTER pAd,
658 IN UINT8 DialogToken)
660 PTPC_REQ_TAB pTab = pAd->CommonCfg.pTpcReqTab;
661 PTPC_REQ_ENTRY pEntry = NULL;
665 DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab doesn't exist.\n", __func__));
672 DBGPRINT(RT_DEBUG_ERROR, ("pTpcReqTab empty.\n"));
676 pEntry = TpcReqLookUp(pAd, DialogToken);
679 PTPC_REQ_ENTRY pPrevEntry = NULL;
680 ULONG HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken);
681 PTPC_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx];
683 RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock);
687 if (pProbeEntry == pEntry)
689 if (pPrevEntry == NULL)
691 pTab->Hash[HashIdx] = pEntry->pNext;
695 pPrevEntry->pNext = pEntry->pNext;
700 pPrevEntry = pProbeEntry;
701 pProbeEntry = pProbeEntry->pNext;
702 } while (pProbeEntry);
704 NdisZeroMemory(pEntry, sizeof(TPC_REQ_ENTRY));
707 RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock);
714 ==========================================================================
716 Get Current TimeS tamp.
720 Return : Current Time Stamp.
721 ==========================================================================
723 static UINT64 GetCurrentTimeStamp(
724 IN PRTMP_ADAPTER pAd)
726 // get current time stamp.
731 ==========================================================================
733 Get Current Transmit Power.
737 Return : Current Time Stamp.
738 ==========================================================================
740 static UINT8 GetCurTxPwr(
741 IN PRTMP_ADAPTER pAd,
744 return 16; /* 16 dBm */
748 ==========================================================================
750 Get Current Transmit Power.
754 Return : Current Time Stamp.
755 ==========================================================================
757 VOID InsertChannelRepIE(
758 IN PRTMP_ADAPTER pAd,
759 OUT PUCHAR pFrameBuf,
760 OUT PULONG pFrameLen,
762 IN UINT8 RegulatoryClass)
766 UINT8 IEId = IE_AP_CHANNEL_REPORT;
767 PUCHAR pChListPtr = NULL;
770 if (strncmp(pCountry, "US", 2) == 0)
772 if (RegulatoryClass >= USA_REGULATORY_INFO_SIZE)
774 DBGPRINT(RT_DEBUG_ERROR, ("%s: USA Unknow Requlatory class (%d)\n",
775 __func__, RegulatoryClass));
779 Len += USARegulatoryInfo[RegulatoryClass].ChannelSet.NumberOfChannels;
780 pChListPtr = USARegulatoryInfo[RegulatoryClass].ChannelSet.ChannelList;
782 else if (strncmp(pCountry, "JP", 2) == 0)
784 if (RegulatoryClass >= JP_REGULATORY_INFO_SIZE)
786 DBGPRINT(RT_DEBUG_ERROR, ("%s: JP Unknow Requlatory class (%d)\n",
787 __func__, RegulatoryClass));
791 Len += JapanRegulatoryInfo[RegulatoryClass].ChannelSet.NumberOfChannels;
792 pChListPtr = JapanRegulatoryInfo[RegulatoryClass].ChannelSet.ChannelList;
796 DBGPRINT(RT_DEBUG_ERROR, ("%s: Unknow Country (%s)\n",
797 __func__, pCountry));
801 MakeOutgoingFrame(pFrameBuf, &TempLen,
808 *pFrameLen = *pFrameLen + TempLen;
814 ==========================================================================
816 Insert Dialog Token into frame.
819 1. frame buffer pointer.
824 ==========================================================================
826 VOID InsertDialogToken(
827 IN PRTMP_ADAPTER pAd,
828 OUT PUCHAR pFrameBuf,
829 OUT PULONG pFrameLen,
830 IN UINT8 DialogToken)
833 MakeOutgoingFrame(pFrameBuf, &TempLen,
837 *pFrameLen = *pFrameLen + TempLen;
843 ==========================================================================
845 Insert TPC Request IE into frame.
848 1. frame buffer pointer.
852 ==========================================================================
854 static VOID InsertTpcReqIE(
855 IN PRTMP_ADAPTER pAd,
856 OUT PUCHAR pFrameBuf,
857 OUT PULONG pFrameLen)
861 UINT8 ElementID = IE_TPC_REQUEST;
863 MakeOutgoingFrame(pFrameBuf, &TempLen,
868 *pFrameLen = *pFrameLen + TempLen;
874 ==========================================================================
876 Insert TPC Report IE into frame.
879 1. frame buffer pointer.
885 ==========================================================================
887 VOID InsertTpcReportIE(
888 IN PRTMP_ADAPTER pAd,
889 OUT PUCHAR pFrameBuf,
890 OUT PULONG pFrameLen,
895 ULONG Len = sizeof(TPC_REPORT_INFO);
896 UINT8 ElementID = IE_TPC_REPORT;
897 TPC_REPORT_INFO TpcReportIE;
899 TpcReportIE.TxPwr = TxPwr;
900 TpcReportIE.LinkMargin = LinkMargin;
902 MakeOutgoingFrame(pFrameBuf, &TempLen,
908 *pFrameLen = *pFrameLen + TempLen;
915 ==========================================================================
917 Insert Channel Switch Announcement IE into frame.
920 1. frame buffer pointer.
922 3. channel switch announcement mode.
923 4. new selected channel.
924 5. channel switch announcement count.
927 ==========================================================================
929 static VOID InsertChSwAnnIE(
930 IN PRTMP_ADAPTER pAd,
931 OUT PUCHAR pFrameBuf,
932 OUT PULONG pFrameLen,
938 ULONG Len = sizeof(CH_SW_ANN_INFO);
939 UINT8 ElementID = IE_CHANNEL_SWITCH_ANNOUNCEMENT;
940 CH_SW_ANN_INFO ChSwAnnIE;
942 ChSwAnnIE.ChSwMode = ChSwMode;
943 ChSwAnnIE.Channel = NewChannel;
944 ChSwAnnIE.ChSwCnt = ChSwCnt;
946 MakeOutgoingFrame(pFrameBuf, &TempLen,
952 *pFrameLen = *pFrameLen + TempLen;
959 ==========================================================================
961 Insert Measure Request IE into frame.
964 1. frame buffer pointer.
967 4. Measure Request Mode.
968 5. Measure Request Type.
970 7. Measure Start time.
975 ==========================================================================
977 static VOID InsertMeasureReqIE(
978 IN PRTMP_ADAPTER pAd,
979 OUT PUCHAR pFrameBuf,
980 OUT PULONG pFrameLen,
982 IN PMEASURE_REQ_INFO pMeasureReqIE)
985 UINT8 ElementID = IE_MEASUREMENT_REQUEST;
987 MakeOutgoingFrame(pFrameBuf, &TempLen,
990 sizeof(MEASURE_REQ_INFO), pMeasureReqIE,
993 *pFrameLen = *pFrameLen + TempLen;
999 ==========================================================================
1001 Insert Measure Report IE into frame.
1004 1. frame buffer pointer.
1007 4. Measure Request Mode.
1008 5. Measure Request Type.
1009 6. Length of Report Infomation
1010 7. Pointer of Report Infomation Buffer.
1013 ==========================================================================
1015 static VOID InsertMeasureReportIE(
1016 IN PRTMP_ADAPTER pAd,
1017 OUT PUCHAR pFrameBuf,
1018 OUT PULONG pFrameLen,
1019 IN PMEASURE_REPORT_INFO pMeasureReportIE,
1020 IN UINT8 ReportLnfoLen,
1021 IN PUINT8 pReportInfo)
1025 UINT8 ElementID = IE_MEASUREMENT_REPORT;
1027 Len = sizeof(MEASURE_REPORT_INFO) + ReportLnfoLen;
1029 MakeOutgoingFrame(pFrameBuf, &TempLen,
1032 Len, pMeasureReportIE,
1035 *pFrameLen = *pFrameLen + TempLen;
1037 if ((ReportLnfoLen > 0) && (pReportInfo != NULL))
1039 MakeOutgoingFrame(pFrameBuf + *pFrameLen, &TempLen,
1040 ReportLnfoLen, pReportInfo,
1043 *pFrameLen = *pFrameLen + TempLen;
1049 ==========================================================================
1051 Prepare Measurement request action frame and enqueue it into
1052 management queue waiting for transmition.
1055 1. the destination mac address of the frame.
1058 ==========================================================================
1060 VOID MakeMeasurementReqFrame(
1061 IN PRTMP_ADAPTER pAd,
1062 OUT PUCHAR pOutBuffer,
1063 OUT PULONG pFrameLen,
1067 IN UINT8 MeasureToken,
1068 IN UINT8 MeasureReqMode,
1069 IN UINT8 MeasureReqType,
1070 IN UINT8 NumOfRepetitions)
1073 MEASURE_REQ_INFO MeasureReqIE;
1075 InsertActField(pAd, (pOutBuffer + *pFrameLen), pFrameLen, Category, Action);
1077 // fill Dialog Token
1078 InsertDialogToken(pAd, (pOutBuffer + *pFrameLen), pFrameLen, MeasureToken);
1080 /* fill Number of repetitions. */
1081 if (Category == CATEGORY_RM)
1083 MakeOutgoingFrame((pOutBuffer+*pFrameLen), &TempLen,
1084 2, &NumOfRepetitions,
1087 *pFrameLen += TempLen;
1090 // prepare Measurement IE.
1091 NdisZeroMemory(&MeasureReqIE, sizeof(MEASURE_REQ_INFO));
1092 MeasureReqIE.Token = MeasureToken;
1093 MeasureReqIE.ReqMode.word = MeasureReqMode;
1094 MeasureReqIE.ReqType = MeasureReqType;
1095 InsertMeasureReqIE(pAd, (pOutBuffer+*pFrameLen), pFrameLen,
1096 TotalLen, &MeasureReqIE);
1102 ==========================================================================
1104 Prepare Measurement report action frame and enqueue it into
1105 management queue waiting for transmition.
1108 1. the destination mac address of the frame.
1111 ==========================================================================
1113 VOID EnqueueMeasurementRep(
1114 IN PRTMP_ADAPTER pAd,
1116 IN UINT8 DialogToken,
1117 IN UINT8 MeasureToken,
1118 IN UINT8 MeasureReqMode,
1119 IN UINT8 MeasureReqType,
1120 IN UINT8 ReportInfoLen,
1121 IN PUINT8 pReportInfo)
1123 PUCHAR pOutBuffer = NULL;
1124 NDIS_STATUS NStatus;
1126 HEADER_802_11 ActHdr;
1127 MEASURE_REPORT_INFO MeasureRepIE;
1129 // build action frame header.
1130 MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
1131 pAd->CurrentAddress);
1133 NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory
1134 if(NStatus != NDIS_STATUS_SUCCESS)
1136 DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __func__));
1139 NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11));
1140 FrameLen = sizeof(HEADER_802_11);
1142 InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_MRP);
1144 // fill Dialog Token
1145 InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken);
1147 // prepare Measurement IE.
1148 NdisZeroMemory(&MeasureRepIE, sizeof(MEASURE_REPORT_INFO));
1149 MeasureRepIE.Token = MeasureToken;
1150 MeasureRepIE.ReportMode = MeasureReqMode;
1151 MeasureRepIE.ReportType = MeasureReqType;
1152 InsertMeasureReportIE(pAd, (pOutBuffer + FrameLen), &FrameLen, &MeasureRepIE, ReportInfoLen, pReportInfo);
1154 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1155 MlmeFreeMemory(pAd, pOutBuffer);
1161 ==========================================================================
1163 Prepare TPC Request action frame and enqueue it into
1164 management queue waiting for transmition.
1167 1. the destination mac address of the frame.
1170 ==========================================================================
1173 IN PRTMP_ADAPTER pAd,
1175 IN UCHAR DialogToken)
1177 PUCHAR pOutBuffer = NULL;
1178 NDIS_STATUS NStatus;
1181 HEADER_802_11 ActHdr;
1183 // build action frame header.
1184 MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
1185 pAd->CurrentAddress);
1187 NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory
1188 if(NStatus != NDIS_STATUS_SUCCESS)
1190 DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __func__));
1193 NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11));
1194 FrameLen = sizeof(HEADER_802_11);
1196 InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_TPCRQ);
1198 // fill Dialog Token
1199 InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken);
1201 // Insert TPC Request IE.
1202 InsertTpcReqIE(pAd, (pOutBuffer + FrameLen), &FrameLen);
1204 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1205 MlmeFreeMemory(pAd, pOutBuffer);
1211 ==========================================================================
1213 Prepare TPC Report action frame and enqueue it into
1214 management queue waiting for transmition.
1217 1. the destination mac address of the frame.
1220 ==========================================================================
1223 IN PRTMP_ADAPTER pAd,
1225 IN UINT8 DialogToken,
1227 IN UINT8 LinkMargin)
1229 PUCHAR pOutBuffer = NULL;
1230 NDIS_STATUS NStatus;
1233 HEADER_802_11 ActHdr;
1235 // build action frame header.
1236 MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
1237 pAd->CurrentAddress);
1239 NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory
1240 if(NStatus != NDIS_STATUS_SUCCESS)
1242 DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __func__));
1245 NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11));
1246 FrameLen = sizeof(HEADER_802_11);
1248 InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_TPCRP);
1250 // fill Dialog Token
1251 InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken);
1253 // Insert TPC Request IE.
1254 InsertTpcReportIE(pAd, (pOutBuffer + FrameLen), &FrameLen, TxPwr, LinkMargin);
1256 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1257 MlmeFreeMemory(pAd, pOutBuffer);
1263 ==========================================================================
1265 Prepare Channel Switch Announcement action frame and enqueue it into
1266 management queue waiting for transmition.
1269 1. the destination mac address of the frame.
1270 2. Channel switch announcement mode.
1271 2. a New selected channel.
1274 ==========================================================================
1276 VOID EnqueueChSwAnn(
1277 IN PRTMP_ADAPTER pAd,
1282 PUCHAR pOutBuffer = NULL;
1283 NDIS_STATUS NStatus;
1286 HEADER_802_11 ActHdr;
1288 // build action frame header.
1289 MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
1290 pAd->CurrentAddress);
1292 NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory
1293 if(NStatus != NDIS_STATUS_SUCCESS)
1295 DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __func__));
1298 NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11));
1299 FrameLen = sizeof(HEADER_802_11);
1301 InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_CHANNEL_SWITCH);
1303 InsertChSwAnnIE(pAd, (pOutBuffer + FrameLen), &FrameLen, ChSwMode, NewCh, 0);
1305 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1306 MlmeFreeMemory(pAd, pOutBuffer);
1311 static BOOLEAN DfsRequirementCheck(
1312 IN PRTMP_ADAPTER pAd,
1315 BOOLEAN Result = FALSE;
1320 // check DFS procedure is running.
1321 // make sure DFS procedure won't start twice.
1322 if (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)
1328 // check the new channel carried from Channel Switch Announcemnet is valid.
1329 for (i=0; i<pAd->ChannelListNum; i++)
1331 if ((Channel == pAd->ChannelList[i].Channel)
1332 &&(pAd->ChannelList[i].RemainingTimeForUse == 0))
1334 // found radar signal in the channel. the channel can't use at least for 30 minutes.
1335 pAd->ChannelList[i].RemainingTimeForUse = 1800;//30 min = 1800 sec
1345 VOID NotifyChSwAnnToPeerAPs(
1346 IN PRTMP_ADAPTER pAd,
1354 static VOID StartDFSProcedure(
1355 IN PRTMP_ADAPTER pAd,
1359 // start DFS procedure
1360 pAd->CommonCfg.Channel = Channel;
1362 N_ChannelCheck(pAd);
1364 pAd->CommonCfg.RadarDetect.RDMode = RD_SWITCHING_MODE;
1365 pAd->CommonCfg.RadarDetect.CSCount = 0;
1369 ==========================================================================
1371 Channel Switch Announcement action frame sanity check.
1374 1. MLME message containing the received frame
1376 3. Channel switch announcement infomation buffer.
1380 ==========================================================================
1384 Channel Switch Announcement IE.
1385 +----+-----+-----------+------------+-----------+
1386 | ID | Len |Ch Sw Mode | New Ch Num | Ch Sw Cnt |
1387 +----+-----+-----------+------------+-----------+
1390 static BOOLEAN PeerChSwAnnSanity(
1391 IN PRTMP_ADAPTER pAd,
1394 OUT PCH_SW_ANN_INFO pChSwAnnInfo)
1396 PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
1397 PUCHAR pFramePtr = Fr->Octet;
1398 BOOLEAN result = FALSE;
1399 PEID_STRUCT eid_ptr;
1401 // skip 802.11 header.
1402 MsgLen -= sizeof(HEADER_802_11);
1404 // skip category and action code.
1408 if (pChSwAnnInfo == NULL)
1411 eid_ptr = (PEID_STRUCT)pFramePtr;
1412 while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
1414 switch(eid_ptr->Eid)
1416 case IE_CHANNEL_SWITCH_ANNOUNCEMENT:
1417 NdisMoveMemory(&pChSwAnnInfo->ChSwMode, eid_ptr->Octet, 1);
1418 NdisMoveMemory(&pChSwAnnInfo->Channel, eid_ptr->Octet + 1, 1);
1419 NdisMoveMemory(&pChSwAnnInfo->ChSwCnt, eid_ptr->Octet + 2, 1);
1427 eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
1434 ==========================================================================
1436 Measurement request action frame sanity check.
1439 1. MLME message containing the received frame
1441 3. Measurement request infomation buffer.
1444 ==========================================================================
1446 static BOOLEAN PeerMeasureReqSanity(
1447 IN PRTMP_ADAPTER pAd,
1450 OUT PUINT8 pDialogToken,
1451 OUT PMEASURE_REQ_INFO pMeasureReqInfo,
1452 OUT PMEASURE_REQ pMeasureReq)
1454 PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
1455 PUCHAR pFramePtr = Fr->Octet;
1456 BOOLEAN result = FALSE;
1457 PEID_STRUCT eid_ptr;
1459 UINT64 MeasureStartTime;
1460 UINT16 MeasureDuration;
1462 // skip 802.11 header.
1463 MsgLen -= sizeof(HEADER_802_11);
1465 // skip category and action code.
1469 if (pMeasureReqInfo == NULL)
1472 NdisMoveMemory(pDialogToken, pFramePtr, 1);
1476 eid_ptr = (PEID_STRUCT)pFramePtr;
1477 while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
1479 switch(eid_ptr->Eid)
1481 case IE_MEASUREMENT_REQUEST:
1482 NdisMoveMemory(&pMeasureReqInfo->Token, eid_ptr->Octet, 1);
1483 NdisMoveMemory(&pMeasureReqInfo->ReqMode.word, eid_ptr->Octet + 1, 1);
1484 NdisMoveMemory(&pMeasureReqInfo->ReqType, eid_ptr->Octet + 2, 1);
1485 ptr = (PUCHAR)(eid_ptr->Octet + 3);
1486 NdisMoveMemory(&pMeasureReq->ChNum, ptr, 1);
1487 NdisMoveMemory(&MeasureStartTime, ptr + 1, 8);
1488 pMeasureReq->MeasureStartTime = SWAP64(MeasureStartTime);
1489 NdisMoveMemory(&MeasureDuration, ptr + 9, 2);
1490 pMeasureReq->MeasureDuration = SWAP16(MeasureDuration);
1498 eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
1505 ==========================================================================
1507 Measurement report action frame sanity check.
1510 1. MLME message containing the received frame
1512 3. Measurement report infomation buffer.
1513 4. basic report infomation buffer.
1516 ==========================================================================
1520 Measurement Report IE.
1521 +----+-----+-------+-------------+--------------+----------------+
1522 | ID | Len | Token | Report Mode | Measure Type | Measure Report |
1523 +----+-----+-------+-------------+--------------+----------------+
1527 +--------+------------+----------+-----+
1528 | Ch Num | Start Time | Duration | Map |
1529 +--------+------------+----------+-----+
1532 Map Field Bit Format.
1533 +-----+---------------+---------------------+-------+------------+----------+
1534 | Bss | OFDM Preamble | Unidentified signal | Radar | Unmeasured | Reserved |
1535 +-----+---------------+---------------------+-------+------------+----------+
1538 static BOOLEAN PeerMeasureReportSanity(
1539 IN PRTMP_ADAPTER pAd,
1542 OUT PUINT8 pDialogToken,
1543 OUT PMEASURE_REPORT_INFO pMeasureReportInfo,
1544 OUT PUINT8 pReportBuf)
1546 PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
1547 PUCHAR pFramePtr = Fr->Octet;
1548 BOOLEAN result = FALSE;
1549 PEID_STRUCT eid_ptr;
1552 // skip 802.11 header.
1553 MsgLen -= sizeof(HEADER_802_11);
1555 // skip category and action code.
1559 if (pMeasureReportInfo == NULL)
1562 NdisMoveMemory(pDialogToken, pFramePtr, 1);
1566 eid_ptr = (PEID_STRUCT)pFramePtr;
1567 while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
1569 switch(eid_ptr->Eid)
1571 case IE_MEASUREMENT_REPORT:
1572 NdisMoveMemory(&pMeasureReportInfo->Token, eid_ptr->Octet, 1);
1573 NdisMoveMemory(&pMeasureReportInfo->ReportMode, eid_ptr->Octet + 1, 1);
1574 NdisMoveMemory(&pMeasureReportInfo->ReportType, eid_ptr->Octet + 2, 1);
1575 if (pMeasureReportInfo->ReportType == RM_BASIC)
1577 PMEASURE_BASIC_REPORT pReport = (PMEASURE_BASIC_REPORT)pReportBuf;
1578 ptr = (PUCHAR)(eid_ptr->Octet + 3);
1579 NdisMoveMemory(&pReport->ChNum, ptr, 1);
1580 NdisMoveMemory(&pReport->MeasureStartTime, ptr + 1, 8);
1581 NdisMoveMemory(&pReport->MeasureDuration, ptr + 9, 2);
1582 NdisMoveMemory(&pReport->Map, ptr + 11, 1);
1585 else if (pMeasureReportInfo->ReportType == RM_CCA)
1587 PMEASURE_CCA_REPORT pReport = (PMEASURE_CCA_REPORT)pReportBuf;
1588 ptr = (PUCHAR)(eid_ptr->Octet + 3);
1589 NdisMoveMemory(&pReport->ChNum, ptr, 1);
1590 NdisMoveMemory(&pReport->MeasureStartTime, ptr + 1, 8);
1591 NdisMoveMemory(&pReport->MeasureDuration, ptr + 9, 2);
1592 NdisMoveMemory(&pReport->CCA_Busy_Fraction, ptr + 11, 1);
1595 else if (pMeasureReportInfo->ReportType == RM_RPI_HISTOGRAM)
1597 PMEASURE_RPI_REPORT pReport = (PMEASURE_RPI_REPORT)pReportBuf;
1598 ptr = (PUCHAR)(eid_ptr->Octet + 3);
1599 NdisMoveMemory(&pReport->ChNum, ptr, 1);
1600 NdisMoveMemory(&pReport->MeasureStartTime, ptr + 1, 8);
1601 NdisMoveMemory(&pReport->MeasureDuration, ptr + 9, 2);
1602 NdisMoveMemory(&pReport->RPI_Density, ptr + 11, 8);
1610 eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
1617 ==========================================================================
1619 TPC Request action frame sanity check.
1622 1. MLME message containing the received frame
1627 ==========================================================================
1629 static BOOLEAN PeerTpcReqSanity(
1630 IN PRTMP_ADAPTER pAd,
1633 OUT PUINT8 pDialogToken)
1635 PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
1636 PUCHAR pFramePtr = Fr->Octet;
1637 BOOLEAN result = FALSE;
1638 PEID_STRUCT eid_ptr;
1640 MsgLen -= sizeof(HEADER_802_11);
1642 // skip category and action code.
1646 if (pDialogToken == NULL)
1649 NdisMoveMemory(pDialogToken, pFramePtr, 1);
1653 eid_ptr = (PEID_STRUCT)pFramePtr;
1654 while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
1656 switch(eid_ptr->Eid)
1658 case IE_TPC_REQUEST:
1665 eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
1672 ==========================================================================
1674 TPC Report action frame sanity check.
1677 1. MLME message containing the received frame
1683 ==========================================================================
1685 static BOOLEAN PeerTpcRepSanity(
1686 IN PRTMP_ADAPTER pAd,
1689 OUT PUINT8 pDialogToken,
1690 OUT PTPC_REPORT_INFO pTpcRepInfo)
1692 PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
1693 PUCHAR pFramePtr = Fr->Octet;
1694 BOOLEAN result = FALSE;
1695 PEID_STRUCT eid_ptr;
1697 MsgLen -= sizeof(HEADER_802_11);
1699 // skip category and action code.
1703 if (pDialogToken == NULL)
1706 NdisMoveMemory(pDialogToken, pFramePtr, 1);
1710 eid_ptr = (PEID_STRUCT)pFramePtr;
1711 while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
1713 switch(eid_ptr->Eid)
1716 NdisMoveMemory(&pTpcRepInfo->TxPwr, eid_ptr->Octet, 1);
1717 NdisMoveMemory(&pTpcRepInfo->LinkMargin, eid_ptr->Octet + 1, 1);
1724 eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
1731 ==========================================================================
1733 Channel Switch Announcement action frame handler.
1736 Elme - MLME message containing the received frame
1739 ==========================================================================
1741 static VOID PeerChSwAnnAction(
1742 IN PRTMP_ADAPTER pAd,
1743 IN MLME_QUEUE_ELEM *Elem)
1745 CH_SW_ANN_INFO ChSwAnnInfo;
1746 PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg;
1747 UCHAR index = 0, Channel = 0, NewChannel = 0;
1750 NdisZeroMemory(&ChSwAnnInfo, sizeof(CH_SW_ANN_INFO));
1751 if (! PeerChSwAnnSanity(pAd, Elem->Msg, Elem->MsgLen, &ChSwAnnInfo))
1753 DBGPRINT(RT_DEBUG_TRACE, ("Invalid Channel Switch Action Frame.\n"));
1757 if (pAd->OpMode == OPMODE_STA)
1759 Bssidx = BssTableSearch(&pAd->ScanTab, pFr->Hdr.Addr3, pAd->CommonCfg.Channel);
1760 if (Bssidx == BSS_NOT_FOUND)
1762 DBGPRINT(RT_DEBUG_TRACE, ("PeerChSwAnnAction - Bssidx is not found\n"));
1766 DBGPRINT(RT_DEBUG_TRACE, ("\n****Bssidx is %d, Channel = %d\n", index, pAd->ScanTab.BssEntry[Bssidx].Channel));
1767 hex_dump("SSID",pAd->ScanTab.BssEntry[Bssidx].Bssid ,6);
1769 Channel = pAd->CommonCfg.Channel;
1770 NewChannel = ChSwAnnInfo.Channel;
1772 if ((pAd->CommonCfg.bIEEE80211H == 1) && (NewChannel != 0) && (Channel != NewChannel))
1774 // Switching to channel 1 can prevent from rescanning the current channel immediately (by auto reconnection).
1775 // In addition, clear the MLME queue and the scan table to discard the RX packets and previous scanning results.
1776 AsicSwitchChannel(pAd, 1, FALSE);
1777 AsicLockChannel(pAd, 1);
1778 LinkDown(pAd, FALSE);
1779 MlmeQueueInit(&pAd->Mlme.Queue);
1780 BssTableInit(&pAd->ScanTab);
1781 RTMPusecDelay(1000000); // use delay to prevent STA do reassoc
1783 // channel sanity check
1784 for (index = 0 ; index < pAd->ChannelListNum; index++)
1786 if (pAd->ChannelList[index].Channel == NewChannel)
1788 pAd->ScanTab.BssEntry[Bssidx].Channel = NewChannel;
1789 pAd->CommonCfg.Channel = NewChannel;
1790 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
1791 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
1792 DBGPRINT(RT_DEBUG_TRACE, ("&&&&&&&&&&&&&&&&PeerChSwAnnAction - STA receive channel switch announcement IE (New Channel =%d)\n", NewChannel));
1797 if (index >= pAd->ChannelListNum)
1799 DBGPRINT_ERR(("&&&&&&&&&&&&&&&&&&&&&&&&&&PeerChSwAnnAction(can not find New Channel=%d in ChannelList[%d]\n", pAd->CommonCfg.Channel, pAd->ChannelListNum));
1809 ==========================================================================
1811 Measurement Request action frame handler.
1814 Elme - MLME message containing the received frame
1817 ==========================================================================
1819 static VOID PeerMeasureReqAction(
1820 IN PRTMP_ADAPTER pAd,
1821 IN MLME_QUEUE_ELEM *Elem)
1823 PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg;
1825 MEASURE_REQ_INFO MeasureReqInfo;
1826 MEASURE_REQ MeasureReq;
1827 MEASURE_REPORT_MODE ReportMode;
1829 if(PeerMeasureReqSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &MeasureReqInfo, &MeasureReq))
1831 ReportMode.word = 0;
1832 ReportMode.field.Incapable = 1;
1833 EnqueueMeasurementRep(pAd, pFr->Hdr.Addr2, DialogToken, MeasureReqInfo.Token, ReportMode.word, MeasureReqInfo.ReqType, 0, NULL);
1840 ==========================================================================
1842 Measurement Report action frame handler.
1845 Elme - MLME message containing the received frame
1848 ==========================================================================
1850 static VOID PeerMeasureReportAction(
1851 IN PRTMP_ADAPTER pAd,
1852 IN MLME_QUEUE_ELEM *Elem)
1854 MEASURE_REPORT_INFO MeasureReportInfo;
1855 PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg;
1857 PUINT8 pMeasureReportInfo;
1859 // if (pAd->CommonCfg.bIEEE80211H != TRUE)
1862 if ((pMeasureReportInfo = kmalloc(sizeof(MEASURE_RPI_REPORT), GFP_ATOMIC)) == NULL)
1864 DBGPRINT(RT_DEBUG_ERROR, ("%s unable to alloc memory for measure report buffer (size=%zu).\n", __func__, sizeof(MEASURE_RPI_REPORT)));
1868 NdisZeroMemory(&MeasureReportInfo, sizeof(MEASURE_REPORT_INFO));
1869 NdisZeroMemory(pMeasureReportInfo, sizeof(MEASURE_RPI_REPORT));
1870 if (PeerMeasureReportSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &MeasureReportInfo, pMeasureReportInfo))
1873 PMEASURE_REQ_ENTRY pEntry = NULL;
1875 // Not a autonomous measure report.
1876 // check the dialog token field. drop it if the dialog token doesn't match.
1877 if ((DialogToken != 0)
1878 && ((pEntry = MeasureReqLookUp(pAd, DialogToken)) == NULL))
1882 MeasureReqDelete(pAd, pEntry->DialogToken);
1884 if (MeasureReportInfo.ReportType == RM_BASIC)
1886 PMEASURE_BASIC_REPORT pBasicReport = (PMEASURE_BASIC_REPORT)pMeasureReportInfo;
1887 if ((pBasicReport->Map.field.Radar)
1888 && (DfsRequirementCheck(pAd, pBasicReport->ChNum) == TRUE))
1890 NotifyChSwAnnToPeerAPs(pAd, pFr->Hdr.Addr1, pFr->Hdr.Addr2, 1, pBasicReport->ChNum);
1891 StartDFSProcedure(pAd, pBasicReport->ChNum, 1);
1897 DBGPRINT(RT_DEBUG_TRACE, ("Invalid Measurement Report Frame.\n"));
1899 kfree(pMeasureReportInfo);
1905 ==========================================================================
1907 TPC Request action frame handler.
1910 Elme - MLME message containing the received frame
1913 ==========================================================================
1915 static VOID PeerTpcReqAction(
1916 IN PRTMP_ADAPTER pAd,
1917 IN MLME_QUEUE_ELEM *Elem)
1919 PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg;
1920 PUCHAR pFramePtr = pFr->Octet;
1922 UINT8 TxPwr = GetCurTxPwr(pAd, Elem->Wcid);
1923 UINT8 LinkMargin = 0;
1926 // link margin: Ratio of the received signal power to the minimum desired by the station (STA). The
1927 // STA may incorporate rate information and channel conditions, including interference, into its computation
1930 RealRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0),
1931 ConvertToRssi(pAd, Elem->Rssi1, RSSI_1),
1932 ConvertToRssi(pAd, Elem->Rssi2, RSSI_2));
1934 // skip Category and action code.
1938 NdisMoveMemory(&DialogToken, pFramePtr, 1);
1940 LinkMargin = (RealRssi / MIN_RCV_PWR);
1941 if (PeerTpcReqSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken))
1942 EnqueueTPCRep(pAd, pFr->Hdr.Addr2, DialogToken, TxPwr, LinkMargin);
1948 ==========================================================================
1950 TPC Report action frame handler.
1953 Elme - MLME message containing the received frame
1956 ==========================================================================
1958 static VOID PeerTpcRepAction(
1959 IN PRTMP_ADAPTER pAd,
1960 IN MLME_QUEUE_ELEM *Elem)
1963 TPC_REPORT_INFO TpcRepInfo;
1964 PTPC_REQ_ENTRY pEntry = NULL;
1966 NdisZeroMemory(&TpcRepInfo, sizeof(TPC_REPORT_INFO));
1967 if (PeerTpcRepSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &TpcRepInfo))
1969 if ((pEntry = TpcReqLookUp(pAd, DialogToken)) != NULL)
1971 TpcReqDelete(pAd, pEntry->DialogToken);
1972 DBGPRINT(RT_DEBUG_TRACE, ("%s: DialogToken=%x, TxPwr=%d, LinkMargin=%d\n",
1973 __func__, DialogToken, TpcRepInfo.TxPwr, TpcRepInfo.LinkMargin));
1981 ==========================================================================
1983 Spectrun action frames Handler such as channel switch annoucement,
1984 measurement report, measurement request actions frames.
1987 Elme - MLME message containing the received frame
1990 ==========================================================================
1992 VOID PeerSpectrumAction(
1993 IN PRTMP_ADAPTER pAd,
1994 IN MLME_QUEUE_ELEM *Elem)
1997 UCHAR Action = Elem->Msg[LENGTH_802_11+1];
1999 if (pAd->CommonCfg.bIEEE80211H != TRUE)
2005 // current rt2860 unable do such measure specified in Measurement Request.
2006 // reject all measurement request.
2007 PeerMeasureReqAction(pAd, Elem);
2011 PeerMeasureReportAction(pAd, Elem);
2015 PeerTpcReqAction(pAd, Elem);
2019 PeerTpcRepAction(pAd, Elem);
2022 case SPEC_CHANNEL_SWITCH:
2025 PeerChSwAnnAction(pAd, Elem);
2033 ==========================================================================
2039 ==========================================================================
2041 INT Set_MeasureReq_Proc(
2042 IN PRTMP_ADAPTER pAd,
2049 MEASURE_REQ_MODE MeasureReqMode;
2050 UINT8 MeasureReqToken = RandomByte(pAd);
2051 UINT8 MeasureReqType = RM_BASIC;
2052 UINT8 MeasureCh = 1;
2053 UINT64 MeasureStartTime = GetCurrentTimeStamp(pAd);
2054 MEASURE_REQ MeasureReq;
2057 HEADER_802_11 ActHdr;
2058 PUCHAR pOutBuffer = NULL;
2059 NDIS_STATUS NStatus;
2062 NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory
2063 if(NStatus != NDIS_STATUS_SUCCESS)
2065 DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __func__));
2066 goto END_OF_MEASURE_REQ;
2070 while ((thisChar = strsep((char **)&arg, "-")) != NULL)
2075 Aid = (UINT8) simple_strtol(thisChar, 0, 16);
2078 case 2: // Measurement Request Type.
2079 MeasureReqType = simple_strtol(thisChar, 0, 16);
2080 if (MeasureReqType > 3)
2082 DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow MeasureReqType(%d)\n", __func__, MeasureReqType));
2083 goto END_OF_MEASURE_REQ;
2087 case 3: // Measurement channel.
2088 MeasureCh = (UINT8) simple_strtol(thisChar, 0, 16);
2094 DBGPRINT(RT_DEBUG_TRACE, ("%s::Aid = %d, MeasureReqType=%d MeasureCh=%d\n", __func__, Aid, MeasureReqType, MeasureCh));
2095 if (!VALID_WCID(Aid))
2097 DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow sta of Aid(%d)\n", __func__, Aid));
2098 goto END_OF_MEASURE_REQ;
2101 MeasureReqMode.word = 0;
2102 MeasureReqMode.field.Enable = 1;
2104 MeasureReqInsert(pAd, MeasureReqToken);
2106 // build action frame header.
2107 MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pAd->MacTab.Content[Aid].Addr,
2108 pAd->CurrentAddress);
2110 NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11));
2111 FrameLen = sizeof(HEADER_802_11);
2113 TotalLen = sizeof(MEASURE_REQ_INFO) + sizeof(MEASURE_REQ);
2115 MakeMeasurementReqFrame(pAd, pOutBuffer, &FrameLen,
2116 sizeof(MEASURE_REQ_INFO), CATEGORY_RM, RM_BASIC,
2117 MeasureReqToken, MeasureReqMode.word,
2120 MeasureReq.ChNum = MeasureCh;
2121 MeasureReq.MeasureStartTime = cpu2le64(MeasureStartTime);
2122 MeasureReq.MeasureDuration = cpu2le16(2000);
2126 MakeOutgoingFrame( pOutBuffer+FrameLen, &TempLen,
2127 sizeof(MEASURE_REQ), &MeasureReq,
2129 FrameLen += TempLen;
2132 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, (UINT)FrameLen);
2135 MlmeFreeMemory(pAd, pOutBuffer);
2140 INT Set_TpcReq_Proc(
2141 IN PRTMP_ADAPTER pAd,
2146 UINT8 TpcReqToken = RandomByte(pAd);
2148 Aid = (UINT) simple_strtol(arg, 0, 16);
2150 DBGPRINT(RT_DEBUG_TRACE, ("%s::Aid = %d\n", __func__, Aid));
2151 if (!VALID_WCID(Aid))
2153 DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow sta of Aid(%d)\n", __func__, Aid));
2157 TpcReqInsert(pAd, TpcReqToken);
2159 EnqueueTPCReq(pAd, pAd->MacTab.Content[Aid].Addr, TpcReqToken);