7fd715ad39b1c77da9519080ea05f4f375c50759
[deliverable/linux.git] / drivers / staging / rt2860 / common / spectrum.c
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
43
44 /* The regulatory information in the USA (US) */
45 DOT11_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 */
66 DOT11_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 */
79 DOT11_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
119 CHAR RTMP_GetTxPwr(
120 IN PRTMP_ADAPTER pAd,
121 IN HTTRANSMIT_SETTING HTTxMode)
122 {
123 typedef 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
276 VOID 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
285 DBGPRINT(RT_DEBUG_ERROR, ("%s Fail to alloc memory for pAd->CommonCfg.pMeasureReqTab.\n", __func__));
286
287 return;
288 }
289
290 VOID MeasureReqTabExit(
291 IN PRTMP_ADAPTER pAd)
292 {
293 NdisFreeSpinLock(&pAd->CommonCfg.MeasureReqTabLock);
294
295 if (pAd->CommonCfg.pMeasureReqTab)
296 kfree(pAd->CommonCfg.pMeasureReqTab);
297 pAd->CommonCfg.pMeasureReqTab = NULL;
298
299 return;
300 }
301
302 PMEASURE_REQ_ENTRY MeasureReqLookUp(
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 {
313 DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab doesn't exist.\n", __func__));
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
338 PMEASURE_REQ_ENTRY MeasureReqInsert(
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 {
350 DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab doesn't exist.\n", __func__));
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;
411 DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab tab full.\n", __func__));
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
437 VOID MeasureReqDelete(
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 {
446 DBGPRINT(RT_DEBUG_ERROR, ("%s: pMeasureReqTab doesn't exist.\n", __func__));
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
494 VOID 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
503 DBGPRINT(RT_DEBUG_ERROR, ("%s Fail to alloc memory for pAd->CommonCfg.pTpcReqTab.\n", __func__));
504
505 return;
506 }
507
508 VOID TpcReqTabExit(
509 IN PRTMP_ADAPTER pAd)
510 {
511 NdisFreeSpinLock(&pAd->CommonCfg.TpcReqTabLock);
512
513 if (pAd->CommonCfg.pTpcReqTab)
514 kfree(pAd->CommonCfg.pTpcReqTab);
515 pAd->CommonCfg.pTpcReqTab = NULL;
516
517 return;
518 }
519
520 static 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 {
531 DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab doesn't exist.\n", __func__));
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
557 static 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 {
569 DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab doesn't exist.\n", __func__));
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;
630 DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab tab full.\n", __func__));
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
656 static 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 {
665 DBGPRINT(RT_DEBUG_ERROR, ("%s: pTpcReqTab doesn't exist.\n", __func__));
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 */
723 static 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 */
740 static UINT8 GetCurTxPwr(
741 IN PRTMP_ADAPTER pAd,
742 IN UINT8 Wcid)
743 {
744 return 16; /* 16 dBm */
745 }
746
747 /*
748 ==========================================================================
749 Description:
750 Get Current Transmit Power.
751
752 Parametrs:
753
754 Return : Current Time Stamp.
755 ==========================================================================
756 */
757 VOID 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
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 */
826 VOID InsertDialogToken(
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 */
887 VOID InsertTpcReportIE(
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 */
929 static 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 */
977 static VOID InsertMeasureReqIE(
978 IN PRTMP_ADAPTER pAd,
979 OUT PUCHAR pFrameBuf,
980 OUT PULONG pFrameLen,
981 IN UINT8 Len,
982 IN PMEASURE_REQ_INFO pMeasureReqIE)
983 {
984 ULONG TempLen;
985 UINT8 ElementID = IE_MEASUREMENT_REQUEST;
986
987 MakeOutgoingFrame(pFrameBuf, &TempLen,
988 1, &ElementID,
989 1, &Len,
990 sizeof(MEASURE_REQ_INFO), pMeasureReqIE,
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 */
1015 static VOID InsertMeasureReportIE(
1016 IN PRTMP_ADAPTER pAd,
1017 OUT PUCHAR pFrameBuf,
1018 OUT PULONG pFrameLen,
1019 IN PMEASURE_REPORT_INFO pMeasureReportIE,
1020 IN UINT8 ReportLnfoLen,
1021 IN PUINT8 pReportInfo)
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 */
1060 VOID MakeMeasurementReqFrame(
1061 IN PRTMP_ADAPTER pAd,
1062 OUT PUCHAR pOutBuffer,
1063 OUT PULONG pFrameLen,
1064 IN UINT8 TotalLen,
1065 IN UINT8 Category,
1066 IN UINT8 Action,
1067 IN UINT8 MeasureToken,
1068 IN UINT8 MeasureReqMode,
1069 IN UINT8 MeasureReqType,
1070 IN UINT8 NumOfRepetitions)
1071 {
1072 ULONG TempLen;
1073 MEASURE_REQ_INFO MeasureReqIE;
1074
1075 InsertActField(pAd, (pOutBuffer + *pFrameLen), pFrameLen, Category, Action);
1076
1077 // fill Dialog Token
1078 InsertDialogToken(pAd, (pOutBuffer + *pFrameLen), pFrameLen, MeasureToken);
1079
1080 /* fill Number of repetitions. */
1081 if (Category == CATEGORY_RM)
1082 {
1083 MakeOutgoingFrame((pOutBuffer+*pFrameLen), &TempLen,
1084 2, &NumOfRepetitions,
1085 END_OF_ARGS);
1086
1087 *pFrameLen += TempLen;
1088 }
1089
1090 // prepare Measurement IE.
1091 NdisZeroMemory(&MeasureReqIE, sizeof(MEASURE_REQ_INFO));
1092 MeasureReqIE.Token = MeasureToken;
1093 MeasureReqIE.ReqMode.word = MeasureReqMode;
1094 MeasureReqIE.ReqType = MeasureReqType;
1095 InsertMeasureReqIE(pAd, (pOutBuffer+*pFrameLen), pFrameLen,
1096 TotalLen, &MeasureReqIE);
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 */
1113 VOID 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 {
1136 DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __func__));
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;
1150 MeasureRepIE.ReportMode = MeasureReqMode;
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 */
1172 VOID 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 {
1190 DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __func__));
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 */
1222 VOID 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 {
1242 DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __func__));
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 */
1276 VOID 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 {
1295 DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __func__));
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
1311 static 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
1345 VOID NotifyChSwAnnToPeerAPs(
1346 IN PRTMP_ADAPTER pAd,
1347 IN PUCHAR pRA,
1348 IN PUCHAR pTA,
1349 IN UINT8 ChSwMode,
1350 IN UINT8 Channel)
1351 {
1352 }
1353
1354 static 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;
1361
1362 N_ChannelCheck(pAd);
1363
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 */
1390 static 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 */
1446 static BOOLEAN PeerMeasureReqSanity(
1447 IN PRTMP_ADAPTER pAd,
1448 IN VOID *pMsg,
1449 IN ULONG MsgLen,
1450 OUT PUINT8 pDialogToken,
1451 OUT PMEASURE_REQ_INFO pMeasureReqInfo,
1452 OUT PMEASURE_REQ pMeasureReq)
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);
1485 ptr = (PUCHAR)(eid_ptr->Octet + 3);
1486 NdisMoveMemory(&pMeasureReq->ChNum, ptr, 1);
1487 NdisMoveMemory(&MeasureStartTime, ptr + 1, 8);
1488 pMeasureReq->MeasureStartTime = SWAP64(MeasureStartTime);
1489 NdisMoveMemory(&MeasureDuration, ptr + 9, 2);
1490 pMeasureReq->MeasureDuration = SWAP16(MeasureDuration);
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 */
1538 static 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;
1578 ptr = (PUCHAR)(eid_ptr->Octet + 3);
1579 NdisMoveMemory(&pReport->ChNum, ptr, 1);
1580 NdisMoveMemory(&pReport->MeasureStartTime, ptr + 1, 8);
1581 NdisMoveMemory(&pReport->MeasureDuration, ptr + 9, 2);
1582 NdisMoveMemory(&pReport->Map, ptr + 11, 1);
1583
1584 }
1585 else if (pMeasureReportInfo->ReportType == RM_CCA)
1586 {
1587 PMEASURE_CCA_REPORT pReport = (PMEASURE_CCA_REPORT)pReportBuf;
1588 ptr = (PUCHAR)(eid_ptr->Octet + 3);
1589 NdisMoveMemory(&pReport->ChNum, ptr, 1);
1590 NdisMoveMemory(&pReport->MeasureStartTime, ptr + 1, 8);
1591 NdisMoveMemory(&pReport->MeasureDuration, ptr + 9, 2);
1592 NdisMoveMemory(&pReport->CCA_Busy_Fraction, ptr + 11, 1);
1593
1594 }
1595 else if (pMeasureReportInfo->ReportType == RM_RPI_HISTOGRAM)
1596 {
1597 PMEASURE_RPI_REPORT pReport = (PMEASURE_RPI_REPORT)pReportBuf;
1598 ptr = (PUCHAR)(eid_ptr->Octet + 3);
1599 NdisMoveMemory(&pReport->ChNum, ptr, 1);
1600 NdisMoveMemory(&pReport->MeasureStartTime, ptr + 1, 8);
1601 NdisMoveMemory(&pReport->MeasureDuration, ptr + 9, 2);
1602 NdisMoveMemory(&pReport->RPI_Density, ptr + 11, 8);
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 */
1629 static 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 */
1685 static 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 */
1741 static 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;
1747 UCHAR index = 0, Channel = 0, NewChannel = 0;
1748 ULONG Bssidx = 0;
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
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 }
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 */
1819 static 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;
1826 MEASURE_REQ MeasureReq;
1827 MEASURE_REPORT_MODE ReportMode;
1828
1829 if(PeerMeasureReqSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &MeasureReqInfo, &MeasureReq))
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 */
1850 static 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 {
1864 DBGPRINT(RT_DEBUG_ERROR, ("%s unable to alloc memory for measure report buffer (size=%zu).\n", __func__, sizeof(MEASURE_RPI_REPORT)));
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 */
1915 static 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 */
1958 static 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",
1973 __func__, DialogToken, TpcRepInfo.TxPwr, TpcRepInfo.LinkMargin));
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 */
1992 VOID 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:
2023
2024
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 */
2041 INT Set_MeasureReq_Proc(
2042 IN PRTMP_ADAPTER pAd,
2043 IN PSTRING arg)
2044 {
2045 UINT Aid = 1;
2046 UINT ArgIdx;
2047 PSTRING thisChar;
2048
2049 MEASURE_REQ_MODE MeasureReqMode;
2050 UINT8 MeasureReqToken = RandomByte(pAd);
2051 UINT8 MeasureReqType = RM_BASIC;
2052 UINT8 MeasureCh = 1;
2053 UINT64 MeasureStartTime = GetCurrentTimeStamp(pAd);
2054 MEASURE_REQ MeasureReq;
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 }
2068
2069 ArgIdx = 1;
2070 while ((thisChar = strsep((char **)&arg, "-")) != NULL)
2071 {
2072 switch(ArgIdx)
2073 {
2074 case 1: // Aid.
2075 Aid = (UINT8) simple_strtol(thisChar, 0, 16);
2076 break;
2077
2078 case 2: // Measurement Request Type.
2079 MeasureReqType = simple_strtol(thisChar, 0, 16);
2080 if (MeasureReqType > 3)
2081 {
2082 DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow MeasureReqType(%d)\n", __func__, MeasureReqType));
2083 goto END_OF_MEASURE_REQ;
2084 }
2085 break;
2086
2087 case 3: // Measurement channel.
2088 MeasureCh = (UINT8) simple_strtol(thisChar, 0, 16);
2089 break;
2090 }
2091 ArgIdx++;
2092 }
2093
2094 DBGPRINT(RT_DEBUG_TRACE, ("%s::Aid = %d, MeasureReqType=%d MeasureCh=%d\n", __func__, Aid, MeasureReqType, MeasureCh));
2095 if (!VALID_WCID(Aid))
2096 {
2097 DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow sta of Aid(%d)\n", __func__, Aid));
2098 goto END_OF_MEASURE_REQ;
2099 }
2100
2101 MeasureReqMode.word = 0;
2102 MeasureReqMode.field.Enable = 1;
2103
2104 MeasureReqInsert(pAd, MeasureReqToken);
2105
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
2134 END_OF_MEASURE_REQ:
2135 MlmeFreeMemory(pAd, pOutBuffer);
2136
2137 return TRUE;
2138 }
2139
2140 INT Set_TpcReq_Proc(
2141 IN PRTMP_ADAPTER pAd,
2142 IN PSTRING arg)
2143 {
2144 UINT Aid;
2145
2146 UINT8 TpcReqToken = RandomByte(pAd);
2147
2148 Aid = (UINT) simple_strtol(arg, 0, 16);
2149
2150 DBGPRINT(RT_DEBUG_TRACE, ("%s::Aid = %d\n", __func__, Aid));
2151 if (!VALID_WCID(Aid))
2152 {
2153 DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow sta of Aid(%d)\n", __func__, Aid));
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
This page took 0.076315 seconds and 4 git commands to generate.