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