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