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