First Support on Ginger and OMAP TI
[linux-ginger.git] / drivers / staging / rt3090 / common / spectrum.c
blob12d2125148ba0a2d4d2522977be9e996be600a74
1 /*
2 *************************************************************************
3 * Ralink Tech Inc.
4 * 5F., No.36, Taiyuan St., Jhubei City,
5 * Hsinchu County 302,
6 * Taiwan, R.O.C.
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. *
14 * *
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. *
19 * *
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. *
24 * *
25 *************************************************************************
27 Module Name:
28 action.c
30 Abstract:
31 Handle association related requests either from WSTA or from local MLME
33 Revision History:
34 Who When What
35 --------- ---------- ----------------------------------------------
36 Fonchi Wu 2008 created for 802.11h
39 #include "../rt_config.h"
40 #include "../action.h"
43 /* The regulatory information in the USA (US) */
44 DOT11_REGULATORY_INFORMATION USARegulatoryInfo[] =
46 /* "regulatory class" "number of channels" "Max Tx Pwr" "channel list" */
47 {0, {0, 0, {0}}}, // Invlid entry
48 {1, {4, 16, {36, 40, 44, 48}}},
49 {2, {4, 23, {52, 56, 60, 64}}},
50 {3, {4, 29, {149, 153, 157, 161}}},
51 {4, {11, 23, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}}},
52 {5, {5, 30, {149, 153, 157, 161, 165}}},
53 {6, {10, 14, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}},
54 {7, {10, 27, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}},
55 {8, {5, 17, {11, 13, 15, 17, 19}}},
56 {9, {5, 30, {11, 13, 15, 17, 19}}},
57 {10, {2, 20, {21, 25}}},
58 {11, {2, 33, {21, 25}}},
59 {12, {11, 30, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}}}
61 #define USA_REGULATORY_INFO_SIZE (sizeof(USARegulatoryInfo) / sizeof(DOT11_REGULATORY_INFORMATION))
64 /* The regulatory information in Europe */
65 DOT11_REGULATORY_INFORMATION EuropeRegulatoryInfo[] =
67 /* "regulatory class" "number of channels" "Max Tx Pwr" "channel list" */
68 {0, {0, 0, {0}}}, // Invalid entry
69 {1, {4, 20, {36, 40, 44, 48}}},
70 {2, {4, 20, {52, 56, 60, 64}}},
71 {3, {11, 30, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}}},
72 {4, {13, 20, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}}}
74 #define EU_REGULATORY_INFO_SIZE (sizeof(EuropeRegulatoryInfo) / sizeof(DOT11_REGULATORY_INFORMATION))
77 /* The regulatory information in Japan */
78 DOT11_REGULATORY_INFORMATION JapanRegulatoryInfo[] =
80 /* "regulatory class" "number of channels" "Max Tx Pwr" "channel list" */
81 {0, {0, 0, {0}}}, // Invalid entry
82 {1, {4, 22, {34, 38, 42, 46}}},
83 {2, {3, 24, {8, 12, 16}}},
84 {3, {3, 24, {8, 12, 16}}},
85 {4, {3, 24, {8, 12, 16}}},
86 {5, {3, 24, {8, 12, 16}}},
87 {6, {3, 22, {8, 12, 16}}},
88 {7, {4, 24, {184, 188, 192, 196}}},
89 {8, {4, 24, {184, 188, 192, 196}}},
90 {9, {4, 24, {184, 188, 192, 196}}},
91 {10, {4, 24, {184, 188, 192, 196}}},
92 {11, {4, 22, {184, 188, 192, 196}}},
93 {12, {4, 24, {7, 8, 9, 11}}},
94 {13, {4, 24, {7, 8, 9, 11}}},
95 {14, {4, 24, {7, 8, 9, 11}}},
96 {15, {4, 24, {7, 8, 9, 11}}},
97 {16, {6, 24, {183, 184, 185, 187, 188, 189}}},
98 {17, {6, 24, {183, 184, 185, 187, 188, 189}}},
99 {18, {6, 24, {183, 184, 185, 187, 188, 189}}},
100 {19, {6, 24, {183, 184, 185, 187, 188, 189}}},
101 {20, {6, 17, {183, 184, 185, 187, 188, 189}}},
102 {21, {6, 24, {6, 7, 8, 9, 10, 11}}},
103 {22, {6, 24, {6, 7, 8, 9, 10, 11}}},
104 {23, {6, 24, {6, 7, 8, 9, 10, 11}}},
105 {24, {6, 24, {6, 7, 8, 9, 10, 11}}},
106 {25, {8, 24, {182, 183, 184, 185, 186, 187, 188, 189}}},
107 {26, {8, 24, {182, 183, 184, 185, 186, 187, 188, 189}}},
108 {27, {8, 24, {182, 183, 184, 185, 186, 187, 188, 189}}},
109 {28, {8, 24, {182, 183, 184, 185, 186, 187, 188, 189}}},
110 {29, {8, 17, {182, 183, 184, 185, 186, 187, 188, 189}}},
111 {30, {13, 23, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}}},
112 {31, {1, 23, {14}}},
113 {32, {4, 22, {52, 56, 60, 64}}}
115 #define JP_REGULATORY_INFO_SIZE (sizeof(JapanRegulatoryInfo) / sizeof(DOT11_REGULATORY_INFORMATION))
118 CHAR RTMP_GetTxPwr(
119 IN PRTMP_ADAPTER pAd,
120 IN HTTRANSMIT_SETTING HTTxMode)
122 typedef struct __TX_PWR_CFG
124 UINT8 Mode;
125 UINT8 MCS;
126 UINT16 req;
127 UINT8 shift;
128 UINT32 BitMask;
129 } TX_PWR_CFG;
131 UINT32 Value;
132 INT Idx;
133 UINT8 PhyMode;
134 CHAR CurTxPwr;
135 UINT8 TxPwrRef = 0;
136 CHAR DaltaPwr;
137 ULONG TxPwr[5];
140 TX_PWR_CFG TxPwrCfg[] = {
141 {MODE_CCK, 0, 0, 4, 0x000000f0},
142 {MODE_CCK, 1, 0, 0, 0x0000000f},
143 {MODE_CCK, 2, 0, 12, 0x0000f000},
144 {MODE_CCK, 3, 0, 8, 0x00000f00},
146 {MODE_OFDM, 0, 0, 20, 0x00f00000},
147 {MODE_OFDM, 1, 0, 16, 0x000f0000},
148 {MODE_OFDM, 2, 0, 28, 0xf0000000},
149 {MODE_OFDM, 3, 0, 24, 0x0f000000},
150 {MODE_OFDM, 4, 1, 4, 0x000000f0},
151 {MODE_OFDM, 5, 1, 0, 0x0000000f},
152 {MODE_OFDM, 6, 1, 12, 0x0000f000},
153 {MODE_OFDM, 7, 1, 8, 0x00000f00}
154 #ifdef DOT11_N_SUPPORT
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}
171 #endif // DOT11_N_SUPPORT //
173 #define MAX_TXPWR_TAB_SIZE (sizeof(TxPwrCfg) / sizeof(TX_PWR_CFG))
175 #ifdef SINGLE_SKU
176 CurTxPwr = pAd->CommonCfg.DefineMaxTxPwr;
177 #else
178 CurTxPwr = 19;
179 #endif
181 /* check Tx Power setting from UI. */
182 if (pAd->CommonCfg.TxPowerPercentage > 90)
184 else if (pAd->CommonCfg.TxPowerPercentage > 60) /* reduce Pwr for 1 dB. */
185 CurTxPwr -= 1;
186 else if (pAd->CommonCfg.TxPowerPercentage > 30) /* reduce Pwr for 3 dB. */
187 CurTxPwr -= 3;
188 else if (pAd->CommonCfg.TxPowerPercentage > 15) /* reduce Pwr for 6 dB. */
189 CurTxPwr -= 6;
190 else if (pAd->CommonCfg.TxPowerPercentage > 9) /* reduce Pwr for 9 dB. */
191 CurTxPwr -= 9;
192 else /* reduce Pwr for 12 dB. */
193 CurTxPwr -= 12;
195 if (pAd->CommonCfg.BBPCurrentBW == BW_40)
197 if (pAd->CommonCfg.CentralChannel > 14)
199 TxPwr[0] = pAd->Tx40MPwrCfgABand[0];
200 TxPwr[1] = pAd->Tx40MPwrCfgABand[1];
201 TxPwr[2] = pAd->Tx40MPwrCfgABand[2];
202 TxPwr[3] = pAd->Tx40MPwrCfgABand[3];
203 TxPwr[4] = pAd->Tx40MPwrCfgABand[4];
205 else
207 TxPwr[0] = pAd->Tx40MPwrCfgGBand[0];
208 TxPwr[1] = pAd->Tx40MPwrCfgGBand[1];
209 TxPwr[2] = pAd->Tx40MPwrCfgGBand[2];
210 TxPwr[3] = pAd->Tx40MPwrCfgGBand[3];
211 TxPwr[4] = pAd->Tx40MPwrCfgGBand[4];
214 else
216 if (pAd->CommonCfg.Channel > 14)
218 TxPwr[0] = pAd->Tx20MPwrCfgABand[0];
219 TxPwr[1] = pAd->Tx20MPwrCfgABand[1];
220 TxPwr[2] = pAd->Tx20MPwrCfgABand[2];
221 TxPwr[3] = pAd->Tx20MPwrCfgABand[3];
222 TxPwr[4] = pAd->Tx20MPwrCfgABand[4];
224 else
226 TxPwr[0] = pAd->Tx20MPwrCfgGBand[0];
227 TxPwr[1] = pAd->Tx20MPwrCfgGBand[1];
228 TxPwr[2] = pAd->Tx20MPwrCfgGBand[2];
229 TxPwr[3] = pAd->Tx20MPwrCfgGBand[3];
230 TxPwr[4] = pAd->Tx20MPwrCfgGBand[4];
235 switch(HTTxMode.field.MODE)
237 case MODE_CCK:
238 case MODE_OFDM:
239 Value = TxPwr[1];
240 TxPwrRef = (Value & 0x00000f00) >> 8;
242 break;
244 #ifdef DOT11_N_SUPPORT
245 case MODE_HTMIX:
246 case MODE_HTGREENFIELD:
247 if (pAd->CommonCfg.TxStream == 1)
249 Value = TxPwr[2];
250 TxPwrRef = (Value & 0x00000f00) >> 8;
252 else if (pAd->CommonCfg.TxStream == 2)
254 Value = TxPwr[3];
255 TxPwrRef = (Value & 0x00000f00) >> 8;
257 break;
258 #endif // DOT11_N_SUPPORT //
261 PhyMode =
262 #ifdef DOT11_N_SUPPORT
263 (HTTxMode.field.MODE == MODE_HTGREENFIELD)
264 ? MODE_HTMIX :
265 #endif // DOT11_N_SUPPORT //
266 HTTxMode.field.MODE;
268 for (Idx = 0; Idx < MAX_TXPWR_TAB_SIZE; Idx++)
270 if ((TxPwrCfg[Idx].Mode == PhyMode)
271 && (TxPwrCfg[Idx].MCS == HTTxMode.field.MCS))
273 Value = TxPwr[TxPwrCfg[Idx].req];
274 DaltaPwr = TxPwrRef - (CHAR)((Value & TxPwrCfg[Idx].BitMask)
275 >> TxPwrCfg[Idx].shift);
276 CurTxPwr -= DaltaPwr;
277 break;
281 return CurTxPwr;
285 VOID MeasureReqTabInit(
286 IN PRTMP_ADAPTER pAd)
288 NdisAllocateSpinLock(&pAd->CommonCfg.MeasureReqTabLock);
290 pAd->CommonCfg.pMeasureReqTab = kmalloc(sizeof(MEASURE_REQ_TAB), GFP_ATOMIC);
291 if (pAd->CommonCfg.pMeasureReqTab)
292 NdisZeroMemory(pAd->CommonCfg.pMeasureReqTab, sizeof(MEASURE_REQ_TAB));
293 else
294 DBGPRINT(RT_DEBUG_ERROR, ("%s Fail to alloc memory for pAd->CommonCfg.pMeasureReqTab.\n", __FUNCTION__));
296 return;
299 VOID MeasureReqTabExit(
300 IN PRTMP_ADAPTER pAd)
302 NdisFreeSpinLock(&pAd->CommonCfg.MeasureReqTabLock);
304 if (pAd->CommonCfg.pMeasureReqTab)
305 kfree(pAd->CommonCfg.pMeasureReqTab);
306 pAd->CommonCfg.pMeasureReqTab = NULL;
308 return;
311 PMEASURE_REQ_ENTRY MeasureReqLookUp(
312 IN PRTMP_ADAPTER pAd,
313 IN UINT8 DialogToken)
315 UINT HashIdx;
316 PMEASURE_REQ_TAB pTab = pAd->CommonCfg.pMeasureReqTab;
317 PMEASURE_REQ_ENTRY pEntry = NULL;
318 PMEASURE_REQ_ENTRY pPrevEntry = NULL;
320 if (pTab == NULL)
322 DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab doesn't exist.\n", __FUNCTION__));
323 return NULL;
326 RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock);
328 HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(DialogToken);
329 pEntry = pTab->Hash[HashIdx];
331 while (pEntry)
333 if (pEntry->DialogToken == DialogToken)
334 break;
335 else
337 pPrevEntry = pEntry;
338 pEntry = pEntry->pNext;
342 RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock);
344 return pEntry;
347 PMEASURE_REQ_ENTRY MeasureReqInsert(
348 IN PRTMP_ADAPTER pAd,
349 IN UINT8 DialogToken)
351 INT i;
352 ULONG HashIdx;
353 PMEASURE_REQ_TAB pTab = pAd->CommonCfg.pMeasureReqTab;
354 PMEASURE_REQ_ENTRY pEntry = NULL, pCurrEntry;
355 ULONG Now;
357 if(pTab == NULL)
359 DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab doesn't exist.\n", __FUNCTION__));
360 return NULL;
363 pEntry = MeasureReqLookUp(pAd, DialogToken);
364 if (pEntry == NULL)
366 RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock);
367 for (i = 0; i < MAX_MEASURE_REQ_TAB_SIZE; i++)
369 NdisGetSystemUpTime(&Now);
370 pEntry = &pTab->Content[i];
372 if ((pEntry->Valid == TRUE)
373 && RTMP_TIME_AFTER((unsigned long)Now, (unsigned long)(pEntry->lastTime + MQ_REQ_AGE_OUT)))
375 PMEASURE_REQ_ENTRY pPrevEntry = NULL;
376 ULONG HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken);
377 PMEASURE_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx];
379 // update Hash list
382 if (pProbeEntry == pEntry)
384 if (pPrevEntry == NULL)
386 pTab->Hash[HashIdx] = pEntry->pNext;
388 else
390 pPrevEntry->pNext = pEntry->pNext;
392 break;
395 pPrevEntry = pProbeEntry;
396 pProbeEntry = pProbeEntry->pNext;
397 } while (pProbeEntry);
399 NdisZeroMemory(pEntry, sizeof(MEASURE_REQ_ENTRY));
400 pTab->Size--;
402 break;
405 if (pEntry->Valid == FALSE)
406 break;
409 if (i < MAX_MEASURE_REQ_TAB_SIZE)
411 NdisGetSystemUpTime(&Now);
412 pEntry->lastTime = Now;
413 pEntry->Valid = TRUE;
414 pEntry->DialogToken = DialogToken;
415 pTab->Size++;
417 else
419 pEntry = NULL;
420 DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab tab full.\n", __FUNCTION__));
423 // add this Neighbor entry into HASH table
424 if (pEntry)
426 HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(DialogToken);
427 if (pTab->Hash[HashIdx] == NULL)
429 pTab->Hash[HashIdx] = pEntry;
431 else
433 pCurrEntry = pTab->Hash[HashIdx];
434 while (pCurrEntry->pNext != NULL)
435 pCurrEntry = pCurrEntry->pNext;
436 pCurrEntry->pNext = pEntry;
440 RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock);
443 return pEntry;
446 VOID MeasureReqDelete(
447 IN PRTMP_ADAPTER pAd,
448 IN UINT8 DialogToken)
450 PMEASURE_REQ_TAB pTab = pAd->CommonCfg.pMeasureReqTab;
451 PMEASURE_REQ_ENTRY pEntry = NULL;
453 if(pTab == NULL)
455 DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab doesn't exist.\n", __FUNCTION__));
456 return;
459 // if empty, return
460 if (pTab->Size == 0)
462 DBGPRINT(RT_DEBUG_ERROR, ("pMeasureReqTab empty.\n"));
463 return;
466 pEntry = MeasureReqLookUp(pAd, DialogToken);
467 if (pEntry != NULL)
469 PMEASURE_REQ_ENTRY pPrevEntry = NULL;
470 ULONG HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken);
471 PMEASURE_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx];
473 RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock);
474 // update Hash list
477 if (pProbeEntry == pEntry)
479 if (pPrevEntry == NULL)
481 pTab->Hash[HashIdx] = pEntry->pNext;
483 else
485 pPrevEntry->pNext = pEntry->pNext;
487 break;
490 pPrevEntry = pProbeEntry;
491 pProbeEntry = pProbeEntry->pNext;
492 } while (pProbeEntry);
494 NdisZeroMemory(pEntry, sizeof(MEASURE_REQ_ENTRY));
495 pTab->Size--;
497 RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock);
500 return;
503 VOID TpcReqTabInit(
504 IN PRTMP_ADAPTER pAd)
506 NdisAllocateSpinLock(&pAd->CommonCfg.TpcReqTabLock);
508 pAd->CommonCfg.pTpcReqTab = kmalloc(sizeof(TPC_REQ_TAB), GFP_ATOMIC);
509 if (pAd->CommonCfg.pTpcReqTab)
510 NdisZeroMemory(pAd->CommonCfg.pTpcReqTab, sizeof(TPC_REQ_TAB));
511 else
512 DBGPRINT(RT_DEBUG_ERROR, ("%s Fail to alloc memory for pAd->CommonCfg.pTpcReqTab.\n", __FUNCTION__));
514 return;
517 VOID TpcReqTabExit(
518 IN PRTMP_ADAPTER pAd)
520 NdisFreeSpinLock(&pAd->CommonCfg.TpcReqTabLock);
522 if (pAd->CommonCfg.pTpcReqTab)
523 kfree(pAd->CommonCfg.pTpcReqTab);
524 pAd->CommonCfg.pTpcReqTab = NULL;
526 return;
529 static PTPC_REQ_ENTRY TpcReqLookUp(
530 IN PRTMP_ADAPTER pAd,
531 IN UINT8 DialogToken)
533 UINT HashIdx;
534 PTPC_REQ_TAB pTab = pAd->CommonCfg.pTpcReqTab;
535 PTPC_REQ_ENTRY pEntry = NULL;
536 PTPC_REQ_ENTRY pPrevEntry = NULL;
538 if (pTab == NULL)
540 DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab doesn't exist.\n", __FUNCTION__));
541 return NULL;
544 RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock);
546 HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(DialogToken);
547 pEntry = pTab->Hash[HashIdx];
549 while (pEntry)
551 if (pEntry->DialogToken == DialogToken)
552 break;
553 else
555 pPrevEntry = pEntry;
556 pEntry = pEntry->pNext;
560 RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock);
562 return pEntry;
566 static PTPC_REQ_ENTRY TpcReqInsert(
567 IN PRTMP_ADAPTER pAd,
568 IN UINT8 DialogToken)
570 INT i;
571 ULONG HashIdx;
572 PTPC_REQ_TAB pTab = pAd->CommonCfg.pTpcReqTab;
573 PTPC_REQ_ENTRY pEntry = NULL, pCurrEntry;
574 ULONG Now;
576 if(pTab == NULL)
578 DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab doesn't exist.\n", __FUNCTION__));
579 return NULL;
582 pEntry = TpcReqLookUp(pAd, DialogToken);
583 if (pEntry == NULL)
585 RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock);
586 for (i = 0; i < MAX_TPC_REQ_TAB_SIZE; i++)
588 NdisGetSystemUpTime(&Now);
589 pEntry = &pTab->Content[i];
591 if ((pEntry->Valid == TRUE)
592 && RTMP_TIME_AFTER((unsigned long)Now, (unsigned long)(pEntry->lastTime + TPC_REQ_AGE_OUT)))
594 PTPC_REQ_ENTRY pPrevEntry = NULL;
595 ULONG HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken);
596 PTPC_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx];
598 // update Hash list
601 if (pProbeEntry == pEntry)
603 if (pPrevEntry == NULL)
605 pTab->Hash[HashIdx] = pEntry->pNext;
607 else
609 pPrevEntry->pNext = pEntry->pNext;
611 break;
614 pPrevEntry = pProbeEntry;
615 pProbeEntry = pProbeEntry->pNext;
616 } while (pProbeEntry);
618 NdisZeroMemory(pEntry, sizeof(TPC_REQ_ENTRY));
619 pTab->Size--;
621 break;
624 if (pEntry->Valid == FALSE)
625 break;
628 if (i < MAX_TPC_REQ_TAB_SIZE)
630 NdisGetSystemUpTime(&Now);
631 pEntry->lastTime = Now;
632 pEntry->Valid = TRUE;
633 pEntry->DialogToken = DialogToken;
634 pTab->Size++;
636 else
638 pEntry = NULL;
639 DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab tab full.\n", __FUNCTION__));
642 // add this Neighbor entry into HASH table
643 if (pEntry)
645 HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(DialogToken);
646 if (pTab->Hash[HashIdx] == NULL)
648 pTab->Hash[HashIdx] = pEntry;
650 else
652 pCurrEntry = pTab->Hash[HashIdx];
653 while (pCurrEntry->pNext != NULL)
654 pCurrEntry = pCurrEntry->pNext;
655 pCurrEntry->pNext = pEntry;
659 RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock);
662 return pEntry;
665 static VOID TpcReqDelete(
666 IN PRTMP_ADAPTER pAd,
667 IN UINT8 DialogToken)
669 PTPC_REQ_TAB pTab = pAd->CommonCfg.pTpcReqTab;
670 PTPC_REQ_ENTRY pEntry = NULL;
672 if(pTab == NULL)
674 DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab doesn't exist.\n", __FUNCTION__));
675 return;
678 // if empty, return
679 if (pTab->Size == 0)
681 DBGPRINT(RT_DEBUG_ERROR, ("pTpcReqTab empty.\n"));
682 return;
685 pEntry = TpcReqLookUp(pAd, DialogToken);
686 if (pEntry != NULL)
688 PTPC_REQ_ENTRY pPrevEntry = NULL;
689 ULONG HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken);
690 PTPC_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx];
692 RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock);
693 // update Hash list
696 if (pProbeEntry == pEntry)
698 if (pPrevEntry == NULL)
700 pTab->Hash[HashIdx] = pEntry->pNext;
702 else
704 pPrevEntry->pNext = pEntry->pNext;
706 break;
709 pPrevEntry = pProbeEntry;
710 pProbeEntry = pProbeEntry->pNext;
711 } while (pProbeEntry);
713 NdisZeroMemory(pEntry, sizeof(TPC_REQ_ENTRY));
714 pTab->Size--;
716 RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock);
719 return;
723 ==========================================================================
724 Description:
725 Get Current TimeS tamp.
727 Parametrs:
729 Return : Current Time Stamp.
730 ==========================================================================
732 static UINT64 GetCurrentTimeStamp(
733 IN PRTMP_ADAPTER pAd)
735 // get current time stamp.
736 return 0;
740 ==========================================================================
741 Description:
742 Get Current Transmit Power.
744 Parametrs:
746 Return : Current Time Stamp.
747 ==========================================================================
749 static UINT8 GetCurTxPwr(
750 IN PRTMP_ADAPTER pAd,
751 IN UINT8 Wcid)
753 return 16; /* 16 dBm */
757 ==========================================================================
758 Description:
759 Get Current Transmit Power.
761 Parametrs:
763 Return : Current Time Stamp.
764 ==========================================================================
766 VOID InsertChannelRepIE(
767 IN PRTMP_ADAPTER pAd,
768 OUT PUCHAR pFrameBuf,
769 OUT PULONG pFrameLen,
770 IN PSTRING pCountry,
771 IN UINT8 RegulatoryClass)
773 ULONG TempLen;
774 UINT8 Len;
775 UINT8 IEId = IE_AP_CHANNEL_REPORT;
776 PUCHAR pChListPtr = NULL;
778 Len = 1;
779 if (strncmp(pCountry, "US", 2) == 0)
781 if (RegulatoryClass >= USA_REGULATORY_INFO_SIZE)
783 DBGPRINT(RT_DEBUG_ERROR, ("%s: USA Unknow Requlatory class (%d)\n",
784 __FUNCTION__, RegulatoryClass));
785 return;
788 Len += USARegulatoryInfo[RegulatoryClass].ChannelSet.NumberOfChannels;
789 pChListPtr = USARegulatoryInfo[RegulatoryClass].ChannelSet.ChannelList;
791 else if (strncmp(pCountry, "JP", 2) == 0)
793 if (RegulatoryClass >= JP_REGULATORY_INFO_SIZE)
795 DBGPRINT(RT_DEBUG_ERROR, ("%s: JP Unknow Requlatory class (%d)\n",
796 __FUNCTION__, RegulatoryClass));
797 return;
800 Len += JapanRegulatoryInfo[RegulatoryClass].ChannelSet.NumberOfChannels;
801 pChListPtr = JapanRegulatoryInfo[RegulatoryClass].ChannelSet.ChannelList;
803 else
805 DBGPRINT(RT_DEBUG_ERROR, ("%s: Unknow Country (%s)\n",
806 __FUNCTION__, pCountry));
807 return;
810 MakeOutgoingFrame(pFrameBuf, &TempLen,
811 1, &IEId,
812 1, &Len,
813 1, &RegulatoryClass,
814 Len -1, pChListPtr,
815 END_OF_ARGS);
817 *pFrameLen = *pFrameLen + TempLen;
819 return;
823 ==========================================================================
824 Description:
825 Insert Dialog Token into frame.
827 Parametrs:
828 1. frame buffer pointer.
829 2. frame length.
830 3. Dialog token.
832 Return : None.
833 ==========================================================================
835 VOID InsertDialogToken(
836 IN PRTMP_ADAPTER pAd,
837 OUT PUCHAR pFrameBuf,
838 OUT PULONG pFrameLen,
839 IN UINT8 DialogToken)
841 ULONG TempLen;
842 MakeOutgoingFrame(pFrameBuf, &TempLen,
843 1, &DialogToken,
844 END_OF_ARGS);
846 *pFrameLen = *pFrameLen + TempLen;
848 return;
852 ==========================================================================
853 Description:
854 Insert TPC Request IE into frame.
856 Parametrs:
857 1. frame buffer pointer.
858 2. frame length.
860 Return : None.
861 ==========================================================================
863 static VOID InsertTpcReqIE(
864 IN PRTMP_ADAPTER pAd,
865 OUT PUCHAR pFrameBuf,
866 OUT PULONG pFrameLen)
868 ULONG TempLen;
869 ULONG Len = 0;
870 UINT8 ElementID = IE_TPC_REQUEST;
872 MakeOutgoingFrame(pFrameBuf, &TempLen,
873 1, &ElementID,
874 1, &Len,
875 END_OF_ARGS);
877 *pFrameLen = *pFrameLen + TempLen;
879 return;
883 ==========================================================================
884 Description:
885 Insert TPC Report IE into frame.
887 Parametrs:
888 1. frame buffer pointer.
889 2. frame length.
890 3. Transmit Power.
891 4. Link Margin.
893 Return : None.
894 ==========================================================================
896 VOID InsertTpcReportIE(
897 IN PRTMP_ADAPTER pAd,
898 OUT PUCHAR pFrameBuf,
899 OUT PULONG pFrameLen,
900 IN UINT8 TxPwr,
901 IN UINT8 LinkMargin)
903 ULONG TempLen;
904 ULONG Len = sizeof(TPC_REPORT_INFO);
905 UINT8 ElementID = IE_TPC_REPORT;
906 TPC_REPORT_INFO TpcReportIE;
908 TpcReportIE.TxPwr = TxPwr;
909 TpcReportIE.LinkMargin = LinkMargin;
911 MakeOutgoingFrame(pFrameBuf, &TempLen,
912 1, &ElementID,
913 1, &Len,
914 Len, &TpcReportIE,
915 END_OF_ARGS);
917 *pFrameLen = *pFrameLen + TempLen;
920 return;
924 ==========================================================================
925 Description:
926 Insert Channel Switch Announcement IE into frame.
928 Parametrs:
929 1. frame buffer pointer.
930 2. frame length.
931 3. channel switch announcement mode.
932 4. new selected channel.
933 5. channel switch announcement count.
935 Return : None.
936 ==========================================================================
938 static VOID InsertChSwAnnIE(
939 IN PRTMP_ADAPTER pAd,
940 OUT PUCHAR pFrameBuf,
941 OUT PULONG pFrameLen,
942 IN UINT8 ChSwMode,
943 IN UINT8 NewChannel,
944 IN UINT8 ChSwCnt)
946 ULONG TempLen;
947 ULONG Len = sizeof(CH_SW_ANN_INFO);
948 UINT8 ElementID = IE_CHANNEL_SWITCH_ANNOUNCEMENT;
949 CH_SW_ANN_INFO ChSwAnnIE;
951 ChSwAnnIE.ChSwMode = ChSwMode;
952 ChSwAnnIE.Channel = NewChannel;
953 ChSwAnnIE.ChSwCnt = ChSwCnt;
955 MakeOutgoingFrame(pFrameBuf, &TempLen,
956 1, &ElementID,
957 1, &Len,
958 Len, &ChSwAnnIE,
959 END_OF_ARGS);
961 *pFrameLen = *pFrameLen + TempLen;
964 return;
968 ==========================================================================
969 Description:
970 Insert Measure Request IE into frame.
972 Parametrs:
973 1. frame buffer pointer.
974 2. frame length.
975 3. Measure Token.
976 4. Measure Request Mode.
977 5. Measure Request Type.
978 6. Measure Channel.
979 7. Measure Start time.
980 8. Measure Duration.
983 Return : None.
984 ==========================================================================
986 static VOID InsertMeasureReqIE(
987 IN PRTMP_ADAPTER pAd,
988 OUT PUCHAR pFrameBuf,
989 OUT PULONG pFrameLen,
990 IN UINT8 Len,
991 IN PMEASURE_REQ_INFO pMeasureReqIE)
993 ULONG TempLen;
994 UINT8 ElementID = IE_MEASUREMENT_REQUEST;
996 MakeOutgoingFrame(pFrameBuf, &TempLen,
997 1, &ElementID,
998 1, &Len,
999 sizeof(MEASURE_REQ_INFO), pMeasureReqIE,
1000 END_OF_ARGS);
1002 *pFrameLen = *pFrameLen + TempLen;
1004 return;
1008 ==========================================================================
1009 Description:
1010 Insert Measure Report IE into frame.
1012 Parametrs:
1013 1. frame buffer pointer.
1014 2. frame length.
1015 3. Measure Token.
1016 4. Measure Request Mode.
1017 5. Measure Request Type.
1018 6. Length of Report Infomation
1019 7. Pointer of Report Infomation Buffer.
1021 Return : None.
1022 ==========================================================================
1024 static VOID InsertMeasureReportIE(
1025 IN PRTMP_ADAPTER pAd,
1026 OUT PUCHAR pFrameBuf,
1027 OUT PULONG pFrameLen,
1028 IN PMEASURE_REPORT_INFO pMeasureReportIE,
1029 IN UINT8 ReportLnfoLen,
1030 IN PUINT8 pReportInfo)
1032 ULONG TempLen;
1033 ULONG Len;
1034 UINT8 ElementID = IE_MEASUREMENT_REPORT;
1036 Len = sizeof(MEASURE_REPORT_INFO) + ReportLnfoLen;
1038 MakeOutgoingFrame(pFrameBuf, &TempLen,
1039 1, &ElementID,
1040 1, &Len,
1041 Len, pMeasureReportIE,
1042 END_OF_ARGS);
1044 *pFrameLen = *pFrameLen + TempLen;
1046 if ((ReportLnfoLen > 0) && (pReportInfo != NULL))
1048 MakeOutgoingFrame(pFrameBuf + *pFrameLen, &TempLen,
1049 ReportLnfoLen, pReportInfo,
1050 END_OF_ARGS);
1052 *pFrameLen = *pFrameLen + TempLen;
1054 return;
1058 ==========================================================================
1059 Description:
1060 Prepare Measurement request action frame and enqueue it into
1061 management queue waiting for transmition.
1063 Parametrs:
1064 1. the destination mac address of the frame.
1066 Return : None.
1067 ==========================================================================
1069 VOID MakeMeasurementReqFrame(
1070 IN PRTMP_ADAPTER pAd,
1071 OUT PUCHAR pOutBuffer,
1072 OUT PULONG pFrameLen,
1073 IN UINT8 TotalLen,
1074 IN UINT8 Category,
1075 IN UINT8 Action,
1076 IN UINT8 MeasureToken,
1077 IN UINT8 MeasureReqMode,
1078 IN UINT8 MeasureReqType,
1079 IN UINT8 NumOfRepetitions)
1081 ULONG TempLen;
1082 MEASURE_REQ_INFO MeasureReqIE;
1084 InsertActField(pAd, (pOutBuffer + *pFrameLen), pFrameLen, Category, Action);
1086 // fill Dialog Token
1087 InsertDialogToken(pAd, (pOutBuffer + *pFrameLen), pFrameLen, MeasureToken);
1089 /* fill Number of repetitions. */
1090 if (Category == CATEGORY_RM)
1092 MakeOutgoingFrame((pOutBuffer+*pFrameLen), &TempLen,
1093 2, &NumOfRepetitions,
1094 END_OF_ARGS);
1096 *pFrameLen += TempLen;
1099 // prepare Measurement IE.
1100 NdisZeroMemory(&MeasureReqIE, sizeof(MEASURE_REQ_INFO));
1101 MeasureReqIE.Token = MeasureToken;
1102 MeasureReqIE.ReqMode.word = MeasureReqMode;
1103 MeasureReqIE.ReqType = MeasureReqType;
1104 InsertMeasureReqIE(pAd, (pOutBuffer+*pFrameLen), pFrameLen,
1105 TotalLen, &MeasureReqIE);
1107 return;
1111 ==========================================================================
1112 Description:
1113 Prepare Measurement report action frame and enqueue it into
1114 management queue waiting for transmition.
1116 Parametrs:
1117 1. the destination mac address of the frame.
1119 Return : None.
1120 ==========================================================================
1122 VOID EnqueueMeasurementRep(
1123 IN PRTMP_ADAPTER pAd,
1124 IN PUCHAR pDA,
1125 IN UINT8 DialogToken,
1126 IN UINT8 MeasureToken,
1127 IN UINT8 MeasureReqMode,
1128 IN UINT8 MeasureReqType,
1129 IN UINT8 ReportInfoLen,
1130 IN PUINT8 pReportInfo)
1132 PUCHAR pOutBuffer = NULL;
1133 NDIS_STATUS NStatus;
1134 ULONG FrameLen;
1135 HEADER_802_11 ActHdr;
1136 MEASURE_REPORT_INFO MeasureRepIE;
1138 // build action frame header.
1139 MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
1140 pAd->CurrentAddress);
1142 NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory
1143 if(NStatus != NDIS_STATUS_SUCCESS)
1145 DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __FUNCTION__));
1146 return;
1148 NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11));
1149 FrameLen = sizeof(HEADER_802_11);
1151 InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_MRP);
1153 // fill Dialog Token
1154 InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken);
1156 // prepare Measurement IE.
1157 NdisZeroMemory(&MeasureRepIE, sizeof(MEASURE_REPORT_INFO));
1158 MeasureRepIE.Token = MeasureToken;
1159 MeasureRepIE.ReportMode = MeasureReqMode;
1160 MeasureRepIE.ReportType = MeasureReqType;
1161 InsertMeasureReportIE(pAd, (pOutBuffer + FrameLen), &FrameLen, &MeasureRepIE, ReportInfoLen, pReportInfo);
1163 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1164 MlmeFreeMemory(pAd, pOutBuffer);
1166 return;
1170 ==========================================================================
1171 Description:
1172 Prepare TPC Request action frame and enqueue it into
1173 management queue waiting for transmition.
1175 Parametrs:
1176 1. the destination mac address of the frame.
1178 Return : None.
1179 ==========================================================================
1181 VOID EnqueueTPCReq(
1182 IN PRTMP_ADAPTER pAd,
1183 IN PUCHAR pDA,
1184 IN UCHAR DialogToken)
1186 PUCHAR pOutBuffer = NULL;
1187 NDIS_STATUS NStatus;
1188 ULONG FrameLen;
1190 HEADER_802_11 ActHdr;
1192 // build action frame header.
1193 MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
1194 pAd->CurrentAddress);
1196 NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory
1197 if(NStatus != NDIS_STATUS_SUCCESS)
1199 DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __FUNCTION__));
1200 return;
1202 NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11));
1203 FrameLen = sizeof(HEADER_802_11);
1205 InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_TPCRQ);
1207 // fill Dialog Token
1208 InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken);
1210 // Insert TPC Request IE.
1211 InsertTpcReqIE(pAd, (pOutBuffer + FrameLen), &FrameLen);
1213 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1214 MlmeFreeMemory(pAd, pOutBuffer);
1216 return;
1220 ==========================================================================
1221 Description:
1222 Prepare TPC Report action frame and enqueue it into
1223 management queue waiting for transmition.
1225 Parametrs:
1226 1. the destination mac address of the frame.
1228 Return : None.
1229 ==========================================================================
1231 VOID EnqueueTPCRep(
1232 IN PRTMP_ADAPTER pAd,
1233 IN PUCHAR pDA,
1234 IN UINT8 DialogToken,
1235 IN UINT8 TxPwr,
1236 IN UINT8 LinkMargin)
1238 PUCHAR pOutBuffer = NULL;
1239 NDIS_STATUS NStatus;
1240 ULONG FrameLen;
1242 HEADER_802_11 ActHdr;
1244 // build action frame header.
1245 MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
1246 pAd->CurrentAddress);
1248 NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory
1249 if(NStatus != NDIS_STATUS_SUCCESS)
1251 DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __FUNCTION__));
1252 return;
1254 NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11));
1255 FrameLen = sizeof(HEADER_802_11);
1257 InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_TPCRP);
1259 // fill Dialog Token
1260 InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken);
1262 // Insert TPC Request IE.
1263 InsertTpcReportIE(pAd, (pOutBuffer + FrameLen), &FrameLen, TxPwr, LinkMargin);
1265 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1266 MlmeFreeMemory(pAd, pOutBuffer);
1268 return;
1272 ==========================================================================
1273 Description:
1274 Prepare Channel Switch Announcement action frame and enqueue it into
1275 management queue waiting for transmition.
1277 Parametrs:
1278 1. the destination mac address of the frame.
1279 2. Channel switch announcement mode.
1280 2. a New selected channel.
1282 Return : None.
1283 ==========================================================================
1285 VOID EnqueueChSwAnn(
1286 IN PRTMP_ADAPTER pAd,
1287 IN PUCHAR pDA,
1288 IN UINT8 ChSwMode,
1289 IN UINT8 NewCh)
1291 PUCHAR pOutBuffer = NULL;
1292 NDIS_STATUS NStatus;
1293 ULONG FrameLen;
1295 HEADER_802_11 ActHdr;
1297 // build action frame header.
1298 MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
1299 pAd->CurrentAddress);
1301 NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory
1302 if(NStatus != NDIS_STATUS_SUCCESS)
1304 DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __FUNCTION__));
1305 return;
1307 NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11));
1308 FrameLen = sizeof(HEADER_802_11);
1310 InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_CHANNEL_SWITCH);
1312 InsertChSwAnnIE(pAd, (pOutBuffer + FrameLen), &FrameLen, ChSwMode, NewCh, 0);
1314 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1315 MlmeFreeMemory(pAd, pOutBuffer);
1317 return;
1320 static BOOLEAN DfsRequirementCheck(
1321 IN PRTMP_ADAPTER pAd,
1322 IN UINT8 Channel)
1324 BOOLEAN Result = FALSE;
1325 INT i;
1329 // check DFS procedure is running.
1330 // make sure DFS procedure won't start twice.
1331 if (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)
1333 Result = FALSE;
1334 break;
1337 // check the new channel carried from Channel Switch Announcemnet is valid.
1338 for (i=0; i<pAd->ChannelListNum; i++)
1340 if ((Channel == pAd->ChannelList[i].Channel)
1341 &&(pAd->ChannelList[i].RemainingTimeForUse == 0))
1343 // found radar signal in the channel. the channel can't use at least for 30 minutes.
1344 pAd->ChannelList[i].RemainingTimeForUse = 1800;//30 min = 1800 sec
1345 Result = TRUE;
1346 break;
1349 } while(FALSE);
1351 return Result;
1354 VOID NotifyChSwAnnToPeerAPs(
1355 IN PRTMP_ADAPTER pAd,
1356 IN PUCHAR pRA,
1357 IN PUCHAR pTA,
1358 IN UINT8 ChSwMode,
1359 IN UINT8 Channel)
1361 #ifdef WDS_SUPPORT
1362 if (!((pRA[0] & 0xff) == 0xff)) // is pRA a broadcase address.
1364 INT i;
1365 // info neighbor APs that Radar signal found throgh WDS link.
1366 for (i = 0; i < MAX_WDS_ENTRY; i++)
1368 if (ValidWdsEntry(pAd, i))
1370 PUCHAR pDA = pAd->WdsTab.WdsEntry[i].PeerWdsAddr;
1372 // DA equal to SA. have no necessary orignal AP which found Radar signal.
1373 if (MAC_ADDR_EQUAL(pTA, pDA))
1374 continue;
1376 // send Channel Switch Action frame to info Neighbro APs.
1377 EnqueueChSwAnn(pAd, pDA, ChSwMode, Channel);
1381 #endif // WDS_SUPPORT //
1384 static VOID StartDFSProcedure(
1385 IN PRTMP_ADAPTER pAd,
1386 IN UCHAR Channel,
1387 IN UINT8 ChSwMode)
1389 // start DFS procedure
1390 pAd->CommonCfg.Channel = Channel;
1391 #ifdef DOT11_N_SUPPORT
1392 N_ChannelCheck(pAd);
1393 #endif // DOT11_N_SUPPORT //
1394 pAd->CommonCfg.RadarDetect.RDMode = RD_SWITCHING_MODE;
1395 pAd->CommonCfg.RadarDetect.CSCount = 0;
1399 ==========================================================================
1400 Description:
1401 Channel Switch Announcement action frame sanity check.
1403 Parametrs:
1404 1. MLME message containing the received frame
1405 2. message length.
1406 3. Channel switch announcement infomation buffer.
1409 Return : None.
1410 ==========================================================================
1414 Channel Switch Announcement IE.
1415 +----+-----+-----------+------------+-----------+
1416 | ID | Len |Ch Sw Mode | New Ch Num | Ch Sw Cnt |
1417 +----+-----+-----------+------------+-----------+
1418 1 1 1 1 1
1420 static BOOLEAN PeerChSwAnnSanity(
1421 IN PRTMP_ADAPTER pAd,
1422 IN VOID *pMsg,
1423 IN ULONG MsgLen,
1424 OUT PCH_SW_ANN_INFO pChSwAnnInfo)
1426 PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
1427 PUCHAR pFramePtr = Fr->Octet;
1428 BOOLEAN result = FALSE;
1429 PEID_STRUCT eid_ptr;
1431 // skip 802.11 header.
1432 MsgLen -= sizeof(HEADER_802_11);
1434 // skip category and action code.
1435 pFramePtr += 2;
1436 MsgLen -= 2;
1438 if (pChSwAnnInfo == NULL)
1439 return result;
1441 eid_ptr = (PEID_STRUCT)pFramePtr;
1442 while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
1444 switch(eid_ptr->Eid)
1446 case IE_CHANNEL_SWITCH_ANNOUNCEMENT:
1447 NdisMoveMemory(&pChSwAnnInfo->ChSwMode, eid_ptr->Octet, 1);
1448 NdisMoveMemory(&pChSwAnnInfo->Channel, eid_ptr->Octet + 1, 1);
1449 NdisMoveMemory(&pChSwAnnInfo->ChSwCnt, eid_ptr->Octet + 2, 1);
1451 result = TRUE;
1452 break;
1454 default:
1455 break;
1457 eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
1460 return result;
1464 ==========================================================================
1465 Description:
1466 Measurement request action frame sanity check.
1468 Parametrs:
1469 1. MLME message containing the received frame
1470 2. message length.
1471 3. Measurement request infomation buffer.
1473 Return : None.
1474 ==========================================================================
1476 static BOOLEAN PeerMeasureReqSanity(
1477 IN PRTMP_ADAPTER pAd,
1478 IN VOID *pMsg,
1479 IN ULONG MsgLen,
1480 OUT PUINT8 pDialogToken,
1481 OUT PMEASURE_REQ_INFO pMeasureReqInfo,
1482 OUT PMEASURE_REQ pMeasureReq)
1484 PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
1485 PUCHAR pFramePtr = Fr->Octet;
1486 BOOLEAN result = FALSE;
1487 PEID_STRUCT eid_ptr;
1488 PUCHAR ptr;
1489 UINT64 MeasureStartTime;
1490 UINT16 MeasureDuration;
1492 // skip 802.11 header.
1493 MsgLen -= sizeof(HEADER_802_11);
1495 // skip category and action code.
1496 pFramePtr += 2;
1497 MsgLen -= 2;
1499 if (pMeasureReqInfo == NULL)
1500 return result;
1502 NdisMoveMemory(pDialogToken, pFramePtr, 1);
1503 pFramePtr += 1;
1504 MsgLen -= 1;
1506 eid_ptr = (PEID_STRUCT)pFramePtr;
1507 while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
1509 switch(eid_ptr->Eid)
1511 case IE_MEASUREMENT_REQUEST:
1512 NdisMoveMemory(&pMeasureReqInfo->Token, eid_ptr->Octet, 1);
1513 NdisMoveMemory(&pMeasureReqInfo->ReqMode.word, eid_ptr->Octet + 1, 1);
1514 NdisMoveMemory(&pMeasureReqInfo->ReqType, eid_ptr->Octet + 2, 1);
1515 ptr = (PUCHAR)(eid_ptr->Octet + 3);
1516 NdisMoveMemory(&pMeasureReq->ChNum, ptr, 1);
1517 NdisMoveMemory(&MeasureStartTime, ptr + 1, 8);
1518 pMeasureReq->MeasureStartTime = SWAP64(MeasureStartTime);
1519 NdisMoveMemory(&MeasureDuration, ptr + 9, 2);
1520 pMeasureReq->MeasureDuration = SWAP16(MeasureDuration);
1522 result = TRUE;
1523 break;
1525 default:
1526 break;
1528 eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
1531 return result;
1535 ==========================================================================
1536 Description:
1537 Measurement report action frame sanity check.
1539 Parametrs:
1540 1. MLME message containing the received frame
1541 2. message length.
1542 3. Measurement report infomation buffer.
1543 4. basic report infomation buffer.
1545 Return : None.
1546 ==========================================================================
1550 Measurement Report IE.
1551 +----+-----+-------+-------------+--------------+----------------+
1552 | ID | Len | Token | Report Mode | Measure Type | Measure Report |
1553 +----+-----+-------+-------------+--------------+----------------+
1554 1 1 1 1 1 variable
1556 Basic Report.
1557 +--------+------------+----------+-----+
1558 | Ch Num | Start Time | Duration | Map |
1559 +--------+------------+----------+-----+
1560 1 8 2 1
1562 Map Field Bit Format.
1563 +-----+---------------+---------------------+-------+------------+----------+
1564 | Bss | OFDM Preamble | Unidentified signal | Radar | Unmeasured | Reserved |
1565 +-----+---------------+---------------------+-------+------------+----------+
1566 0 1 2 3 4 5-7
1568 static BOOLEAN PeerMeasureReportSanity(
1569 IN PRTMP_ADAPTER pAd,
1570 IN VOID *pMsg,
1571 IN ULONG MsgLen,
1572 OUT PUINT8 pDialogToken,
1573 OUT PMEASURE_REPORT_INFO pMeasureReportInfo,
1574 OUT PUINT8 pReportBuf)
1576 PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
1577 PUCHAR pFramePtr = Fr->Octet;
1578 BOOLEAN result = FALSE;
1579 PEID_STRUCT eid_ptr;
1580 PUCHAR ptr;
1582 // skip 802.11 header.
1583 MsgLen -= sizeof(HEADER_802_11);
1585 // skip category and action code.
1586 pFramePtr += 2;
1587 MsgLen -= 2;
1589 if (pMeasureReportInfo == NULL)
1590 return result;
1592 NdisMoveMemory(pDialogToken, pFramePtr, 1);
1593 pFramePtr += 1;
1594 MsgLen -= 1;
1596 eid_ptr = (PEID_STRUCT)pFramePtr;
1597 while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
1599 switch(eid_ptr->Eid)
1601 case IE_MEASUREMENT_REPORT:
1602 NdisMoveMemory(&pMeasureReportInfo->Token, eid_ptr->Octet, 1);
1603 NdisMoveMemory(&pMeasureReportInfo->ReportMode, eid_ptr->Octet + 1, 1);
1604 NdisMoveMemory(&pMeasureReportInfo->ReportType, eid_ptr->Octet + 2, 1);
1605 if (pMeasureReportInfo->ReportType == RM_BASIC)
1607 PMEASURE_BASIC_REPORT pReport = (PMEASURE_BASIC_REPORT)pReportBuf;
1608 ptr = (PUCHAR)(eid_ptr->Octet + 3);
1609 NdisMoveMemory(&pReport->ChNum, ptr, 1);
1610 NdisMoveMemory(&pReport->MeasureStartTime, ptr + 1, 8);
1611 NdisMoveMemory(&pReport->MeasureDuration, ptr + 9, 2);
1612 NdisMoveMemory(&pReport->Map, ptr + 11, 1);
1615 else if (pMeasureReportInfo->ReportType == RM_CCA)
1617 PMEASURE_CCA_REPORT pReport = (PMEASURE_CCA_REPORT)pReportBuf;
1618 ptr = (PUCHAR)(eid_ptr->Octet + 3);
1619 NdisMoveMemory(&pReport->ChNum, ptr, 1);
1620 NdisMoveMemory(&pReport->MeasureStartTime, ptr + 1, 8);
1621 NdisMoveMemory(&pReport->MeasureDuration, ptr + 9, 2);
1622 NdisMoveMemory(&pReport->CCA_Busy_Fraction, ptr + 11, 1);
1625 else if (pMeasureReportInfo->ReportType == RM_RPI_HISTOGRAM)
1627 PMEASURE_RPI_REPORT pReport = (PMEASURE_RPI_REPORT)pReportBuf;
1628 ptr = (PUCHAR)(eid_ptr->Octet + 3);
1629 NdisMoveMemory(&pReport->ChNum, ptr, 1);
1630 NdisMoveMemory(&pReport->MeasureStartTime, ptr + 1, 8);
1631 NdisMoveMemory(&pReport->MeasureDuration, ptr + 9, 2);
1632 NdisMoveMemory(&pReport->RPI_Density, ptr + 11, 8);
1634 result = TRUE;
1635 break;
1637 default:
1638 break;
1640 eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
1643 return result;
1647 ==========================================================================
1648 Description:
1649 TPC Request action frame sanity check.
1651 Parametrs:
1652 1. MLME message containing the received frame
1653 2. message length.
1654 3. Dialog Token.
1656 Return : None.
1657 ==========================================================================
1659 static BOOLEAN PeerTpcReqSanity(
1660 IN PRTMP_ADAPTER pAd,
1661 IN VOID *pMsg,
1662 IN ULONG MsgLen,
1663 OUT PUINT8 pDialogToken)
1665 PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
1666 PUCHAR pFramePtr = Fr->Octet;
1667 BOOLEAN result = FALSE;
1668 PEID_STRUCT eid_ptr;
1670 MsgLen -= sizeof(HEADER_802_11);
1672 // skip category and action code.
1673 pFramePtr += 2;
1674 MsgLen -= 2;
1676 if (pDialogToken == NULL)
1677 return result;
1679 NdisMoveMemory(pDialogToken, pFramePtr, 1);
1680 pFramePtr += 1;
1681 MsgLen -= 1;
1683 eid_ptr = (PEID_STRUCT)pFramePtr;
1684 while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
1686 switch(eid_ptr->Eid)
1688 case IE_TPC_REQUEST:
1689 result = TRUE;
1690 break;
1692 default:
1693 break;
1695 eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
1698 return result;
1702 ==========================================================================
1703 Description:
1704 TPC Report action frame sanity check.
1706 Parametrs:
1707 1. MLME message containing the received frame
1708 2. message length.
1709 3. Dialog Token.
1710 4. TPC Report IE.
1712 Return : None.
1713 ==========================================================================
1715 static BOOLEAN PeerTpcRepSanity(
1716 IN PRTMP_ADAPTER pAd,
1717 IN VOID *pMsg,
1718 IN ULONG MsgLen,
1719 OUT PUINT8 pDialogToken,
1720 OUT PTPC_REPORT_INFO pTpcRepInfo)
1722 PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
1723 PUCHAR pFramePtr = Fr->Octet;
1724 BOOLEAN result = FALSE;
1725 PEID_STRUCT eid_ptr;
1727 MsgLen -= sizeof(HEADER_802_11);
1729 // skip category and action code.
1730 pFramePtr += 2;
1731 MsgLen -= 2;
1733 if (pDialogToken == NULL)
1734 return result;
1736 NdisMoveMemory(pDialogToken, pFramePtr, 1);
1737 pFramePtr += 1;
1738 MsgLen -= 1;
1740 eid_ptr = (PEID_STRUCT)pFramePtr;
1741 while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
1743 switch(eid_ptr->Eid)
1745 case IE_TPC_REPORT:
1746 NdisMoveMemory(&pTpcRepInfo->TxPwr, eid_ptr->Octet, 1);
1747 NdisMoveMemory(&pTpcRepInfo->LinkMargin, eid_ptr->Octet + 1, 1);
1748 result = TRUE;
1749 break;
1751 default:
1752 break;
1754 eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
1757 return result;
1761 ==========================================================================
1762 Description:
1763 Channel Switch Announcement action frame handler.
1765 Parametrs:
1766 Elme - MLME message containing the received frame
1768 Return : None.
1769 ==========================================================================
1771 static VOID PeerChSwAnnAction(
1772 IN PRTMP_ADAPTER pAd,
1773 IN MLME_QUEUE_ELEM *Elem)
1775 CH_SW_ANN_INFO ChSwAnnInfo;
1776 PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg;
1777 #ifdef CONFIG_STA_SUPPORT
1778 UCHAR index = 0, Channel = 0, NewChannel = 0;
1779 ULONG Bssidx = 0;
1780 #endif // CONFIG_STA_SUPPORT //
1782 NdisZeroMemory(&ChSwAnnInfo, sizeof(CH_SW_ANN_INFO));
1783 if (! PeerChSwAnnSanity(pAd, Elem->Msg, Elem->MsgLen, &ChSwAnnInfo))
1785 DBGPRINT(RT_DEBUG_TRACE, ("Invalid Channel Switch Action Frame.\n"));
1786 return;
1790 #ifdef CONFIG_STA_SUPPORT
1791 if (pAd->OpMode == OPMODE_STA)
1793 Bssidx = BssTableSearch(&pAd->ScanTab, pFr->Hdr.Addr3, pAd->CommonCfg.Channel);
1794 if (Bssidx == BSS_NOT_FOUND)
1796 DBGPRINT(RT_DEBUG_TRACE, ("PeerChSwAnnAction - Bssidx is not found\n"));
1797 return;
1800 DBGPRINT(RT_DEBUG_TRACE, ("\n****Bssidx is %d, Channel = %d\n", index, pAd->ScanTab.BssEntry[Bssidx].Channel));
1801 hex_dump("SSID",pAd->ScanTab.BssEntry[Bssidx].Bssid ,6);
1803 Channel = pAd->CommonCfg.Channel;
1804 NewChannel = ChSwAnnInfo.Channel;
1806 if ((pAd->CommonCfg.bIEEE80211H == 1) && (NewChannel != 0) && (Channel != NewChannel))
1808 // Switching to channel 1 can prevent from rescanning the current channel immediately (by auto reconnection).
1809 // In addition, clear the MLME queue and the scan table to discard the RX packets and previous scanning results.
1810 AsicSwitchChannel(pAd, 1, FALSE);
1811 AsicLockChannel(pAd, 1);
1812 LinkDown(pAd, FALSE);
1813 MlmeQueueInit(&pAd->Mlme.Queue);
1814 BssTableInit(&pAd->ScanTab);
1815 RTMPusecDelay(1000000); // use delay to prevent STA do reassoc
1817 // channel sanity check
1818 for (index = 0 ; index < pAd->ChannelListNum; index++)
1820 if (pAd->ChannelList[index].Channel == NewChannel)
1822 pAd->ScanTab.BssEntry[Bssidx].Channel = NewChannel;
1823 pAd->CommonCfg.Channel = NewChannel;
1824 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
1825 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
1826 DBGPRINT(RT_DEBUG_TRACE, ("&&&&&&&&&&&&&&&&PeerChSwAnnAction - STA receive channel switch announcement IE (New Channel =%d)\n", NewChannel));
1827 break;
1831 if (index >= pAd->ChannelListNum)
1833 DBGPRINT_ERR(("&&&&&&&&&&&&&&&&&&&&&&&&&&PeerChSwAnnAction(can not find New Channel=%d in ChannelList[%d]\n", pAd->CommonCfg.Channel, pAd->ChannelListNum));
1837 #endif // CONFIG_STA_SUPPORT //
1839 return;
1844 ==========================================================================
1845 Description:
1846 Measurement Request action frame handler.
1848 Parametrs:
1849 Elme - MLME message containing the received frame
1851 Return : None.
1852 ==========================================================================
1854 static VOID PeerMeasureReqAction(
1855 IN PRTMP_ADAPTER pAd,
1856 IN MLME_QUEUE_ELEM *Elem)
1858 PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg;
1859 UINT8 DialogToken;
1860 MEASURE_REQ_INFO MeasureReqInfo;
1861 MEASURE_REQ MeasureReq;
1862 MEASURE_REPORT_MODE ReportMode;
1864 if(PeerMeasureReqSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &MeasureReqInfo, &MeasureReq))
1866 ReportMode.word = 0;
1867 ReportMode.field.Incapable = 1;
1868 EnqueueMeasurementRep(pAd, pFr->Hdr.Addr2, DialogToken, MeasureReqInfo.Token, ReportMode.word, MeasureReqInfo.ReqType, 0, NULL);
1871 return;
1875 ==========================================================================
1876 Description:
1877 Measurement Report action frame handler.
1879 Parametrs:
1880 Elme - MLME message containing the received frame
1882 Return : None.
1883 ==========================================================================
1885 static VOID PeerMeasureReportAction(
1886 IN PRTMP_ADAPTER pAd,
1887 IN MLME_QUEUE_ELEM *Elem)
1889 MEASURE_REPORT_INFO MeasureReportInfo;
1890 PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg;
1891 UINT8 DialogToken;
1892 PUINT8 pMeasureReportInfo;
1894 // if (pAd->CommonCfg.bIEEE80211H != TRUE)
1895 // return;
1897 if ((pMeasureReportInfo = kmalloc(sizeof(MEASURE_RPI_REPORT), GFP_ATOMIC)) == NULL)
1899 DBGPRINT(RT_DEBUG_ERROR, ("%s unable to alloc memory for measure report buffer (size=%d).\n", __FUNCTION__, sizeof(MEASURE_RPI_REPORT)));
1900 return;
1903 NdisZeroMemory(&MeasureReportInfo, sizeof(MEASURE_REPORT_INFO));
1904 NdisZeroMemory(pMeasureReportInfo, sizeof(MEASURE_RPI_REPORT));
1905 if (PeerMeasureReportSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &MeasureReportInfo, pMeasureReportInfo))
1907 do {
1908 PMEASURE_REQ_ENTRY pEntry = NULL;
1910 // Not a autonomous measure report.
1911 // check the dialog token field. drop it if the dialog token doesn't match.
1912 if ((DialogToken != 0)
1913 && ((pEntry = MeasureReqLookUp(pAd, DialogToken)) == NULL))
1914 break;
1916 if (pEntry != NULL)
1917 MeasureReqDelete(pAd, pEntry->DialogToken);
1919 if (MeasureReportInfo.ReportType == RM_BASIC)
1921 PMEASURE_BASIC_REPORT pBasicReport = (PMEASURE_BASIC_REPORT)pMeasureReportInfo;
1922 if ((pBasicReport->Map.field.Radar)
1923 && (DfsRequirementCheck(pAd, pBasicReport->ChNum) == TRUE))
1925 NotifyChSwAnnToPeerAPs(pAd, pFr->Hdr.Addr1, pFr->Hdr.Addr2, 1, pBasicReport->ChNum);
1926 StartDFSProcedure(pAd, pBasicReport->ChNum, 1);
1929 } while (FALSE);
1931 else
1932 DBGPRINT(RT_DEBUG_TRACE, ("Invalid Measurement Report Frame.\n"));
1934 kfree(pMeasureReportInfo);
1936 return;
1940 ==========================================================================
1941 Description:
1942 TPC Request action frame handler.
1944 Parametrs:
1945 Elme - MLME message containing the received frame
1947 Return : None.
1948 ==========================================================================
1950 static VOID PeerTpcReqAction(
1951 IN PRTMP_ADAPTER pAd,
1952 IN MLME_QUEUE_ELEM *Elem)
1954 PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg;
1955 PUCHAR pFramePtr = pFr->Octet;
1956 UINT8 DialogToken;
1957 UINT8 TxPwr = GetCurTxPwr(pAd, Elem->Wcid);
1958 UINT8 LinkMargin = 0;
1959 CHAR RealRssi;
1961 // link margin: Ratio of the received signal power to the minimum desired by the station (STA). The
1962 // STA may incorporate rate information and channel conditions, including interference, into its computation
1963 // of link margin.
1965 RealRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0),
1966 ConvertToRssi(pAd, Elem->Rssi1, RSSI_1),
1967 ConvertToRssi(pAd, Elem->Rssi2, RSSI_2));
1969 // skip Category and action code.
1970 pFramePtr += 2;
1972 // Dialog token.
1973 NdisMoveMemory(&DialogToken, pFramePtr, 1);
1975 LinkMargin = (RealRssi / MIN_RCV_PWR);
1976 if (PeerTpcReqSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken))
1977 EnqueueTPCRep(pAd, pFr->Hdr.Addr2, DialogToken, TxPwr, LinkMargin);
1979 return;
1983 ==========================================================================
1984 Description:
1985 TPC Report action frame handler.
1987 Parametrs:
1988 Elme - MLME message containing the received frame
1990 Return : None.
1991 ==========================================================================
1993 static VOID PeerTpcRepAction(
1994 IN PRTMP_ADAPTER pAd,
1995 IN MLME_QUEUE_ELEM *Elem)
1997 UINT8 DialogToken;
1998 TPC_REPORT_INFO TpcRepInfo;
1999 PTPC_REQ_ENTRY pEntry = NULL;
2001 NdisZeroMemory(&TpcRepInfo, sizeof(TPC_REPORT_INFO));
2002 if (PeerTpcRepSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &TpcRepInfo))
2004 if ((pEntry = TpcReqLookUp(pAd, DialogToken)) != NULL)
2006 TpcReqDelete(pAd, pEntry->DialogToken);
2007 DBGPRINT(RT_DEBUG_TRACE, ("%s: DialogToken=%x, TxPwr=%d, LinkMargin=%d\n",
2008 __FUNCTION__, DialogToken, TpcRepInfo.TxPwr, TpcRepInfo.LinkMargin));
2012 return;
2016 ==========================================================================
2017 Description:
2018 Spectrun action frames Handler such as channel switch annoucement,
2019 measurement report, measurement request actions frames.
2021 Parametrs:
2022 Elme - MLME message containing the received frame
2024 Return : None.
2025 ==========================================================================
2027 VOID PeerSpectrumAction(
2028 IN PRTMP_ADAPTER pAd,
2029 IN MLME_QUEUE_ELEM *Elem)
2032 UCHAR Action = Elem->Msg[LENGTH_802_11+1];
2034 if (pAd->CommonCfg.bIEEE80211H != TRUE)
2035 return;
2037 switch(Action)
2039 case SPEC_MRQ:
2040 // current rt2860 unable do such measure specified in Measurement Request.
2041 // reject all measurement request.
2042 PeerMeasureReqAction(pAd, Elem);
2043 break;
2045 case SPEC_MRP:
2046 PeerMeasureReportAction(pAd, Elem);
2047 break;
2049 case SPEC_TPCRQ:
2050 PeerTpcReqAction(pAd, Elem);
2051 break;
2053 case SPEC_TPCRP:
2054 PeerTpcRepAction(pAd, Elem);
2055 break;
2057 case SPEC_CHANNEL_SWITCH:
2059 #ifdef DOT11N_DRAFT3
2061 SEC_CHA_OFFSET_IE Secondary;
2062 CHA_SWITCH_ANNOUNCE_IE ChannelSwitch;
2064 // 802.11h only has Channel Switch Announcement IE.
2065 RTMPMoveMemory(&ChannelSwitch, &Elem->Msg[LENGTH_802_11+4], sizeof (CHA_SWITCH_ANNOUNCE_IE));
2067 // 802.11n D3.03 adds secondary channel offset element in the end.
2068 if (Elem->MsgLen == (LENGTH_802_11 + 2 + sizeof (CHA_SWITCH_ANNOUNCE_IE) + sizeof (SEC_CHA_OFFSET_IE)))
2070 RTMPMoveMemory(&Secondary, &Elem->Msg[LENGTH_802_11+9], sizeof (SEC_CHA_OFFSET_IE));
2072 else
2074 Secondary.SecondaryChannelOffset = 0;
2077 if ((Elem->Msg[LENGTH_802_11+2] == IE_CHANNEL_SWITCH_ANNOUNCEMENT) && (Elem->Msg[LENGTH_802_11+3] == 3))
2079 ChannelSwitchAction(pAd, Elem->Wcid, ChannelSwitch.NewChannel, Secondary.SecondaryChannelOffset);
2082 #endif // DOT11N_DRAFT3 //
2084 PeerChSwAnnAction(pAd, Elem);
2085 break;
2088 return;
2092 ==========================================================================
2093 Description:
2095 Parametrs:
2097 Return : None.
2098 ==========================================================================
2100 INT Set_MeasureReq_Proc(
2101 IN PRTMP_ADAPTER pAd,
2102 IN PSTRING arg)
2104 UINT Aid = 1;
2105 UINT ArgIdx;
2106 PSTRING thisChar;
2108 MEASURE_REQ_MODE MeasureReqMode;
2109 UINT8 MeasureReqToken = RandomByte(pAd);
2110 UINT8 MeasureReqType = RM_BASIC;
2111 UINT8 MeasureCh = 1;
2112 UINT64 MeasureStartTime = GetCurrentTimeStamp(pAd);
2113 MEASURE_REQ MeasureReq;
2114 UINT8 TotalLen;
2116 HEADER_802_11 ActHdr;
2117 PUCHAR pOutBuffer = NULL;
2118 NDIS_STATUS NStatus;
2119 ULONG FrameLen;
2121 NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory
2122 if(NStatus != NDIS_STATUS_SUCCESS)
2124 DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __FUNCTION__));
2125 goto END_OF_MEASURE_REQ;
2128 ArgIdx = 1;
2129 while ((thisChar = strsep((char **)&arg, "-")) != NULL)
2131 switch(ArgIdx)
2133 case 1: // Aid.
2134 Aid = (UINT8) simple_strtol(thisChar, 0, 16);
2135 break;
2137 case 2: // Measurement Request Type.
2138 MeasureReqType = simple_strtol(thisChar, 0, 16);
2139 if (MeasureReqType > 3)
2141 DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow MeasureReqType(%d)\n", __FUNCTION__, MeasureReqType));
2142 goto END_OF_MEASURE_REQ;
2144 break;
2146 case 3: // Measurement channel.
2147 MeasureCh = (UINT8) simple_strtol(thisChar, 0, 16);
2148 break;
2150 ArgIdx++;
2153 DBGPRINT(RT_DEBUG_TRACE, ("%s::Aid = %d, MeasureReqType=%d MeasureCh=%d\n", __FUNCTION__, Aid, MeasureReqType, MeasureCh));
2154 if (!VALID_WCID(Aid))
2156 DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow sta of Aid(%d)\n", __FUNCTION__, Aid));
2157 goto END_OF_MEASURE_REQ;
2160 MeasureReqMode.word = 0;
2161 MeasureReqMode.field.Enable = 1;
2163 MeasureReqInsert(pAd, MeasureReqToken);
2165 // build action frame header.
2166 MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pAd->MacTab.Content[Aid].Addr,
2167 pAd->CurrentAddress);
2169 NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11));
2170 FrameLen = sizeof(HEADER_802_11);
2172 TotalLen = sizeof(MEASURE_REQ_INFO) + sizeof(MEASURE_REQ);
2174 MakeMeasurementReqFrame(pAd, pOutBuffer, &FrameLen,
2175 sizeof(MEASURE_REQ_INFO), CATEGORY_RM, RM_BASIC,
2176 MeasureReqToken, MeasureReqMode.word,
2177 MeasureReqType, 0);
2179 MeasureReq.ChNum = MeasureCh;
2180 MeasureReq.MeasureStartTime = cpu2le64(MeasureStartTime);
2181 MeasureReq.MeasureDuration = cpu2le16(2000);
2184 ULONG TempLen;
2185 MakeOutgoingFrame( pOutBuffer+FrameLen, &TempLen,
2186 sizeof(MEASURE_REQ), &MeasureReq,
2187 END_OF_ARGS);
2188 FrameLen += TempLen;
2191 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, (UINT)FrameLen);
2193 END_OF_MEASURE_REQ:
2194 MlmeFreeMemory(pAd, pOutBuffer);
2196 return TRUE;
2199 INT Set_TpcReq_Proc(
2200 IN PRTMP_ADAPTER pAd,
2201 IN PSTRING arg)
2203 UINT Aid;
2205 UINT8 TpcReqToken = RandomByte(pAd);
2207 Aid = (UINT) simple_strtol(arg, 0, 16);
2209 DBGPRINT(RT_DEBUG_TRACE, ("%s::Aid = %d\n", __FUNCTION__, Aid));
2210 if (!VALID_WCID(Aid))
2212 DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow sta of Aid(%d)\n", __FUNCTION__, Aid));
2213 return TRUE;
2216 TpcReqInsert(pAd, TpcReqToken);
2218 EnqueueTPCReq(pAd, pAd->MacTab.Content[Aid].Addr, TpcReqToken);
2220 return TRUE;