]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/staging/rt2860/common/spectrum.c
Staging: rt28x0: updates from vendor's V2.1.0.0 drivers
[net-next-2.6.git] / drivers / staging / rt2860 / common / spectrum.c
CommitLineData
91980990
GKH
1/*
2 *************************************************************************
3 * Ralink Tech Inc.
4 * 5F., No.36, Taiyuan St., Jhubei City,
5 * Hsinchu County 302,
6 * Taiwan, R.O.C.
7 *
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
9 *
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 *************************************************************************
26
27
28 Module Name:
29 action.c
30
31 Abstract:
32 Handle association related requests either from WSTA or from local MLME
33
34 Revision History:
35 Who When What
36 --------- ---------- ----------------------------------------------
37 Fonchi Wu 2008 created for 802.11h
38 */
39
40#include "../rt_config.h"
41#include "action.h"
42
ca97b838
BZ
43
44/* The regulatory information in the USA (US) */
45DOT11_REGULATORY_INFORMATION USARegulatoryInfo[] =
46{
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}}}
61};
62#define USA_REGULATORY_INFO_SIZE (sizeof(USARegulatoryInfo) / sizeof(DOT11_REGULATORY_INFORMATION))
63
64
65/* The regulatory information in Europe */
66DOT11_REGULATORY_INFORMATION EuropeRegulatoryInfo[] =
67{
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}}}
74};
75#define EU_REGULATORY_INFO_SIZE (sizeof(EuropeRegulatoryInfo) / sizeof(DOT11_REGULATORY_INFORMATION))
76
77
78/* The regulatory information in Japan */
79DOT11_REGULATORY_INFORMATION JapanRegulatoryInfo[] =
80{
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}}},
113 {31, {1, 23, {14}}},
114 {32, {4, 22, {52, 56, 60, 64}}}
115};
116#define JP_REGULATORY_INFO_SIZE (sizeof(JapanRegulatoryInfo) / sizeof(DOT11_REGULATORY_INFORMATION))
117
118
119CHAR RTMP_GetTxPwr(
120 IN PRTMP_ADAPTER pAd,
121 IN HTTRANSMIT_SETTING HTTxMode)
122{
123typedef struct __TX_PWR_CFG
124{
125 UINT8 Mode;
126 UINT8 MCS;
127 UINT16 req;
128 UINT8 shift;
129 UINT32 BitMask;
130} TX_PWR_CFG;
131
132 UINT32 Value;
133 INT Idx;
134 UINT8 PhyMode;
135 CHAR CurTxPwr;
136 UINT8 TxPwrRef = 0;
137 CHAR DaltaPwr;
138 ULONG TxPwr[5];
139
140
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},
146
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}
171 };
172#define MAX_TXPWR_TAB_SIZE (sizeof(TxPwrCfg) / sizeof(TX_PWR_CFG))
173
174 CurTxPwr = 19;
175
176 /* check Tx Power setting from UI. */
177 if (pAd->CommonCfg.TxPowerPercentage > 90)
178 ;
179 else if (pAd->CommonCfg.TxPowerPercentage > 60) /* reduce Pwr for 1 dB. */
180 CurTxPwr -= 1;
181 else if (pAd->CommonCfg.TxPowerPercentage > 30) /* reduce Pwr for 3 dB. */
182 CurTxPwr -= 3;
183 else if (pAd->CommonCfg.TxPowerPercentage > 15) /* reduce Pwr for 6 dB. */
184 CurTxPwr -= 6;
185 else if (pAd->CommonCfg.TxPowerPercentage > 9) /* reduce Pwr for 9 dB. */
186 CurTxPwr -= 9;
187 else /* reduce Pwr for 12 dB. */
188 CurTxPwr -= 12;
189
190 if (pAd->CommonCfg.BBPCurrentBW == BW_40)
191 {
192 if (pAd->CommonCfg.CentralChannel > 14)
193 {
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];
199 }
200 else
201 {
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];
207 }
208 }
209 else
210 {
211 if (pAd->CommonCfg.Channel > 14)
212 {
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];
218 }
219 else
220 {
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];
226 }
227 }
228
229
230 switch(HTTxMode.field.MODE)
231 {
232 case MODE_CCK:
233 case MODE_OFDM:
234 Value = TxPwr[1];
235 TxPwrRef = (Value & 0x00000f00) >> 8;
236
237 break;
238
239 case MODE_HTMIX:
240 case MODE_HTGREENFIELD:
241 if (pAd->CommonCfg.TxStream == 1)
242 {
243 Value = TxPwr[2];
244 TxPwrRef = (Value & 0x00000f00) >> 8;
245 }
246 else if (pAd->CommonCfg.TxStream == 2)
247 {
248 Value = TxPwr[3];
249 TxPwrRef = (Value & 0x00000f00) >> 8;
250 }
251 break;
252 }
253
254 PhyMode =
255 (HTTxMode.field.MODE == MODE_HTGREENFIELD)
256 ? MODE_HTMIX :
257 HTTxMode.field.MODE;
258
259 for (Idx = 0; Idx < MAX_TXPWR_TAB_SIZE; Idx++)
260 {
261 if ((TxPwrCfg[Idx].Mode == PhyMode)
262 && (TxPwrCfg[Idx].MCS == HTTxMode.field.MCS))
263 {
264 Value = TxPwr[TxPwrCfg[Idx].req];
265 DaltaPwr = TxPwrRef - (CHAR)((Value & TxPwrCfg[Idx].BitMask)
266 >> TxPwrCfg[Idx].shift);
267 CurTxPwr -= DaltaPwr;
268 break;
269 }
270 }
271
272 return CurTxPwr;
273}
274
275
91980990
GKH
276VOID MeasureReqTabInit(
277 IN PRTMP_ADAPTER pAd)
278{
279 NdisAllocateSpinLock(&pAd->CommonCfg.MeasureReqTabLock);
280
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));
284 else
d599edca 285 DBGPRINT(RT_DEBUG_ERROR, ("%s Fail to alloc memory for pAd->CommonCfg.pMeasureReqTab.\n", __func__));
91980990
GKH
286
287 return;
288}
289
290VOID MeasureReqTabExit(
291 IN PRTMP_ADAPTER pAd)
292{
ca97b838 293 NdisFreeSpinLock(&pAd->CommonCfg.MeasureReqTabLock);
91980990
GKH
294
295 if (pAd->CommonCfg.pMeasureReqTab)
296 kfree(pAd->CommonCfg.pMeasureReqTab);
297 pAd->CommonCfg.pMeasureReqTab = NULL;
298
299 return;
300}
301
ca97b838 302PMEASURE_REQ_ENTRY MeasureReqLookUp(
91980990
GKH
303 IN PRTMP_ADAPTER pAd,
304 IN UINT8 DialogToken)
305{
306 UINT HashIdx;
307 PMEASURE_REQ_TAB pTab = pAd->CommonCfg.pMeasureReqTab;
308 PMEASURE_REQ_ENTRY pEntry = NULL;
309 PMEASURE_REQ_ENTRY pPrevEntry = NULL;
310
311 if (pTab == NULL)
312 {
d599edca 313 DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab doesn't exist.\n", __func__));
91980990
GKH
314 return NULL;
315 }
316
317 RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock);
318
319 HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(DialogToken);
320 pEntry = pTab->Hash[HashIdx];
321
322 while (pEntry)
323 {
324 if (pEntry->DialogToken == DialogToken)
325 break;
326 else
327 {
328 pPrevEntry = pEntry;
329 pEntry = pEntry->pNext;
330 }
331 }
332
333 RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock);
334
335 return pEntry;
336}
337
ca97b838 338PMEASURE_REQ_ENTRY MeasureReqInsert(
91980990
GKH
339 IN PRTMP_ADAPTER pAd,
340 IN UINT8 DialogToken)
341{
342 INT i;
343 ULONG HashIdx;
344 PMEASURE_REQ_TAB pTab = pAd->CommonCfg.pMeasureReqTab;
345 PMEASURE_REQ_ENTRY pEntry = NULL, pCurrEntry;
346 ULONG Now;
347
348 if(pTab == NULL)
349 {
d599edca 350 DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab doesn't exist.\n", __func__));
91980990
GKH
351 return NULL;
352 }
353
354 pEntry = MeasureReqLookUp(pAd, DialogToken);
355 if (pEntry == NULL)
356 {
357 RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock);
358 for (i = 0; i < MAX_MEASURE_REQ_TAB_SIZE; i++)
359 {
360 NdisGetSystemUpTime(&Now);
361 pEntry = &pTab->Content[i];
362
363 if ((pEntry->Valid == TRUE)
364 && RTMP_TIME_AFTER((unsigned long)Now, (unsigned long)(pEntry->lastTime + MQ_REQ_AGE_OUT)))
365 {
366 PMEASURE_REQ_ENTRY pPrevEntry = NULL;
367 ULONG HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken);
368 PMEASURE_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx];
369
370 // update Hash list
371 do
372 {
373 if (pProbeEntry == pEntry)
374 {
375 if (pPrevEntry == NULL)
376 {
377 pTab->Hash[HashIdx] = pEntry->pNext;
378 }
379 else
380 {
381 pPrevEntry->pNext = pEntry->pNext;
382 }
383 break;
384 }
385
386 pPrevEntry = pProbeEntry;
387 pProbeEntry = pProbeEntry->pNext;
388 } while (pProbeEntry);
389
390 NdisZeroMemory(pEntry, sizeof(MEASURE_REQ_ENTRY));
391 pTab->Size--;
392
393 break;
394 }
395
396 if (pEntry->Valid == FALSE)
397 break;
398 }
399
400 if (i < MAX_MEASURE_REQ_TAB_SIZE)
401 {
402 NdisGetSystemUpTime(&Now);
403 pEntry->lastTime = Now;
404 pEntry->Valid = TRUE;
405 pEntry->DialogToken = DialogToken;
406 pTab->Size++;
407 }
408 else
409 {
410 pEntry = NULL;
d599edca 411 DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab tab full.\n", __func__));
91980990
GKH
412 }
413
414 // add this Neighbor entry into HASH table
415 if (pEntry)
416 {
417 HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(DialogToken);
418 if (pTab->Hash[HashIdx] == NULL)
419 {
420 pTab->Hash[HashIdx] = pEntry;
421 }
422 else
423 {
424 pCurrEntry = pTab->Hash[HashIdx];
425 while (pCurrEntry->pNext != NULL)
426 pCurrEntry = pCurrEntry->pNext;
427 pCurrEntry->pNext = pEntry;
428 }
429 }
430
431 RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock);
432 }
433
434 return pEntry;
435}
436
ca97b838 437VOID MeasureReqDelete(
91980990
GKH
438 IN PRTMP_ADAPTER pAd,
439 IN UINT8 DialogToken)
440{
441 PMEASURE_REQ_TAB pTab = pAd->CommonCfg.pMeasureReqTab;
442 PMEASURE_REQ_ENTRY pEntry = NULL;
443
444 if(pTab == NULL)
445 {
d599edca 446 DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab doesn't exist.\n", __func__));
91980990
GKH
447 return;
448 }
449
450 // if empty, return
451 if (pTab->Size == 0)
452 {
453 DBGPRINT(RT_DEBUG_ERROR, ("pMeasureReqTab empty.\n"));
454 return;
455 }
456
457 pEntry = MeasureReqLookUp(pAd, DialogToken);
458 if (pEntry != NULL)
459 {
460 PMEASURE_REQ_ENTRY pPrevEntry = NULL;
461 ULONG HashIdx = MQ_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken);
462 PMEASURE_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx];
463
464 RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock);
465 // update Hash list
466 do
467 {
468 if (pProbeEntry == pEntry)
469 {
470 if (pPrevEntry == NULL)
471 {
472 pTab->Hash[HashIdx] = pEntry->pNext;
473 }
474 else
475 {
476 pPrevEntry->pNext = pEntry->pNext;
477 }
478 break;
479 }
480
481 pPrevEntry = pProbeEntry;
482 pProbeEntry = pProbeEntry->pNext;
483 } while (pProbeEntry);
484
485 NdisZeroMemory(pEntry, sizeof(MEASURE_REQ_ENTRY));
486 pTab->Size--;
487
488 RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock);
489 }
490
491 return;
492}
493
494VOID TpcReqTabInit(
495 IN PRTMP_ADAPTER pAd)
496{
497 NdisAllocateSpinLock(&pAd->CommonCfg.TpcReqTabLock);
498
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));
502 else
d599edca 503 DBGPRINT(RT_DEBUG_ERROR, ("%s Fail to alloc memory for pAd->CommonCfg.pTpcReqTab.\n", __func__));
91980990
GKH
504
505 return;
506}
507
508VOID TpcReqTabExit(
509 IN PRTMP_ADAPTER pAd)
510{
ca97b838 511 NdisFreeSpinLock(&pAd->CommonCfg.TpcReqTabLock);
91980990
GKH
512
513 if (pAd->CommonCfg.pTpcReqTab)
514 kfree(pAd->CommonCfg.pTpcReqTab);
515 pAd->CommonCfg.pTpcReqTab = NULL;
516
517 return;
518}
519
520static PTPC_REQ_ENTRY TpcReqLookUp(
521 IN PRTMP_ADAPTER pAd,
522 IN UINT8 DialogToken)
523{
524 UINT HashIdx;
525 PTPC_REQ_TAB pTab = pAd->CommonCfg.pTpcReqTab;
526 PTPC_REQ_ENTRY pEntry = NULL;
527 PTPC_REQ_ENTRY pPrevEntry = NULL;
528
529 if (pTab == NULL)
530 {
d599edca 531 DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab doesn't exist.\n", __func__));
91980990
GKH
532 return NULL;
533 }
534
535 RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock);
536
537 HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(DialogToken);
538 pEntry = pTab->Hash[HashIdx];
539
540 while (pEntry)
541 {
542 if (pEntry->DialogToken == DialogToken)
543 break;
544 else
545 {
546 pPrevEntry = pEntry;
547 pEntry = pEntry->pNext;
548 }
549 }
550
551 RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock);
552
553 return pEntry;
554}
555
556
557static PTPC_REQ_ENTRY TpcReqInsert(
558 IN PRTMP_ADAPTER pAd,
559 IN UINT8 DialogToken)
560{
561 INT i;
562 ULONG HashIdx;
563 PTPC_REQ_TAB pTab = pAd->CommonCfg.pTpcReqTab;
564 PTPC_REQ_ENTRY pEntry = NULL, pCurrEntry;
565 ULONG Now;
566
567 if(pTab == NULL)
568 {
d599edca 569 DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab doesn't exist.\n", __func__));
91980990
GKH
570 return NULL;
571 }
572
573 pEntry = TpcReqLookUp(pAd, DialogToken);
574 if (pEntry == NULL)
575 {
576 RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock);
577 for (i = 0; i < MAX_TPC_REQ_TAB_SIZE; i++)
578 {
579 NdisGetSystemUpTime(&Now);
580 pEntry = &pTab->Content[i];
581
582 if ((pEntry->Valid == TRUE)
583 && RTMP_TIME_AFTER((unsigned long)Now, (unsigned long)(pEntry->lastTime + TPC_REQ_AGE_OUT)))
584 {
585 PTPC_REQ_ENTRY pPrevEntry = NULL;
586 ULONG HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken);
587 PTPC_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx];
588
589 // update Hash list
590 do
591 {
592 if (pProbeEntry == pEntry)
593 {
594 if (pPrevEntry == NULL)
595 {
596 pTab->Hash[HashIdx] = pEntry->pNext;
597 }
598 else
599 {
600 pPrevEntry->pNext = pEntry->pNext;
601 }
602 break;
603 }
604
605 pPrevEntry = pProbeEntry;
606 pProbeEntry = pProbeEntry->pNext;
607 } while (pProbeEntry);
608
609 NdisZeroMemory(pEntry, sizeof(TPC_REQ_ENTRY));
610 pTab->Size--;
611
612 break;
613 }
614
615 if (pEntry->Valid == FALSE)
616 break;
617 }
618
619 if (i < MAX_TPC_REQ_TAB_SIZE)
620 {
621 NdisGetSystemUpTime(&Now);
622 pEntry->lastTime = Now;
623 pEntry->Valid = TRUE;
624 pEntry->DialogToken = DialogToken;
625 pTab->Size++;
626 }
627 else
628 {
629 pEntry = NULL;
d599edca 630 DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab tab full.\n", __func__));
91980990
GKH
631 }
632
633 // add this Neighbor entry into HASH table
634 if (pEntry)
635 {
636 HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(DialogToken);
637 if (pTab->Hash[HashIdx] == NULL)
638 {
639 pTab->Hash[HashIdx] = pEntry;
640 }
641 else
642 {
643 pCurrEntry = pTab->Hash[HashIdx];
644 while (pCurrEntry->pNext != NULL)
645 pCurrEntry = pCurrEntry->pNext;
646 pCurrEntry->pNext = pEntry;
647 }
648 }
649
650 RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock);
651 }
652
653 return pEntry;
654}
655
656static VOID TpcReqDelete(
657 IN PRTMP_ADAPTER pAd,
658 IN UINT8 DialogToken)
659{
660 PTPC_REQ_TAB pTab = pAd->CommonCfg.pTpcReqTab;
661 PTPC_REQ_ENTRY pEntry = NULL;
662
663 if(pTab == NULL)
664 {
d599edca 665 DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab doesn't exist.\n", __func__));
91980990
GKH
666 return;
667 }
668
669 // if empty, return
670 if (pTab->Size == 0)
671 {
672 DBGPRINT(RT_DEBUG_ERROR, ("pTpcReqTab empty.\n"));
673 return;
674 }
675
676 pEntry = TpcReqLookUp(pAd, DialogToken);
677 if (pEntry != NULL)
678 {
679 PTPC_REQ_ENTRY pPrevEntry = NULL;
680 ULONG HashIdx = TPC_DIALOGTOKEN_HASH_INDEX(pEntry->DialogToken);
681 PTPC_REQ_ENTRY pProbeEntry = pTab->Hash[HashIdx];
682
683 RTMP_SEM_LOCK(&pAd->CommonCfg.TpcReqTabLock);
684 // update Hash list
685 do
686 {
687 if (pProbeEntry == pEntry)
688 {
689 if (pPrevEntry == NULL)
690 {
691 pTab->Hash[HashIdx] = pEntry->pNext;
692 }
693 else
694 {
695 pPrevEntry->pNext = pEntry->pNext;
696 }
697 break;
698 }
699
700 pPrevEntry = pProbeEntry;
701 pProbeEntry = pProbeEntry->pNext;
702 } while (pProbeEntry);
703
704 NdisZeroMemory(pEntry, sizeof(TPC_REQ_ENTRY));
705 pTab->Size--;
706
707 RTMP_SEM_UNLOCK(&pAd->CommonCfg.TpcReqTabLock);
708 }
709
710 return;
711}
712
713/*
714 ==========================================================================
715 Description:
716 Get Current TimeS tamp.
717
718 Parametrs:
719
720 Return : Current Time Stamp.
721 ==========================================================================
722 */
723static UINT64 GetCurrentTimeStamp(
724 IN PRTMP_ADAPTER pAd)
725{
726 // get current time stamp.
727 return 0;
728}
729
730/*
731 ==========================================================================
732 Description:
733 Get Current Transmit Power.
734
735 Parametrs:
736
737 Return : Current Time Stamp.
738 ==========================================================================
739 */
740static UINT8 GetCurTxPwr(
741 IN PRTMP_ADAPTER pAd,
742 IN UINT8 Wcid)
743{
744 return 16; /* 16 dBm */
745}
746
ca97b838
BZ
747/*
748 ==========================================================================
749 Description:
750 Get Current Transmit Power.
751
752 Parametrs:
753
754 Return : Current Time Stamp.
755 ==========================================================================
756 */
757VOID InsertChannelRepIE(
758 IN PRTMP_ADAPTER pAd,
759 OUT PUCHAR pFrameBuf,
760 OUT PULONG pFrameLen,
761 IN PSTRING pCountry,
762 IN UINT8 RegulatoryClass)
763{
764 ULONG TempLen;
765 UINT8 Len;
766 UINT8 IEId = IE_AP_CHANNEL_REPORT;
767 PUCHAR pChListPtr = NULL;
768
769 Len = 1;
770 if (strncmp(pCountry, "US", 2) == 0)
771 {
772 if (RegulatoryClass >= USA_REGULATORY_INFO_SIZE)
773 {
774 DBGPRINT(RT_DEBUG_ERROR, ("%s: USA Unknow Requlatory class (%d)\n",
775 __func__, RegulatoryClass));
776 return;
777 }
778
779 Len += USARegulatoryInfo[RegulatoryClass].ChannelSet.NumberOfChannels;
780 pChListPtr = USARegulatoryInfo[RegulatoryClass].ChannelSet.ChannelList;
781 }
782 else if (strncmp(pCountry, "JP", 2) == 0)
783 {
784 if (RegulatoryClass >= JP_REGULATORY_INFO_SIZE)
785 {
786 DBGPRINT(RT_DEBUG_ERROR, ("%s: JP Unknow Requlatory class (%d)\n",
787 __func__, RegulatoryClass));
788 return;
789 }
790
791 Len += JapanRegulatoryInfo[RegulatoryClass].ChannelSet.NumberOfChannels;
792 pChListPtr = JapanRegulatoryInfo[RegulatoryClass].ChannelSet.ChannelList;
793 }
794 else
795 {
796 DBGPRINT(RT_DEBUG_ERROR, ("%s: Unknow Country (%s)\n",
797 __func__, pCountry));
798 return;
799 }
800
801 MakeOutgoingFrame(pFrameBuf, &TempLen,
802 1, &IEId,
803 1, &Len,
804 1, &RegulatoryClass,
805 Len -1, pChListPtr,
806 END_OF_ARGS);
807
808 *pFrameLen = *pFrameLen + TempLen;
809
810 return;
811}
812
91980990
GKH
813/*
814 ==========================================================================
815 Description:
816 Insert Dialog Token into frame.
817
818 Parametrs:
819 1. frame buffer pointer.
820 2. frame length.
821 3. Dialog token.
822
823 Return : None.
824 ==========================================================================
825 */
ca97b838 826VOID InsertDialogToken(
91980990
GKH
827 IN PRTMP_ADAPTER pAd,
828 OUT PUCHAR pFrameBuf,
829 OUT PULONG pFrameLen,
830 IN UINT8 DialogToken)
831{
832 ULONG TempLen;
833 MakeOutgoingFrame(pFrameBuf, &TempLen,
834 1, &DialogToken,
835 END_OF_ARGS);
836
837 *pFrameLen = *pFrameLen + TempLen;
838
839 return;
840}
841
842/*
843 ==========================================================================
844 Description:
845 Insert TPC Request IE into frame.
846
847 Parametrs:
848 1. frame buffer pointer.
849 2. frame length.
850
851 Return : None.
852 ==========================================================================
853 */
854 static VOID InsertTpcReqIE(
855 IN PRTMP_ADAPTER pAd,
856 OUT PUCHAR pFrameBuf,
857 OUT PULONG pFrameLen)
858{
859 ULONG TempLen;
860 ULONG Len = 0;
861 UINT8 ElementID = IE_TPC_REQUEST;
862
863 MakeOutgoingFrame(pFrameBuf, &TempLen,
864 1, &ElementID,
865 1, &Len,
866 END_OF_ARGS);
867
868 *pFrameLen = *pFrameLen + TempLen;
869
870 return;
871}
872
873/*
874 ==========================================================================
875 Description:
876 Insert TPC Report IE into frame.
877
878 Parametrs:
879 1. frame buffer pointer.
880 2. frame length.
881 3. Transmit Power.
882 4. Link Margin.
883
884 Return : None.
885 ==========================================================================
886 */
ca97b838 887VOID InsertTpcReportIE(
91980990
GKH
888 IN PRTMP_ADAPTER pAd,
889 OUT PUCHAR pFrameBuf,
890 OUT PULONG pFrameLen,
891 IN UINT8 TxPwr,
892 IN UINT8 LinkMargin)
893{
894 ULONG TempLen;
895 ULONG Len = sizeof(TPC_REPORT_INFO);
896 UINT8 ElementID = IE_TPC_REPORT;
897 TPC_REPORT_INFO TpcReportIE;
898
899 TpcReportIE.TxPwr = TxPwr;
900 TpcReportIE.LinkMargin = LinkMargin;
901
902 MakeOutgoingFrame(pFrameBuf, &TempLen,
903 1, &ElementID,
904 1, &Len,
905 Len, &TpcReportIE,
906 END_OF_ARGS);
907
908 *pFrameLen = *pFrameLen + TempLen;
909
910
911 return;
912}
913
914/*
915 ==========================================================================
916 Description:
917 Insert Channel Switch Announcement IE into frame.
918
919 Parametrs:
920 1. frame buffer pointer.
921 2. frame length.
922 3. channel switch announcement mode.
923 4. new selected channel.
924 5. channel switch announcement count.
925
926 Return : None.
927 ==========================================================================
928 */
929static VOID InsertChSwAnnIE(
930 IN PRTMP_ADAPTER pAd,
931 OUT PUCHAR pFrameBuf,
932 OUT PULONG pFrameLen,
933 IN UINT8 ChSwMode,
934 IN UINT8 NewChannel,
935 IN UINT8 ChSwCnt)
936{
937 ULONG TempLen;
938 ULONG Len = sizeof(CH_SW_ANN_INFO);
939 UINT8 ElementID = IE_CHANNEL_SWITCH_ANNOUNCEMENT;
940 CH_SW_ANN_INFO ChSwAnnIE;
941
942 ChSwAnnIE.ChSwMode = ChSwMode;
943 ChSwAnnIE.Channel = NewChannel;
944 ChSwAnnIE.ChSwCnt = ChSwCnt;
945
946 MakeOutgoingFrame(pFrameBuf, &TempLen,
947 1, &ElementID,
948 1, &Len,
949 Len, &ChSwAnnIE,
950 END_OF_ARGS);
951
952 *pFrameLen = *pFrameLen + TempLen;
953
954
955 return;
956}
957
958/*
959 ==========================================================================
960 Description:
961 Insert Measure Request IE into frame.
962
963 Parametrs:
964 1. frame buffer pointer.
965 2. frame length.
966 3. Measure Token.
967 4. Measure Request Mode.
968 5. Measure Request Type.
969 6. Measure Channel.
970 7. Measure Start time.
971 8. Measure Duration.
972
973
974 Return : None.
975 ==========================================================================
976 */
977static VOID InsertMeasureReqIE(
978 IN PRTMP_ADAPTER pAd,
979 OUT PUCHAR pFrameBuf,
980 OUT PULONG pFrameLen,
ca97b838 981 IN UINT8 Len,
91980990
GKH
982 IN PMEASURE_REQ_INFO pMeasureReqIE)
983{
984 ULONG TempLen;
91980990
GKH
985 UINT8 ElementID = IE_MEASUREMENT_REQUEST;
986
987 MakeOutgoingFrame(pFrameBuf, &TempLen,
988 1, &ElementID,
989 1, &Len,
ca97b838 990 sizeof(MEASURE_REQ_INFO), pMeasureReqIE,
91980990
GKH
991 END_OF_ARGS);
992
993 *pFrameLen = *pFrameLen + TempLen;
994
995 return;
996}
997
998/*
999 ==========================================================================
1000 Description:
1001 Insert Measure Report IE into frame.
1002
1003 Parametrs:
1004 1. frame buffer pointer.
1005 2. frame length.
1006 3. Measure Token.
1007 4. Measure Request Mode.
1008 5. Measure Request Type.
1009 6. Length of Report Infomation
1010 7. Pointer of Report Infomation Buffer.
1011
1012 Return : None.
1013 ==========================================================================
1014 */
1015static 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)
1022{
1023 ULONG TempLen;
1024 ULONG Len;
1025 UINT8 ElementID = IE_MEASUREMENT_REPORT;
1026
1027 Len = sizeof(MEASURE_REPORT_INFO) + ReportLnfoLen;
1028
1029 MakeOutgoingFrame(pFrameBuf, &TempLen,
1030 1, &ElementID,
1031 1, &Len,
1032 Len, pMeasureReportIE,
1033 END_OF_ARGS);
1034
1035 *pFrameLen = *pFrameLen + TempLen;
1036
1037 if ((ReportLnfoLen > 0) && (pReportInfo != NULL))
1038 {
1039 MakeOutgoingFrame(pFrameBuf + *pFrameLen, &TempLen,
1040 ReportLnfoLen, pReportInfo,
1041 END_OF_ARGS);
1042
1043 *pFrameLen = *pFrameLen + TempLen;
1044 }
1045 return;
1046}
1047
1048/*
1049 ==========================================================================
1050 Description:
1051 Prepare Measurement request action frame and enqueue it into
1052 management queue waiting for transmition.
1053
1054 Parametrs:
1055 1. the destination mac address of the frame.
1056
1057 Return : None.
1058 ==========================================================================
1059 */
ca97b838 1060VOID MakeMeasurementReqFrame(
91980990 1061 IN PRTMP_ADAPTER pAd,
ca97b838
BZ
1062 OUT PUCHAR pOutBuffer,
1063 OUT PULONG pFrameLen,
1064 IN UINT8 TotalLen,
1065 IN UINT8 Category,
1066 IN UINT8 Action,
91980990
GKH
1067 IN UINT8 MeasureToken,
1068 IN UINT8 MeasureReqMode,
1069 IN UINT8 MeasureReqType,
ca97b838 1070 IN UINT8 NumOfRepetitions)
91980990 1071{
ca97b838 1072 ULONG TempLen;
91980990 1073 MEASURE_REQ_INFO MeasureReqIE;
91980990 1074
ca97b838 1075 InsertActField(pAd, (pOutBuffer + *pFrameLen), pFrameLen, Category, Action);
91980990 1076
ca97b838
BZ
1077 // fill Dialog Token
1078 InsertDialogToken(pAd, (pOutBuffer + *pFrameLen), pFrameLen, MeasureToken);
91980990 1079
ca97b838
BZ
1080 /* fill Number of repetitions. */
1081 if (Category == CATEGORY_RM)
1082 {
1083 MakeOutgoingFrame((pOutBuffer+*pFrameLen), &TempLen,
1084 2, &NumOfRepetitions,
1085 END_OF_ARGS);
91980990 1086
ca97b838
BZ
1087 *pFrameLen += TempLen;
1088 }
91980990
GKH
1089
1090 // prepare Measurement IE.
1091 NdisZeroMemory(&MeasureReqIE, sizeof(MEASURE_REQ_INFO));
ca97b838 1092 MeasureReqIE.Token = MeasureToken;
91980990
GKH
1093 MeasureReqIE.ReqMode.word = MeasureReqMode;
1094 MeasureReqIE.ReqType = MeasureReqType;
ca97b838
BZ
1095 InsertMeasureReqIE(pAd, (pOutBuffer+*pFrameLen), pFrameLen,
1096 TotalLen, &MeasureReqIE);
91980990
GKH
1097
1098 return;
1099}
1100
1101/*
1102 ==========================================================================
1103 Description:
1104 Prepare Measurement report action frame and enqueue it into
1105 management queue waiting for transmition.
1106
1107 Parametrs:
1108 1. the destination mac address of the frame.
1109
1110 Return : None.
1111 ==========================================================================
1112 */
1113VOID EnqueueMeasurementRep(
1114 IN PRTMP_ADAPTER pAd,
1115 IN PUCHAR pDA,
1116 IN UINT8 DialogToken,
1117 IN UINT8 MeasureToken,
1118 IN UINT8 MeasureReqMode,
1119 IN UINT8 MeasureReqType,
1120 IN UINT8 ReportInfoLen,
1121 IN PUINT8 pReportInfo)
1122{
1123 PUCHAR pOutBuffer = NULL;
1124 NDIS_STATUS NStatus;
1125 ULONG FrameLen;
1126 HEADER_802_11 ActHdr;
1127 MEASURE_REPORT_INFO MeasureRepIE;
1128
1129 // build action frame header.
1130 MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
1131 pAd->CurrentAddress);
1132
1133 NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory
1134 if(NStatus != NDIS_STATUS_SUCCESS)
1135 {
d599edca 1136 DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __func__));
91980990
GKH
1137 return;
1138 }
1139 NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11));
1140 FrameLen = sizeof(HEADER_802_11);
1141
1142 InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_MRP);
1143
1144 // fill Dialog Token
1145 InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken);
1146
1147 // prepare Measurement IE.
1148 NdisZeroMemory(&MeasureRepIE, sizeof(MEASURE_REPORT_INFO));
1149 MeasureRepIE.Token = MeasureToken;
ca97b838 1150 MeasureRepIE.ReportMode = MeasureReqMode;
91980990
GKH
1151 MeasureRepIE.ReportType = MeasureReqType;
1152 InsertMeasureReportIE(pAd, (pOutBuffer + FrameLen), &FrameLen, &MeasureRepIE, ReportInfoLen, pReportInfo);
1153
1154 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1155 MlmeFreeMemory(pAd, pOutBuffer);
1156
1157 return;
1158}
1159
1160/*
1161 ==========================================================================
1162 Description:
1163 Prepare TPC Request action frame and enqueue it into
1164 management queue waiting for transmition.
1165
1166 Parametrs:
1167 1. the destination mac address of the frame.
1168
1169 Return : None.
1170 ==========================================================================
1171 */
1172VOID EnqueueTPCReq(
1173 IN PRTMP_ADAPTER pAd,
1174 IN PUCHAR pDA,
1175 IN UCHAR DialogToken)
1176{
1177 PUCHAR pOutBuffer = NULL;
1178 NDIS_STATUS NStatus;
1179 ULONG FrameLen;
1180
1181 HEADER_802_11 ActHdr;
1182
1183 // build action frame header.
1184 MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
1185 pAd->CurrentAddress);
1186
1187 NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory
1188 if(NStatus != NDIS_STATUS_SUCCESS)
1189 {
d599edca 1190 DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __func__));
91980990
GKH
1191 return;
1192 }
1193 NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11));
1194 FrameLen = sizeof(HEADER_802_11);
1195
1196 InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_TPCRQ);
1197
1198 // fill Dialog Token
1199 InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken);
1200
1201 // Insert TPC Request IE.
1202 InsertTpcReqIE(pAd, (pOutBuffer + FrameLen), &FrameLen);
1203
1204 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1205 MlmeFreeMemory(pAd, pOutBuffer);
1206
1207 return;
1208}
1209
1210/*
1211 ==========================================================================
1212 Description:
1213 Prepare TPC Report action frame and enqueue it into
1214 management queue waiting for transmition.
1215
1216 Parametrs:
1217 1. the destination mac address of the frame.
1218
1219 Return : None.
1220 ==========================================================================
1221 */
1222VOID EnqueueTPCRep(
1223 IN PRTMP_ADAPTER pAd,
1224 IN PUCHAR pDA,
1225 IN UINT8 DialogToken,
1226 IN UINT8 TxPwr,
1227 IN UINT8 LinkMargin)
1228{
1229 PUCHAR pOutBuffer = NULL;
1230 NDIS_STATUS NStatus;
1231 ULONG FrameLen;
1232
1233 HEADER_802_11 ActHdr;
1234
1235 // build action frame header.
1236 MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
1237 pAd->CurrentAddress);
1238
1239 NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory
1240 if(NStatus != NDIS_STATUS_SUCCESS)
1241 {
d599edca 1242 DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __func__));
91980990
GKH
1243 return;
1244 }
1245 NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11));
1246 FrameLen = sizeof(HEADER_802_11);
1247
1248 InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_TPCRP);
1249
1250 // fill Dialog Token
1251 InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken);
1252
1253 // Insert TPC Request IE.
1254 InsertTpcReportIE(pAd, (pOutBuffer + FrameLen), &FrameLen, TxPwr, LinkMargin);
1255
1256 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1257 MlmeFreeMemory(pAd, pOutBuffer);
1258
1259 return;
1260}
1261
1262/*
1263 ==========================================================================
1264 Description:
1265 Prepare Channel Switch Announcement action frame and enqueue it into
1266 management queue waiting for transmition.
1267
1268 Parametrs:
1269 1. the destination mac address of the frame.
1270 2. Channel switch announcement mode.
1271 2. a New selected channel.
1272
1273 Return : None.
1274 ==========================================================================
1275 */
1276VOID EnqueueChSwAnn(
1277 IN PRTMP_ADAPTER pAd,
1278 IN PUCHAR pDA,
1279 IN UINT8 ChSwMode,
1280 IN UINT8 NewCh)
1281{
1282 PUCHAR pOutBuffer = NULL;
1283 NDIS_STATUS NStatus;
1284 ULONG FrameLen;
1285
1286 HEADER_802_11 ActHdr;
1287
1288 // build action frame header.
1289 MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
1290 pAd->CurrentAddress);
1291
1292 NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory
1293 if(NStatus != NDIS_STATUS_SUCCESS)
1294 {
d599edca 1295 DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __func__));
91980990
GKH
1296 return;
1297 }
1298 NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11));
1299 FrameLen = sizeof(HEADER_802_11);
1300
1301 InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_CHANNEL_SWITCH);
1302
1303 InsertChSwAnnIE(pAd, (pOutBuffer + FrameLen), &FrameLen, ChSwMode, NewCh, 0);
1304
1305 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1306 MlmeFreeMemory(pAd, pOutBuffer);
1307
1308 return;
1309}
1310
1311static BOOLEAN DfsRequirementCheck(
1312 IN PRTMP_ADAPTER pAd,
1313 IN UINT8 Channel)
1314{
1315 BOOLEAN Result = FALSE;
1316 INT i;
1317
1318 do
1319 {
1320 // check DFS procedure is running.
1321 // make sure DFS procedure won't start twice.
1322 if (pAd->CommonCfg.RadarDetect.RDMode != RD_NORMAL_MODE)
1323 {
1324 Result = FALSE;
1325 break;
1326 }
1327
1328 // check the new channel carried from Channel Switch Announcemnet is valid.
1329 for (i=0; i<pAd->ChannelListNum; i++)
1330 {
1331 if ((Channel == pAd->ChannelList[i].Channel)
1332 &&(pAd->ChannelList[i].RemainingTimeForUse == 0))
1333 {
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
1336 Result = TRUE;
1337 break;
1338 }
1339 }
1340 } while(FALSE);
1341
1342 return Result;
1343}
1344
1345VOID NotifyChSwAnnToPeerAPs(
1346 IN PRTMP_ADAPTER pAd,
1347 IN PUCHAR pRA,
1348 IN PUCHAR pTA,
1349 IN UINT8 ChSwMode,
1350 IN UINT8 Channel)
1351{
91980990
GKH
1352}
1353
1354static VOID StartDFSProcedure(
1355 IN PRTMP_ADAPTER pAd,
1356 IN UCHAR Channel,
1357 IN UINT8 ChSwMode)
1358{
1359 // start DFS procedure
1360 pAd->CommonCfg.Channel = Channel;
1623267a 1361
91980990 1362 N_ChannelCheck(pAd);
1623267a 1363
91980990
GKH
1364 pAd->CommonCfg.RadarDetect.RDMode = RD_SWITCHING_MODE;
1365 pAd->CommonCfg.RadarDetect.CSCount = 0;
1366}
1367
1368/*
1369 ==========================================================================
1370 Description:
1371 Channel Switch Announcement action frame sanity check.
1372
1373 Parametrs:
1374 1. MLME message containing the received frame
1375 2. message length.
1376 3. Channel switch announcement infomation buffer.
1377
1378
1379 Return : None.
1380 ==========================================================================
1381 */
1382
1383/*
1384 Channel Switch Announcement IE.
1385 +----+-----+-----------+------------+-----------+
1386 | ID | Len |Ch Sw Mode | New Ch Num | Ch Sw Cnt |
1387 +----+-----+-----------+------------+-----------+
1388 1 1 1 1 1
1389*/
1390static BOOLEAN PeerChSwAnnSanity(
1391 IN PRTMP_ADAPTER pAd,
1392 IN VOID *pMsg,
1393 IN ULONG MsgLen,
1394 OUT PCH_SW_ANN_INFO pChSwAnnInfo)
1395{
1396 PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
1397 PUCHAR pFramePtr = Fr->Octet;
1398 BOOLEAN result = FALSE;
1399 PEID_STRUCT eid_ptr;
1400
1401 // skip 802.11 header.
1402 MsgLen -= sizeof(HEADER_802_11);
1403
1404 // skip category and action code.
1405 pFramePtr += 2;
1406 MsgLen -= 2;
1407
1408 if (pChSwAnnInfo == NULL)
1409 return result;
1410
1411 eid_ptr = (PEID_STRUCT)pFramePtr;
1412 while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
1413 {
1414 switch(eid_ptr->Eid)
1415 {
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);
1420
1421 result = TRUE;
1422 break;
1423
1424 default:
1425 break;
1426 }
1427 eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
1428 }
1429
1430 return result;
1431}
1432
1433/*
1434 ==========================================================================
1435 Description:
1436 Measurement request action frame sanity check.
1437
1438 Parametrs:
1439 1. MLME message containing the received frame
1440 2. message length.
1441 3. Measurement request infomation buffer.
1442
1443 Return : None.
1444 ==========================================================================
1445 */
1446static BOOLEAN PeerMeasureReqSanity(
1447 IN PRTMP_ADAPTER pAd,
1448 IN VOID *pMsg,
1449 IN ULONG MsgLen,
1450 OUT PUINT8 pDialogToken,
ca97b838
BZ
1451 OUT PMEASURE_REQ_INFO pMeasureReqInfo,
1452 OUT PMEASURE_REQ pMeasureReq)
91980990
GKH
1453{
1454 PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
1455 PUCHAR pFramePtr = Fr->Octet;
1456 BOOLEAN result = FALSE;
1457 PEID_STRUCT eid_ptr;
1458 PUCHAR ptr;
1459 UINT64 MeasureStartTime;
1460 UINT16 MeasureDuration;
1461
1462 // skip 802.11 header.
1463 MsgLen -= sizeof(HEADER_802_11);
1464
1465 // skip category and action code.
1466 pFramePtr += 2;
1467 MsgLen -= 2;
1468
1469 if (pMeasureReqInfo == NULL)
1470 return result;
1471
1472 NdisMoveMemory(pDialogToken, pFramePtr, 1);
1473 pFramePtr += 1;
1474 MsgLen -= 1;
1475
1476 eid_ptr = (PEID_STRUCT)pFramePtr;
1477 while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
1478 {
1479 switch(eid_ptr->Eid)
1480 {
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);
ca97b838
BZ
1485 ptr = (PUCHAR)(eid_ptr->Octet + 3);
1486 NdisMoveMemory(&pMeasureReq->ChNum, ptr, 1);
91980990 1487 NdisMoveMemory(&MeasureStartTime, ptr + 1, 8);
ca97b838 1488 pMeasureReq->MeasureStartTime = SWAP64(MeasureStartTime);
91980990 1489 NdisMoveMemory(&MeasureDuration, ptr + 9, 2);
ca97b838 1490 pMeasureReq->MeasureDuration = SWAP16(MeasureDuration);
91980990
GKH
1491
1492 result = TRUE;
1493 break;
1494
1495 default:
1496 break;
1497 }
1498 eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
1499 }
1500
1501 return result;
1502}
1503
1504/*
1505 ==========================================================================
1506 Description:
1507 Measurement report action frame sanity check.
1508
1509 Parametrs:
1510 1. MLME message containing the received frame
1511 2. message length.
1512 3. Measurement report infomation buffer.
1513 4. basic report infomation buffer.
1514
1515 Return : None.
1516 ==========================================================================
1517 */
1518
1519/*
1520 Measurement Report IE.
1521 +----+-----+-------+-------------+--------------+----------------+
1522 | ID | Len | Token | Report Mode | Measure Type | Measure Report |
1523 +----+-----+-------+-------------+--------------+----------------+
1524 1 1 1 1 1 variable
1525
1526 Basic Report.
1527 +--------+------------+----------+-----+
1528 | Ch Num | Start Time | Duration | Map |
1529 +--------+------------+----------+-----+
1530 1 8 2 1
1531
1532 Map Field Bit Format.
1533 +-----+---------------+---------------------+-------+------------+----------+
1534 | Bss | OFDM Preamble | Unidentified signal | Radar | Unmeasured | Reserved |
1535 +-----+---------------+---------------------+-------+------------+----------+
1536 0 1 2 3 4 5-7
1537*/
1538static BOOLEAN PeerMeasureReportSanity(
1539 IN PRTMP_ADAPTER pAd,
1540 IN VOID *pMsg,
1541 IN ULONG MsgLen,
1542 OUT PUINT8 pDialogToken,
1543 OUT PMEASURE_REPORT_INFO pMeasureReportInfo,
1544 OUT PUINT8 pReportBuf)
1545{
1546 PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
1547 PUCHAR pFramePtr = Fr->Octet;
1548 BOOLEAN result = FALSE;
1549 PEID_STRUCT eid_ptr;
1550 PUCHAR ptr;
1551
1552 // skip 802.11 header.
1553 MsgLen -= sizeof(HEADER_802_11);
1554
1555 // skip category and action code.
1556 pFramePtr += 2;
1557 MsgLen -= 2;
1558
1559 if (pMeasureReportInfo == NULL)
1560 return result;
1561
1562 NdisMoveMemory(pDialogToken, pFramePtr, 1);
1563 pFramePtr += 1;
1564 MsgLen -= 1;
1565
1566 eid_ptr = (PEID_STRUCT)pFramePtr;
1567 while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
1568 {
1569 switch(eid_ptr->Eid)
1570 {
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)
1576 {
1577 PMEASURE_BASIC_REPORT pReport = (PMEASURE_BASIC_REPORT)pReportBuf;
ca97b838 1578 ptr = (PUCHAR)(eid_ptr->Octet + 3);
91980990
GKH
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);
1583
1584 }
1585 else if (pMeasureReportInfo->ReportType == RM_CCA)
1586 {
1587 PMEASURE_CCA_REPORT pReport = (PMEASURE_CCA_REPORT)pReportBuf;
ca97b838 1588 ptr = (PUCHAR)(eid_ptr->Octet + 3);
91980990
GKH
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);
1593
1594 }
1595 else if (pMeasureReportInfo->ReportType == RM_RPI_HISTOGRAM)
1596 {
1597 PMEASURE_RPI_REPORT pReport = (PMEASURE_RPI_REPORT)pReportBuf;
ca97b838 1598 ptr = (PUCHAR)(eid_ptr->Octet + 3);
91980990
GKH
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);
1603 }
1604 result = TRUE;
1605 break;
1606
1607 default:
1608 break;
1609 }
1610 eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
1611 }
1612
1613 return result;
1614}
1615
1616/*
1617 ==========================================================================
1618 Description:
1619 TPC Request action frame sanity check.
1620
1621 Parametrs:
1622 1. MLME message containing the received frame
1623 2. message length.
1624 3. Dialog Token.
1625
1626 Return : None.
1627 ==========================================================================
1628 */
1629static BOOLEAN PeerTpcReqSanity(
1630 IN PRTMP_ADAPTER pAd,
1631 IN VOID *pMsg,
1632 IN ULONG MsgLen,
1633 OUT PUINT8 pDialogToken)
1634{
1635 PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
1636 PUCHAR pFramePtr = Fr->Octet;
1637 BOOLEAN result = FALSE;
1638 PEID_STRUCT eid_ptr;
1639
1640 MsgLen -= sizeof(HEADER_802_11);
1641
1642 // skip category and action code.
1643 pFramePtr += 2;
1644 MsgLen -= 2;
1645
1646 if (pDialogToken == NULL)
1647 return result;
1648
1649 NdisMoveMemory(pDialogToken, pFramePtr, 1);
1650 pFramePtr += 1;
1651 MsgLen -= 1;
1652
1653 eid_ptr = (PEID_STRUCT)pFramePtr;
1654 while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
1655 {
1656 switch(eid_ptr->Eid)
1657 {
1658 case IE_TPC_REQUEST:
1659 result = TRUE;
1660 break;
1661
1662 default:
1663 break;
1664 }
1665 eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
1666 }
1667
1668 return result;
1669}
1670
1671/*
1672 ==========================================================================
1673 Description:
1674 TPC Report action frame sanity check.
1675
1676 Parametrs:
1677 1. MLME message containing the received frame
1678 2. message length.
1679 3. Dialog Token.
1680 4. TPC Report IE.
1681
1682 Return : None.
1683 ==========================================================================
1684 */
1685static BOOLEAN PeerTpcRepSanity(
1686 IN PRTMP_ADAPTER pAd,
1687 IN VOID *pMsg,
1688 IN ULONG MsgLen,
1689 OUT PUINT8 pDialogToken,
1690 OUT PTPC_REPORT_INFO pTpcRepInfo)
1691{
1692 PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
1693 PUCHAR pFramePtr = Fr->Octet;
1694 BOOLEAN result = FALSE;
1695 PEID_STRUCT eid_ptr;
1696
1697 MsgLen -= sizeof(HEADER_802_11);
1698
1699 // skip category and action code.
1700 pFramePtr += 2;
1701 MsgLen -= 2;
1702
1703 if (pDialogToken == NULL)
1704 return result;
1705
1706 NdisMoveMemory(pDialogToken, pFramePtr, 1);
1707 pFramePtr += 1;
1708 MsgLen -= 1;
1709
1710 eid_ptr = (PEID_STRUCT)pFramePtr;
1711 while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
1712 {
1713 switch(eid_ptr->Eid)
1714 {
1715 case IE_TPC_REPORT:
1716 NdisMoveMemory(&pTpcRepInfo->TxPwr, eid_ptr->Octet, 1);
1717 NdisMoveMemory(&pTpcRepInfo->LinkMargin, eid_ptr->Octet + 1, 1);
1718 result = TRUE;
1719 break;
1720
1721 default:
1722 break;
1723 }
1724 eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
1725 }
1726
1727 return result;
1728}
1729
1730/*
1731 ==========================================================================
1732 Description:
1733 Channel Switch Announcement action frame handler.
1734
1735 Parametrs:
1736 Elme - MLME message containing the received frame
1737
1738 Return : None.
1739 ==========================================================================
1740 */
1741static VOID PeerChSwAnnAction(
1742 IN PRTMP_ADAPTER pAd,
1743 IN MLME_QUEUE_ELEM *Elem)
1744{
1745 CH_SW_ANN_INFO ChSwAnnInfo;
1746 PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg;
91980990
GKH
1747 UCHAR index = 0, Channel = 0, NewChannel = 0;
1748 ULONG Bssidx = 0;
91980990
GKH
1749
1750 NdisZeroMemory(&ChSwAnnInfo, sizeof(CH_SW_ANN_INFO));
1751 if (! PeerChSwAnnSanity(pAd, Elem->Msg, Elem->MsgLen, &ChSwAnnInfo))
1752 {
1753 DBGPRINT(RT_DEBUG_TRACE, ("Invalid Channel Switch Action Frame.\n"));
1754 return;
1755 }
1756
91980990
GKH
1757 if (pAd->OpMode == OPMODE_STA)
1758 {
1759 Bssidx = BssTableSearch(&pAd->ScanTab, pFr->Hdr.Addr3, pAd->CommonCfg.Channel);
1760 if (Bssidx == BSS_NOT_FOUND)
1761 {
1762 DBGPRINT(RT_DEBUG_TRACE, ("PeerChSwAnnAction - Bssidx is not found\n"));
1763 return;
1764 }
1765
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);
1768
1769 Channel = pAd->CommonCfg.Channel;
1770 NewChannel = ChSwAnnInfo.Channel;
1771
1772 if ((pAd->CommonCfg.bIEEE80211H == 1) && (NewChannel != 0) && (Channel != NewChannel))
1773 {
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
1782
1783 // channel sanity check
1784 for (index = 0 ; index < pAd->ChannelListNum; index++)
1785 {
1786 if (pAd->ChannelList[index].Channel == NewChannel)
1787 {
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));
1793 break;
1794 }
1795 }
1796
1797 if (index >= pAd->ChannelListNum)
1798 {
1799 DBGPRINT_ERR(("&&&&&&&&&&&&&&&&&&&&&&&&&&PeerChSwAnnAction(can not find New Channel=%d in ChannelList[%d]\n", pAd->CommonCfg.Channel, pAd->ChannelListNum));
1800 }
1801 }
1802 }
91980990
GKH
1803
1804 return;
1805}
1806
1807
1808/*
1809 ==========================================================================
1810 Description:
1811 Measurement Request action frame handler.
1812
1813 Parametrs:
1814 Elme - MLME message containing the received frame
1815
1816 Return : None.
1817 ==========================================================================
1818 */
1819static VOID PeerMeasureReqAction(
1820 IN PRTMP_ADAPTER pAd,
1821 IN MLME_QUEUE_ELEM *Elem)
1822{
1823 PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg;
1824 UINT8 DialogToken;
1825 MEASURE_REQ_INFO MeasureReqInfo;
ca97b838 1826 MEASURE_REQ MeasureReq;
91980990
GKH
1827 MEASURE_REPORT_MODE ReportMode;
1828
ca97b838 1829 if(PeerMeasureReqSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &MeasureReqInfo, &MeasureReq))
91980990
GKH
1830 {
1831 ReportMode.word = 0;
1832 ReportMode.field.Incapable = 1;
1833 EnqueueMeasurementRep(pAd, pFr->Hdr.Addr2, DialogToken, MeasureReqInfo.Token, ReportMode.word, MeasureReqInfo.ReqType, 0, NULL);
1834 }
1835
1836 return;
1837}
1838
1839/*
1840 ==========================================================================
1841 Description:
1842 Measurement Report action frame handler.
1843
1844 Parametrs:
1845 Elme - MLME message containing the received frame
1846
1847 Return : None.
1848 ==========================================================================
1849 */
1850static VOID PeerMeasureReportAction(
1851 IN PRTMP_ADAPTER pAd,
1852 IN MLME_QUEUE_ELEM *Elem)
1853{
1854 MEASURE_REPORT_INFO MeasureReportInfo;
1855 PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg;
1856 UINT8 DialogToken;
1857 PUINT8 pMeasureReportInfo;
1858
1859// if (pAd->CommonCfg.bIEEE80211H != TRUE)
1860// return;
1861
1862 if ((pMeasureReportInfo = kmalloc(sizeof(MEASURE_RPI_REPORT), GFP_ATOMIC)) == NULL)
1863 {
f4b44e76 1864 DBGPRINT(RT_DEBUG_ERROR, ("%s unable to alloc memory for measure report buffer (size=%zu).\n", __func__, sizeof(MEASURE_RPI_REPORT)));
91980990
GKH
1865 return;
1866 }
1867
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))
1871 {
1872 do {
1873 PMEASURE_REQ_ENTRY pEntry = NULL;
1874
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))
1879 break;
1880
1881 if (pEntry != NULL)
1882 MeasureReqDelete(pAd, pEntry->DialogToken);
1883
1884 if (MeasureReportInfo.ReportType == RM_BASIC)
1885 {
1886 PMEASURE_BASIC_REPORT pBasicReport = (PMEASURE_BASIC_REPORT)pMeasureReportInfo;
1887 if ((pBasicReport->Map.field.Radar)
1888 && (DfsRequirementCheck(pAd, pBasicReport->ChNum) == TRUE))
1889 {
1890 NotifyChSwAnnToPeerAPs(pAd, pFr->Hdr.Addr1, pFr->Hdr.Addr2, 1, pBasicReport->ChNum);
1891 StartDFSProcedure(pAd, pBasicReport->ChNum, 1);
1892 }
1893 }
1894 } while (FALSE);
1895 }
1896 else
1897 DBGPRINT(RT_DEBUG_TRACE, ("Invalid Measurement Report Frame.\n"));
1898
1899 kfree(pMeasureReportInfo);
1900
1901 return;
1902}
1903
1904/*
1905 ==========================================================================
1906 Description:
1907 TPC Request action frame handler.
1908
1909 Parametrs:
1910 Elme - MLME message containing the received frame
1911
1912 Return : None.
1913 ==========================================================================
1914 */
1915static VOID PeerTpcReqAction(
1916 IN PRTMP_ADAPTER pAd,
1917 IN MLME_QUEUE_ELEM *Elem)
1918{
1919 PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg;
1920 PUCHAR pFramePtr = pFr->Octet;
1921 UINT8 DialogToken;
1922 UINT8 TxPwr = GetCurTxPwr(pAd, Elem->Wcid);
1923 UINT8 LinkMargin = 0;
1924 CHAR RealRssi;
1925
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
1928 // of link margin.
1929
1930 RealRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Elem->Rssi0, RSSI_0),
1931 ConvertToRssi(pAd, Elem->Rssi1, RSSI_1),
1932 ConvertToRssi(pAd, Elem->Rssi2, RSSI_2));
1933
1934 // skip Category and action code.
1935 pFramePtr += 2;
1936
1937 // Dialog token.
1938 NdisMoveMemory(&DialogToken, pFramePtr, 1);
1939
1940 LinkMargin = (RealRssi / MIN_RCV_PWR);
1941 if (PeerTpcReqSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken))
1942 EnqueueTPCRep(pAd, pFr->Hdr.Addr2, DialogToken, TxPwr, LinkMargin);
1943
1944 return;
1945}
1946
1947/*
1948 ==========================================================================
1949 Description:
1950 TPC Report action frame handler.
1951
1952 Parametrs:
1953 Elme - MLME message containing the received frame
1954
1955 Return : None.
1956 ==========================================================================
1957 */
1958static VOID PeerTpcRepAction(
1959 IN PRTMP_ADAPTER pAd,
1960 IN MLME_QUEUE_ELEM *Elem)
1961{
1962 UINT8 DialogToken;
1963 TPC_REPORT_INFO TpcRepInfo;
1964 PTPC_REQ_ENTRY pEntry = NULL;
1965
1966 NdisZeroMemory(&TpcRepInfo, sizeof(TPC_REPORT_INFO));
1967 if (PeerTpcRepSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &TpcRepInfo))
1968 {
1969 if ((pEntry = TpcReqLookUp(pAd, DialogToken)) != NULL)
1970 {
1971 TpcReqDelete(pAd, pEntry->DialogToken);
1972 DBGPRINT(RT_DEBUG_TRACE, ("%s: DialogToken=%x, TxPwr=%d, LinkMargin=%d\n",
d599edca 1973 __func__, DialogToken, TpcRepInfo.TxPwr, TpcRepInfo.LinkMargin));
91980990
GKH
1974 }
1975 }
1976
1977 return;
1978}
1979
1980/*
1981 ==========================================================================
1982 Description:
1983 Spectrun action frames Handler such as channel switch annoucement,
1984 measurement report, measurement request actions frames.
1985
1986 Parametrs:
1987 Elme - MLME message containing the received frame
1988
1989 Return : None.
1990 ==========================================================================
1991 */
1992VOID PeerSpectrumAction(
1993 IN PRTMP_ADAPTER pAd,
1994 IN MLME_QUEUE_ELEM *Elem)
1995{
1996
1997 UCHAR Action = Elem->Msg[LENGTH_802_11+1];
1998
1999 if (pAd->CommonCfg.bIEEE80211H != TRUE)
2000 return;
2001
2002 switch(Action)
2003 {
2004 case SPEC_MRQ:
2005 // current rt2860 unable do such measure specified in Measurement Request.
2006 // reject all measurement request.
2007 PeerMeasureReqAction(pAd, Elem);
2008 break;
2009
2010 case SPEC_MRP:
2011 PeerMeasureReportAction(pAd, Elem);
2012 break;
2013
2014 case SPEC_TPCRQ:
2015 PeerTpcReqAction(pAd, Elem);
2016 break;
2017
2018 case SPEC_TPCRP:
2019 PeerTpcRepAction(pAd, Elem);
2020 break;
2021
2022 case SPEC_CHANNEL_SWITCH:
ca97b838
BZ
2023
2024
91980990
GKH
2025 PeerChSwAnnAction(pAd, Elem);
2026 break;
2027 }
2028
2029 return;
2030}
2031
2032/*
2033 ==========================================================================
2034 Description:
2035
2036 Parametrs:
2037
2038 Return : None.
2039 ==========================================================================
2040 */
2041INT Set_MeasureReq_Proc(
2042 IN PRTMP_ADAPTER pAd,
ca97b838 2043 IN PSTRING arg)
91980990
GKH
2044{
2045 UINT Aid = 1;
2046 UINT ArgIdx;
ca97b838 2047 PSTRING thisChar;
91980990
GKH
2048
2049 MEASURE_REQ_MODE MeasureReqMode;
2050 UINT8 MeasureReqToken = RandomByte(pAd);
2051 UINT8 MeasureReqType = RM_BASIC;
2052 UINT8 MeasureCh = 1;
ca97b838
BZ
2053 UINT64 MeasureStartTime = GetCurrentTimeStamp(pAd);
2054 MEASURE_REQ MeasureReq;
2055 UINT8 TotalLen;
2056
2057 HEADER_802_11 ActHdr;
2058 PUCHAR pOutBuffer = NULL;
2059 NDIS_STATUS NStatus;
2060 ULONG FrameLen;
2061
2062 NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); //Get an unused nonpaged memory
2063 if(NStatus != NDIS_STATUS_SUCCESS)
2064 {
2065 DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __func__));
2066 goto END_OF_MEASURE_REQ;
2067 }
91980990
GKH
2068
2069 ArgIdx = 1;
2070 while ((thisChar = strsep((char **)&arg, "-")) != NULL)
2071 {
2072 switch(ArgIdx)
2073 {
2074 case 1: // Aid.
ca97b838 2075 Aid = (UINT8) simple_strtol(thisChar, 0, 16);
91980990
GKH
2076 break;
2077
2078 case 2: // Measurement Request Type.
2079 MeasureReqType = simple_strtol(thisChar, 0, 16);
2080 if (MeasureReqType > 3)
2081 {
d599edca 2082 DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow MeasureReqType(%d)\n", __func__, MeasureReqType));
ca97b838 2083 goto END_OF_MEASURE_REQ;
91980990
GKH
2084 }
2085 break;
2086
2087 case 3: // Measurement channel.
ca97b838 2088 MeasureCh = (UINT8) simple_strtol(thisChar, 0, 16);
91980990
GKH
2089 break;
2090 }
2091 ArgIdx++;
2092 }
2093
d599edca 2094 DBGPRINT(RT_DEBUG_TRACE, ("%s::Aid = %d, MeasureReqType=%d MeasureCh=%d\n", __func__, Aid, MeasureReqType, MeasureCh));
91980990
GKH
2095 if (!VALID_WCID(Aid))
2096 {
d599edca 2097 DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow sta of Aid(%d)\n", __func__, Aid));
ca97b838 2098 goto END_OF_MEASURE_REQ;
91980990
GKH
2099 }
2100
2101 MeasureReqMode.word = 0;
2102 MeasureReqMode.field.Enable = 1;
2103
2104 MeasureReqInsert(pAd, MeasureReqToken);
2105
ca97b838
BZ
2106 // build action frame header.
2107 MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pAd->MacTab.Content[Aid].Addr,
2108 pAd->CurrentAddress);
2109
2110 NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11));
2111 FrameLen = sizeof(HEADER_802_11);
2112
2113 TotalLen = sizeof(MEASURE_REQ_INFO) + sizeof(MEASURE_REQ);
2114
2115 MakeMeasurementReqFrame(pAd, pOutBuffer, &FrameLen,
2116 sizeof(MEASURE_REQ_INFO), CATEGORY_RM, RM_BASIC,
2117 MeasureReqToken, MeasureReqMode.word,
2118 MeasureReqType, 0);
2119
2120 MeasureReq.ChNum = MeasureCh;
2121 MeasureReq.MeasureStartTime = cpu2le64(MeasureStartTime);
2122 MeasureReq.MeasureDuration = cpu2le16(2000);
2123
2124 {
2125 ULONG TempLen;
2126 MakeOutgoingFrame( pOutBuffer+FrameLen, &TempLen,
2127 sizeof(MEASURE_REQ), &MeasureReq,
2128 END_OF_ARGS);
2129 FrameLen += TempLen;
2130 }
2131
2132 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, (UINT)FrameLen);
2133
2134END_OF_MEASURE_REQ:
2135 MlmeFreeMemory(pAd, pOutBuffer);
91980990
GKH
2136
2137 return TRUE;
2138}
2139
2140INT Set_TpcReq_Proc(
2141 IN PRTMP_ADAPTER pAd,
ca97b838 2142 IN PSTRING arg)
91980990
GKH
2143{
2144 UINT Aid;
2145
2146 UINT8 TpcReqToken = RandomByte(pAd);
2147
ca97b838 2148 Aid = (UINT) simple_strtol(arg, 0, 16);
91980990 2149
d599edca 2150 DBGPRINT(RT_DEBUG_TRACE, ("%s::Aid = %d\n", __func__, Aid));
91980990
GKH
2151 if (!VALID_WCID(Aid))
2152 {
d599edca 2153 DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow sta of Aid(%d)\n", __func__, Aid));
91980990
GKH
2154 return TRUE;
2155 }
2156
2157 TpcReqInsert(pAd, TpcReqToken);
2158
2159 EnqueueTPCReq(pAd, pAd->MacTab.Content[Aid].Addr, TpcReqToken);
2160
2161 return TRUE;
2162}
2163