Commit | Line | Data |
---|---|---|
4bd43f50 LR |
1 | /* |
2 | * Copyright (c) 2007-2008 Atheros Communications Inc. | |
3 | * | |
4 | * Permission to use, copy, modify, and/or distribute this software for any | |
5 | * purpose with or without fee is hereby granted, provided that the above | |
6 | * copyright notice and this permission notice appear in all copies. | |
7 | * | |
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
15 | */ | |
16 | ||
17 | #include "cprecomp.h" | |
18 | ||
19 | void zfScanMgrInit(zdev_t* dev) | |
20 | { | |
21 | zmw_get_wlan_dev(dev); | |
22 | ||
23 | wd->sta.scanMgr.scanReqs[0] = 0; | |
24 | wd->sta.scanMgr.scanReqs[1] = 0; | |
25 | ||
26 | wd->sta.scanMgr.currScanType = ZM_SCAN_MGR_SCAN_NONE; | |
27 | wd->sta.scanMgr.scanStartDelay = 3; | |
28 | //wd->sta.scanMgr.scanStartDelay = 0; | |
29 | } | |
30 | ||
31 | u8_t zfScanMgrScanStart(zdev_t* dev, u8_t scanType) | |
32 | { | |
33 | u8_t i; | |
34 | ||
35 | zmw_get_wlan_dev(dev); | |
36 | ||
37 | zm_debug_msg1("scanType = ", scanType); | |
38 | ||
39 | zmw_declare_for_critical_section(); | |
40 | ||
41 | if ( scanType != ZM_SCAN_MGR_SCAN_INTERNAL && | |
42 | scanType != ZM_SCAN_MGR_SCAN_EXTERNAL ) | |
43 | { | |
44 | zm_debug_msg0("unknown scanType"); | |
45 | return 1; | |
46 | } | |
47 | else if (zfStaIsConnecting(dev)) | |
48 | { | |
49 | zm_debug_msg0("reject scan request due to connecting"); | |
50 | return 1; | |
51 | } | |
52 | ||
53 | i = scanType - 1; | |
54 | ||
55 | zmw_enter_critical_section(dev); | |
56 | ||
57 | if ( wd->sta.scanMgr.scanReqs[i] == 1 ) | |
58 | { | |
59 | zm_debug_msg1("scan rescheduled", scanType); | |
60 | goto scan_done; | |
61 | } | |
62 | ||
63 | wd->sta.scanMgr.scanReqs[i] = 1; | |
64 | zm_debug_msg1("scan scheduled: ", scanType); | |
65 | ||
66 | // If there's no scan pending, we do the scan right away. | |
67 | // If there's an internal scan and the new scan request is external one, | |
68 | // we will restart the scan. | |
69 | if ( wd->sta.scanMgr.currScanType == ZM_SCAN_MGR_SCAN_NONE ) | |
70 | { | |
71 | goto schedule_scan; | |
72 | } | |
73 | else if ( wd->sta.scanMgr.currScanType == ZM_SCAN_MGR_SCAN_INTERNAL && | |
74 | scanType == ZM_SCAN_MGR_SCAN_EXTERNAL ) | |
75 | { | |
76 | // Stop the internal scan & schedule external scan first | |
77 | zfTimerCancel(dev, ZM_EVENT_SCAN); | |
78 | ||
79 | /* Fix for WHQL sendrecv => we do not apply delay time in which the device | |
80 | stop transmitting packet when we already connect to some AP */ | |
81 | wd->sta.bScheduleScan = FALSE; | |
82 | ||
83 | zfTimerCancel(dev, ZM_EVENT_TIMEOUT_SCAN); | |
84 | zfTimerCancel(dev, ZM_EVENT_IN_SCAN); | |
85 | ||
86 | wd->sta.bChannelScan = FALSE; | |
87 | goto schedule_scan; | |
88 | } | |
89 | else | |
90 | { | |
91 | zm_debug_msg0("Scan is busy...waiting later to start\n"); | |
92 | } | |
93 | ||
94 | zmw_leave_critical_section(dev); | |
95 | return 0; | |
96 | ||
97 | scan_done: | |
98 | zmw_leave_critical_section(dev); | |
99 | return 1; | |
100 | ||
101 | schedule_scan: | |
102 | ||
103 | wd->sta.bScheduleScan = TRUE; | |
104 | ||
105 | zfTimerSchedule(dev, ZM_EVENT_SCAN, wd->sta.scanMgr.scanStartDelay); | |
106 | wd->sta.scanMgr.scanStartDelay = 3; | |
107 | //wd->sta.scanMgr.scanStartDelay = 0; | |
108 | wd->sta.scanMgr.currScanType = scanType; | |
109 | zmw_leave_critical_section(dev); | |
110 | ||
111 | if ((zfStaIsConnected(dev)) && (!zfPowerSavingMgrIsSleeping(dev))) | |
112 | { | |
113 | zfSendNullData(dev, 1); | |
114 | } | |
115 | return 0; | |
116 | } | |
117 | ||
118 | void zfScanMgrScanStop(zdev_t* dev, u8_t scanType) | |
119 | { | |
120 | u8_t scanNotifyRequired = 0; | |
121 | u8_t theOtherScan = ZM_SCAN_MGR_SCAN_NONE; | |
122 | ||
123 | zmw_get_wlan_dev(dev); | |
124 | ||
125 | zmw_declare_for_critical_section(); | |
126 | ||
127 | zmw_enter_critical_section(dev); | |
128 | ||
129 | if ( wd->sta.scanMgr.currScanType == ZM_SCAN_MGR_SCAN_NONE ) | |
130 | { | |
131 | zm_assert(wd->sta.scanMgr.scanReqs[0] == 0); | |
132 | zm_assert(wd->sta.scanMgr.scanReqs[1] == 0); | |
133 | goto done; | |
134 | } | |
135 | ||
136 | switch(scanType) | |
137 | { | |
138 | case ZM_SCAN_MGR_SCAN_EXTERNAL: | |
139 | scanNotifyRequired = 1; | |
140 | theOtherScan = ZM_SCAN_MGR_SCAN_INTERNAL; | |
141 | break; | |
142 | ||
143 | case ZM_SCAN_MGR_SCAN_INTERNAL: | |
144 | theOtherScan = ZM_SCAN_MGR_SCAN_EXTERNAL; | |
145 | break; | |
146 | ||
147 | default: | |
148 | goto done; | |
149 | } | |
150 | ||
151 | if ( wd->sta.scanMgr.currScanType != scanType ) | |
152 | { | |
153 | goto stop_done; | |
154 | } | |
155 | ||
156 | zfTimerCancel(dev, ZM_EVENT_SCAN); | |
157 | ||
158 | /* Fix for WHQL sendrecv => we do not apply delay time in which the device | |
159 | stop transmitting packet when we already connect to some AP */ | |
160 | wd->sta.bScheduleScan = FALSE; | |
161 | ||
162 | zfTimerCancel(dev, ZM_EVENT_TIMEOUT_SCAN); | |
163 | zfTimerCancel(dev, ZM_EVENT_IN_SCAN); | |
164 | ||
165 | wd->sta.bChannelScan = FALSE; | |
166 | wd->sta.scanFrequency = 0; | |
167 | ||
168 | if ( wd->sta.scanMgr.scanReqs[theOtherScan - 1] ) | |
169 | { | |
170 | wd->sta.scanMgr.currScanType = theOtherScan; | |
171 | ||
172 | // Schedule the other scan after 1 second later | |
173 | zfTimerSchedule(dev, ZM_EVENT_SCAN, 100); | |
174 | } | |
175 | else | |
176 | { | |
177 | wd->sta.scanMgr.currScanType = ZM_SCAN_MGR_SCAN_NONE; | |
178 | } | |
179 | ||
180 | stop_done: | |
181 | wd->sta.scanMgr.scanReqs[scanType - 1] = 0; | |
182 | ||
183 | zmw_leave_critical_section(dev); | |
184 | ||
185 | /* avoid lose receive packet when site survey */ | |
186 | if ((zfStaIsConnected(dev)) && (!zfPowerSavingMgrIsSleeping(dev))) | |
187 | { | |
188 | zfSendNullData(dev, 0); | |
189 | } | |
190 | ||
191 | if ( scanNotifyRequired ) | |
192 | { | |
193 | zm_debug_msg0("Scan notify after reset"); | |
194 | if (wd->zfcbScanNotify != NULL) | |
195 | { | |
196 | wd->zfcbScanNotify(dev, NULL); | |
197 | } | |
198 | } | |
199 | ||
200 | return; | |
201 | ||
202 | done: | |
203 | zmw_leave_critical_section(dev); | |
204 | return; | |
205 | } | |
206 | ||
207 | void zfScanMgrScanAck(zdev_t* dev) | |
208 | { | |
209 | zmw_get_wlan_dev(dev); | |
210 | ||
211 | zmw_declare_for_critical_section(); | |
212 | ||
213 | zmw_enter_critical_section(dev); | |
214 | ||
215 | wd->sta.scanMgr.scanStartDelay = 3; | |
216 | //wd->sta.scanMgr.scanStartDelay = 0; | |
217 | ||
218 | zmw_leave_critical_section(dev); | |
219 | return; | |
220 | } | |
221 | ||
222 | extern void zfStaReconnect(zdev_t* dev); | |
223 | ||
224 | static void zfScanSendProbeRequest(zdev_t* dev) | |
225 | { | |
226 | u8_t k; | |
227 | u16_t dst[3] = { 0xffff, 0xffff, 0xffff }; | |
228 | ||
229 | zmw_get_wlan_dev(dev); | |
230 | ||
231 | /* Increase rxBeaconCount to prevent beacon lost */ | |
232 | if (zfStaIsConnected(dev)) | |
233 | { | |
234 | wd->sta.rxBeaconCount++; | |
235 | } | |
236 | ||
237 | if ( wd->sta.bPassiveScan ) | |
238 | { | |
239 | return; | |
240 | } | |
241 | /* enable 802.l11h and in DFS Band , disable sending probe request */ | |
242 | if (wd->sta.DFSEnable) | |
243 | { | |
244 | if (zfHpIsDfsChannel(dev, wd->sta.scanFrequency)) | |
245 | { | |
246 | return; | |
247 | } | |
248 | } | |
249 | ||
250 | zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_PROBEREQ, dst, 0, 0, 0); | |
251 | ||
252 | if ( wd->sta.disableProbingWithSsid ) | |
253 | { | |
254 | return; | |
255 | } | |
256 | ||
257 | for (k=1; k<=ZM_MAX_PROBE_HIDDEN_SSID_SIZE; k++) | |
258 | { | |
259 | if ( wd->ws.probingSsidList[k-1].ssidLen != 0 ) | |
260 | { | |
261 | zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_PROBEREQ, dst, k, 0, 0); | |
262 | } | |
263 | } | |
264 | } | |
265 | ||
266 | static void zfScanMgrEventSetFreqCompleteCb(zdev_t* dev) | |
267 | { | |
268 | zmw_get_wlan_dev(dev); | |
269 | ||
270 | zmw_declare_for_critical_section(); | |
271 | ||
272 | //printk("zfScanMgrEventSetFreqCompleteCb #1\n"); | |
273 | ||
274 | zmw_enter_critical_section(dev); | |
275 | zfTimerSchedule(dev, ZM_EVENT_IN_SCAN, ZM_TICK_IN_SCAN); | |
276 | if (wd->sta.bPassiveScan) | |
277 | { | |
278 | zfTimerSchedule(dev, ZM_EVENT_TIMEOUT_SCAN, wd->sta.passiveScanTickPerChannel); | |
279 | } | |
280 | else | |
281 | { | |
282 | zfTimerSchedule(dev, ZM_EVENT_TIMEOUT_SCAN, wd->sta.activescanTickPerChannel); | |
283 | } | |
284 | zmw_leave_critical_section(dev); | |
285 | ||
286 | zfScanSendProbeRequest(dev); | |
287 | } | |
288 | ||
289 | ||
290 | static void zfScanMgrEventScanCompleteCb(zdev_t* dev) | |
291 | { | |
4bd43f50 LR |
292 | if ((zfStaIsConnected(dev)) && (!zfPowerSavingMgrIsSleeping(dev))) |
293 | { | |
294 | zfSendNullData(dev, 0); | |
295 | } | |
296 | return; | |
297 | } | |
298 | ||
299 | ||
300 | void zfScanMgrScanEventRetry(zdev_t* dev) | |
301 | { | |
302 | zmw_get_wlan_dev(dev); | |
303 | ||
304 | if ( !wd->sta.bChannelScan ) | |
305 | { | |
306 | return; | |
307 | } | |
308 | ||
309 | if ( !wd->sta.bPassiveScan ) | |
310 | { | |
311 | zfScanSendProbeRequest(dev); | |
312 | #if 0 | |
313 | zmw_enter_critical_section(dev); | |
314 | zfTimerSchedule(dev, ZM_EVENT_IN_SCAN, ZM_TICK_IN_SCAN); | |
315 | zmw_leave_critical_section(dev); | |
316 | #endif | |
317 | } | |
318 | } | |
319 | ||
320 | u8_t zfScanMgrScanEventTimeout(zdev_t* dev) | |
321 | { | |
322 | u16_t nextScanFrequency = 0; | |
323 | u8_t temp; | |
324 | ||
325 | zmw_get_wlan_dev(dev); | |
326 | ||
327 | zmw_declare_for_critical_section(); | |
328 | ||
329 | zmw_enter_critical_section(dev); | |
330 | if ( wd->sta.scanFrequency == 0 ) | |
331 | { | |
332 | zmw_leave_critical_section(dev); | |
333 | return -1; | |
334 | } | |
335 | ||
336 | nextScanFrequency = zfChGetNextChannel(dev, wd->sta.scanFrequency, | |
337 | &wd->sta.bPassiveScan); | |
338 | ||
339 | if ( (nextScanFrequency == 0xffff) | |
340 | || (wd->sta.scanFrequency == zfChGetLastChannel(dev, &temp)) ) | |
341 | { | |
342 | u8_t currScanType; | |
343 | u8_t isExternalScan = 0; | |
344 | u8_t isInternalScan = 0; | |
345 | ||
346 | //zm_debug_msg1("end scan = ", KeQueryInterruptTime()); | |
347 | wd->sta.scanFrequency = 0; | |
348 | ||
349 | zm_debug_msg1("scan 1 type: ", wd->sta.scanMgr.currScanType); | |
350 | zm_debug_msg1("scan channel count = ", wd->regulationTable.allowChannelCnt); | |
351 | ||
352 | //zfBssInfoRefresh(dev); | |
353 | zfTimerCancel(dev, ZM_EVENT_TIMEOUT_SCAN); | |
354 | ||
355 | if ( wd->sta.bChannelScan == FALSE ) | |
356 | { | |
357 | zm_debug_msg0("WOW!! scan is cancelled\n"); | |
358 | zmw_leave_critical_section(dev); | |
359 | goto report_scan_result; | |
360 | } | |
361 | ||
362 | ||
363 | currScanType = wd->sta.scanMgr.currScanType; | |
364 | switch(currScanType) | |
365 | { | |
366 | case ZM_SCAN_MGR_SCAN_EXTERNAL: | |
367 | isExternalScan = 1; | |
368 | ||
369 | if ( wd->sta.scanMgr.scanReqs[ZM_SCAN_MGR_SCAN_INTERNAL - 1] ) | |
370 | { | |
371 | wd->sta.scanMgr.scanReqs[ZM_SCAN_MGR_SCAN_INTERNAL - 1] = 0; | |
372 | isInternalScan = 1; | |
373 | } | |
374 | ||
375 | break; | |
376 | ||
377 | case ZM_SCAN_MGR_SCAN_INTERNAL: | |
378 | isInternalScan = 1; | |
379 | ||
380 | if ( wd->sta.scanMgr.scanReqs[ZM_SCAN_MGR_SCAN_EXTERNAL - 1] ) | |
381 | { | |
382 | // Because the external scan should pre-empts internal scan. | |
383 | // So this shall not be happened!! | |
384 | zm_assert(0); | |
385 | } | |
386 | ||
387 | break; | |
388 | ||
389 | default: | |
390 | zm_assert(0); | |
391 | break; | |
392 | } | |
393 | ||
394 | wd->sta.scanMgr.scanReqs[currScanType - 1] = 0; | |
395 | wd->sta.scanMgr.scanStartDelay = 100; | |
396 | wd->sta.scanMgr.currScanType = ZM_SCAN_MGR_SCAN_NONE; | |
397 | zmw_leave_critical_section(dev); | |
398 | ||
399 | //Set channel according to AP's configuration | |
400 | zfCoreSetFrequencyEx(dev, wd->frequency, wd->BandWidth40, | |
401 | wd->ExtOffset, zfScanMgrEventScanCompleteCb); | |
402 | ||
403 | wd->sta.bChannelScan = FALSE; | |
404 | ||
405 | #if 1 | |
406 | if (zfStaIsConnected(dev)) | |
407 | { // Finish site survey, reset the variable to detect using wrong frequency ! | |
408 | zfHpFinishSiteSurvey(dev, 1); | |
409 | zmw_enter_critical_section(dev); | |
410 | wd->sta.ibssSiteSurveyStatus = 2; | |
411 | wd->tickIbssReceiveBeacon = 0; | |
412 | wd->sta.ibssReceiveBeaconCount = 0; | |
413 | zmw_leave_critical_section(dev); | |
414 | ||
415 | /* #5 Re-enable RIFS function after the site survey ! */ | |
416 | /* This is because switch band will reset the BB register to initial value */ | |
417 | if( wd->sta.rifsState == ZM_RIFS_STATE_DETECTED ) | |
418 | { | |
419 | zfHpEnableRifs(dev, ((wd->sta.currentFrequency<3000)?1:0), wd->sta.EnableHT, wd->sta.HT2040); | |
420 | } | |
421 | } | |
422 | else | |
423 | { | |
424 | zfHpFinishSiteSurvey(dev, 0); | |
425 | zmw_enter_critical_section(dev); | |
426 | wd->sta.ibssSiteSurveyStatus = 0; | |
427 | zmw_leave_critical_section(dev); | |
428 | } | |
429 | #endif | |
430 | ||
431 | report_scan_result: | |
432 | /* avoid lose receive packet when site survey */ | |
433 | //if ((zfStaIsConnected(dev)) && (!zfPowerSavingMgrIsSleeping(dev))) | |
434 | //{ | |
435 | // zfSendNullData(dev, 0); | |
436 | //} | |
437 | ||
438 | if ( isExternalScan )//Quickly reboot | |
439 | { | |
440 | if (wd->zfcbScanNotify != NULL) | |
441 | { | |
442 | wd->zfcbScanNotify(dev, NULL); | |
443 | } | |
444 | } | |
445 | ||
446 | if ( isInternalScan ) | |
447 | { | |
448 | //wd->sta.InternalScanReq = 0; | |
449 | zfStaReconnect(dev); | |
450 | } | |
451 | ||
452 | return 0; | |
453 | } | |
454 | else | |
455 | { | |
456 | wd->sta.scanFrequency = nextScanFrequency; | |
457 | ||
458 | //zmw_enter_critical_section(dev); | |
459 | zfTimerCancel(dev, ZM_EVENT_IN_SCAN); | |
460 | zmw_leave_critical_section(dev); | |
461 | ||
462 | zm_debug_msg0("scan 2"); | |
463 | zfCoreSetFrequencyV2(dev, wd->sta.scanFrequency, zfScanMgrEventSetFreqCompleteCb); | |
464 | ||
465 | return 1; | |
466 | } | |
467 | } | |
468 | ||
469 | void zfScanMgrScanEventStart(zdev_t* dev) | |
470 | { | |
471 | zmw_get_wlan_dev(dev); | |
472 | ||
473 | zmw_declare_for_critical_section(); | |
474 | ||
475 | if ( wd->sta.bChannelScan ) | |
476 | { | |
477 | return; | |
478 | } | |
479 | ||
480 | zfPowerSavingMgrWakeup(dev); | |
481 | ||
482 | zmw_enter_critical_section(dev); | |
483 | ||
484 | if ( wd->sta.scanMgr.currScanType == ZM_SCAN_MGR_SCAN_NONE ) | |
485 | { | |
486 | goto no_scan; | |
487 | } | |
488 | ||
489 | //zfBssInfoRefresh(dev); | |
490 | zfBssInfoRefresh(dev, 0); | |
491 | wd->sta.bChannelScan = TRUE; | |
492 | wd->sta.bScheduleScan = FALSE; | |
493 | zfTimerCancel(dev, ZM_EVENT_IN_SCAN); | |
494 | zfTimerCancel(dev, ZM_EVENT_TIMEOUT_SCAN); | |
495 | ||
496 | //zm_debug_msg1("start scan = ", KeQueryInterruptTime()); | |
497 | wd->sta.scanFrequency = zfChGetFirstChannel(dev, &wd->sta.bPassiveScan); | |
498 | zmw_leave_critical_section(dev); | |
499 | ||
500 | /* avoid lose receive packet when site survey */ | |
501 | //if ((zfStaIsConnected(dev)) && (!zfPowerSavingMgrIsSleeping(dev))) | |
502 | //{ | |
503 | // zfSendNullData(dev, 1); | |
504 | //} | |
505 | // zm_debug_msg0("scan 0"); | |
506 | // zfCoreSetFrequencyV2(dev, wd->sta.scanFrequency, zfScanMgrEventSetFreqCompleteCb); | |
507 | ||
508 | #if 1 | |
509 | if (zfStaIsConnected(dev)) | |
510 | {// If doing site survey ! | |
511 | zfHpBeginSiteSurvey(dev, 1); | |
512 | zmw_enter_critical_section(dev); | |
513 | wd->sta.ibssSiteSurveyStatus = 1; | |
514 | zmw_leave_critical_section(dev); | |
515 | } | |
516 | else | |
517 | { | |
518 | zfHpBeginSiteSurvey(dev, 0); | |
519 | zmw_enter_critical_section(dev); | |
520 | wd->sta.ibssSiteSurveyStatus = 0; | |
521 | zmw_leave_critical_section(dev); | |
522 | } | |
523 | #endif | |
524 | ||
525 | zm_debug_msg0("scan 0"); | |
526 | zfCoreSetFrequencyV2(dev, wd->sta.scanFrequency, zfScanMgrEventSetFreqCompleteCb); | |
527 | ||
528 | return; | |
529 | ||
530 | no_scan: | |
531 | zmw_leave_critical_section(dev); | |
532 | return; | |
533 | } |