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