aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/otus/80211core/cscanmgr.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/otus/80211core/cscanmgr.c')
-rw-r--r--drivers/staging/otus/80211core/cscanmgr.c535
1 files changed, 535 insertions, 0 deletions
diff --git a/drivers/staging/otus/80211core/cscanmgr.c b/drivers/staging/otus/80211core/cscanmgr.c
new file mode 100644
index 000000000000..b32835c87590
--- /dev/null
+++ b/drivers/staging/otus/80211core/cscanmgr.c
@@ -0,0 +1,535 @@
+/*
+ * Copyright (c) 2007-2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "cprecomp.h"
+
+void zfScanMgrInit(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ wd->sta.scanMgr.scanReqs[0] = 0;
+ wd->sta.scanMgr.scanReqs[1] = 0;
+
+ wd->sta.scanMgr.currScanType = ZM_SCAN_MGR_SCAN_NONE;
+ wd->sta.scanMgr.scanStartDelay = 3;
+ //wd->sta.scanMgr.scanStartDelay = 0;
+}
+
+u8_t zfScanMgrScanStart(zdev_t* dev, u8_t scanType)
+{
+ u8_t i;
+
+ zmw_get_wlan_dev(dev);
+
+ zm_debug_msg1("scanType = ", scanType);
+
+ zmw_declare_for_critical_section();
+
+ if ( scanType != ZM_SCAN_MGR_SCAN_INTERNAL &&
+ scanType != ZM_SCAN_MGR_SCAN_EXTERNAL )
+ {
+ zm_debug_msg0("unknown scanType");
+ return 1;
+ }
+ else if (zfStaIsConnecting(dev))
+ {
+ zm_debug_msg0("reject scan request due to connecting");
+ return 1;
+ }
+
+ i = scanType - 1;
+
+ zmw_enter_critical_section(dev);
+
+ if ( wd->sta.scanMgr.scanReqs[i] == 1 )
+ {
+ zm_debug_msg1("scan rescheduled", scanType);
+ goto scan_done;
+ }
+
+ wd->sta.scanMgr.scanReqs[i] = 1;
+ zm_debug_msg1("scan scheduled: ", scanType);
+
+ // If there's no scan pending, we do the scan right away.
+ // If there's an internal scan and the new scan request is external one,
+ // we will restart the scan.
+ if ( wd->sta.scanMgr.currScanType == ZM_SCAN_MGR_SCAN_NONE )
+ {
+ goto schedule_scan;
+ }
+ else if ( wd->sta.scanMgr.currScanType == ZM_SCAN_MGR_SCAN_INTERNAL &&
+ scanType == ZM_SCAN_MGR_SCAN_EXTERNAL )
+ {
+ // Stop the internal scan & schedule external scan first
+ zfTimerCancel(dev, ZM_EVENT_SCAN);
+
+ /* Fix for WHQL sendrecv => we do not apply delay time in which the device
+ stop transmitting packet when we already connect to some AP */
+ wd->sta.bScheduleScan = FALSE;
+
+ zfTimerCancel(dev, ZM_EVENT_TIMEOUT_SCAN);
+ zfTimerCancel(dev, ZM_EVENT_IN_SCAN);
+
+ wd->sta.bChannelScan = FALSE;
+ goto schedule_scan;
+ }
+ else
+ {
+ zm_debug_msg0("Scan is busy...waiting later to start\n");
+ }
+
+ zmw_leave_critical_section(dev);
+ return 0;
+
+scan_done:
+ zmw_leave_critical_section(dev);
+ return 1;
+
+schedule_scan:
+
+ wd->sta.bScheduleScan = TRUE;
+
+ zfTimerSchedule(dev, ZM_EVENT_SCAN, wd->sta.scanMgr.scanStartDelay);
+ wd->sta.scanMgr.scanStartDelay = 3;
+ //wd->sta.scanMgr.scanStartDelay = 0;
+ wd->sta.scanMgr.currScanType = scanType;
+ zmw_leave_critical_section(dev);
+
+ if ((zfStaIsConnected(dev)) && (!zfPowerSavingMgrIsSleeping(dev)))
+ {
+ zfSendNullData(dev, 1);
+ }
+ return 0;
+}
+
+void zfScanMgrScanStop(zdev_t* dev, u8_t scanType)
+{
+ u8_t scanNotifyRequired = 0;
+ u8_t theOtherScan = ZM_SCAN_MGR_SCAN_NONE;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+
+ if ( wd->sta.scanMgr.currScanType == ZM_SCAN_MGR_SCAN_NONE )
+ {
+ zm_assert(wd->sta.scanMgr.scanReqs[0] == 0);
+ zm_assert(wd->sta.scanMgr.scanReqs[1] == 0);
+ goto done;
+ }
+
+ switch(scanType)
+ {
+ case ZM_SCAN_MGR_SCAN_EXTERNAL:
+ scanNotifyRequired = 1;
+ theOtherScan = ZM_SCAN_MGR_SCAN_INTERNAL;
+ break;
+
+ case ZM_SCAN_MGR_SCAN_INTERNAL:
+ theOtherScan = ZM_SCAN_MGR_SCAN_EXTERNAL;
+ break;
+
+ default:
+ goto done;
+ }
+
+ if ( wd->sta.scanMgr.currScanType != scanType )
+ {
+ goto stop_done;
+ }
+
+ zfTimerCancel(dev, ZM_EVENT_SCAN);
+
+ /* Fix for WHQL sendrecv => we do not apply delay time in which the device
+ stop transmitting packet when we already connect to some AP */
+ wd->sta.bScheduleScan = FALSE;
+
+ zfTimerCancel(dev, ZM_EVENT_TIMEOUT_SCAN);
+ zfTimerCancel(dev, ZM_EVENT_IN_SCAN);
+
+ wd->sta.bChannelScan = FALSE;
+ wd->sta.scanFrequency = 0;
+
+ if ( wd->sta.scanMgr.scanReqs[theOtherScan - 1] )
+ {
+ wd->sta.scanMgr.currScanType = theOtherScan;
+
+ // Schedule the other scan after 1 second later
+ zfTimerSchedule(dev, ZM_EVENT_SCAN, 100);
+ }
+ else
+ {
+ wd->sta.scanMgr.currScanType = ZM_SCAN_MGR_SCAN_NONE;
+ }
+
+stop_done:
+ wd->sta.scanMgr.scanReqs[scanType - 1] = 0;
+
+ zmw_leave_critical_section(dev);
+
+ /* avoid lose receive packet when site survey */
+ if ((zfStaIsConnected(dev)) && (!zfPowerSavingMgrIsSleeping(dev)))
+ {
+ zfSendNullData(dev, 0);
+ }
+
+ if ( scanNotifyRequired )
+ {
+ zm_debug_msg0("Scan notify after reset");
+ if (wd->zfcbScanNotify != NULL)
+ {
+ wd->zfcbScanNotify(dev, NULL);
+ }
+ }
+
+ return;
+
+done:
+ zmw_leave_critical_section(dev);
+ return;
+}
+
+void zfScanMgrScanAck(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+
+ wd->sta.scanMgr.scanStartDelay = 3;
+ //wd->sta.scanMgr.scanStartDelay = 0;
+
+ zmw_leave_critical_section(dev);
+ return;
+}
+
+extern void zfStaReconnect(zdev_t* dev);
+
+static void zfScanSendProbeRequest(zdev_t* dev)
+{
+ u8_t k;
+ u16_t dst[3] = { 0xffff, 0xffff, 0xffff };
+
+ zmw_get_wlan_dev(dev);
+
+ /* Increase rxBeaconCount to prevent beacon lost */
+ if (zfStaIsConnected(dev))
+ {
+ wd->sta.rxBeaconCount++;
+ }
+
+ if ( wd->sta.bPassiveScan )
+ {
+ return;
+ }
+ /* enable 802.l11h and in DFS Band , disable sending probe request */
+ if (wd->sta.DFSEnable)
+ {
+ if (zfHpIsDfsChannel(dev, wd->sta.scanFrequency))
+ {
+ return;
+ }
+ }
+
+ zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_PROBEREQ, dst, 0, 0, 0);
+
+ if ( wd->sta.disableProbingWithSsid )
+ {
+ return;
+ }
+
+ for (k=1; k<=ZM_MAX_PROBE_HIDDEN_SSID_SIZE; k++)
+ {
+ if ( wd->ws.probingSsidList[k-1].ssidLen != 0 )
+ {
+ zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_PROBEREQ, dst, k, 0, 0);
+ }
+ }
+}
+
+static void zfScanMgrEventSetFreqCompleteCb(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+//printk("zfScanMgrEventSetFreqCompleteCb #1\n");
+
+ zmw_enter_critical_section(dev);
+ zfTimerSchedule(dev, ZM_EVENT_IN_SCAN, ZM_TICK_IN_SCAN);
+ if (wd->sta.bPassiveScan)
+ {
+ zfTimerSchedule(dev, ZM_EVENT_TIMEOUT_SCAN, wd->sta.passiveScanTickPerChannel);
+ }
+ else
+ {
+ zfTimerSchedule(dev, ZM_EVENT_TIMEOUT_SCAN, wd->sta.activescanTickPerChannel);
+ }
+ zmw_leave_critical_section(dev);
+
+ zfScanSendProbeRequest(dev);
+}
+
+
+static void zfScanMgrEventScanCompleteCb(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ if ((zfStaIsConnected(dev)) && (!zfPowerSavingMgrIsSleeping(dev)))
+ {
+ zfSendNullData(dev, 0);
+ }
+ return;
+}
+
+
+void zfScanMgrScanEventRetry(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ if ( !wd->sta.bChannelScan )
+ {
+ return;
+ }
+
+ if ( !wd->sta.bPassiveScan )
+ {
+ zfScanSendProbeRequest(dev);
+ #if 0
+ zmw_enter_critical_section(dev);
+ zfTimerSchedule(dev, ZM_EVENT_IN_SCAN, ZM_TICK_IN_SCAN);
+ zmw_leave_critical_section(dev);
+ #endif
+ }
+}
+
+u8_t zfScanMgrScanEventTimeout(zdev_t* dev)
+{
+ u16_t nextScanFrequency = 0;
+ u8_t temp;
+
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ zmw_enter_critical_section(dev);
+ if ( wd->sta.scanFrequency == 0 )
+ {
+ zmw_leave_critical_section(dev);
+ return -1;
+ }
+
+ nextScanFrequency = zfChGetNextChannel(dev, wd->sta.scanFrequency,
+ &wd->sta.bPassiveScan);
+
+ if ( (nextScanFrequency == 0xffff)
+ || (wd->sta.scanFrequency == zfChGetLastChannel(dev, &temp)) )
+ {
+ u8_t currScanType;
+ u8_t isExternalScan = 0;
+ u8_t isInternalScan = 0;
+
+ //zm_debug_msg1("end scan = ", KeQueryInterruptTime());
+ wd->sta.scanFrequency = 0;
+
+ zm_debug_msg1("scan 1 type: ", wd->sta.scanMgr.currScanType);
+ zm_debug_msg1("scan channel count = ", wd->regulationTable.allowChannelCnt);
+
+ //zfBssInfoRefresh(dev);
+ zfTimerCancel(dev, ZM_EVENT_TIMEOUT_SCAN);
+
+ if ( wd->sta.bChannelScan == FALSE )
+ {
+ zm_debug_msg0("WOW!! scan is cancelled\n");
+ zmw_leave_critical_section(dev);
+ goto report_scan_result;
+ }
+
+
+ currScanType = wd->sta.scanMgr.currScanType;
+ switch(currScanType)
+ {
+ case ZM_SCAN_MGR_SCAN_EXTERNAL:
+ isExternalScan = 1;
+
+ if ( wd->sta.scanMgr.scanReqs[ZM_SCAN_MGR_SCAN_INTERNAL - 1] )
+ {
+ wd->sta.scanMgr.scanReqs[ZM_SCAN_MGR_SCAN_INTERNAL - 1] = 0;
+ isInternalScan = 1;
+ }
+
+ break;
+
+ case ZM_SCAN_MGR_SCAN_INTERNAL:
+ isInternalScan = 1;
+
+ if ( wd->sta.scanMgr.scanReqs[ZM_SCAN_MGR_SCAN_EXTERNAL - 1] )
+ {
+ // Because the external scan should pre-empts internal scan.
+ // So this shall not be happened!!
+ zm_assert(0);
+ }
+
+ break;
+
+ default:
+ zm_assert(0);
+ break;
+ }
+
+ wd->sta.scanMgr.scanReqs[currScanType - 1] = 0;
+ wd->sta.scanMgr.scanStartDelay = 100;
+ wd->sta.scanMgr.currScanType = ZM_SCAN_MGR_SCAN_NONE;
+ zmw_leave_critical_section(dev);
+
+ //Set channel according to AP's configuration
+ zfCoreSetFrequencyEx(dev, wd->frequency, wd->BandWidth40,
+ wd->ExtOffset, zfScanMgrEventScanCompleteCb);
+
+ wd->sta.bChannelScan = FALSE;
+
+ #if 1
+ if (zfStaIsConnected(dev))
+ { // Finish site survey, reset the variable to detect using wrong frequency !
+ zfHpFinishSiteSurvey(dev, 1);
+ zmw_enter_critical_section(dev);
+ wd->sta.ibssSiteSurveyStatus = 2;
+ wd->tickIbssReceiveBeacon = 0;
+ wd->sta.ibssReceiveBeaconCount = 0;
+ zmw_leave_critical_section(dev);
+
+ /* #5 Re-enable RIFS function after the site survey ! */
+ /* This is because switch band will reset the BB register to initial value */
+ if( wd->sta.rifsState == ZM_RIFS_STATE_DETECTED )
+ {
+ zfHpEnableRifs(dev, ((wd->sta.currentFrequency<3000)?1:0), wd->sta.EnableHT, wd->sta.HT2040);
+ }
+ }
+ else
+ {
+ zfHpFinishSiteSurvey(dev, 0);
+ zmw_enter_critical_section(dev);
+ wd->sta.ibssSiteSurveyStatus = 0;
+ zmw_leave_critical_section(dev);
+ }
+ #endif
+
+report_scan_result:
+ /* avoid lose receive packet when site survey */
+ //if ((zfStaIsConnected(dev)) && (!zfPowerSavingMgrIsSleeping(dev)))
+ //{
+ // zfSendNullData(dev, 0);
+ //}
+
+ if ( isExternalScan )//Quickly reboot
+ {
+ if (wd->zfcbScanNotify != NULL)
+ {
+ wd->zfcbScanNotify(dev, NULL);
+ }
+ }
+
+ if ( isInternalScan )
+ {
+ //wd->sta.InternalScanReq = 0;
+ zfStaReconnect(dev);
+ }
+
+ return 0;
+ }
+ else
+ {
+ wd->sta.scanFrequency = nextScanFrequency;
+
+ //zmw_enter_critical_section(dev);
+ zfTimerCancel(dev, ZM_EVENT_IN_SCAN);
+ zmw_leave_critical_section(dev);
+
+ zm_debug_msg0("scan 2");
+ zfCoreSetFrequencyV2(dev, wd->sta.scanFrequency, zfScanMgrEventSetFreqCompleteCb);
+
+ return 1;
+ }
+}
+
+void zfScanMgrScanEventStart(zdev_t* dev)
+{
+ zmw_get_wlan_dev(dev);
+
+ zmw_declare_for_critical_section();
+
+ if ( wd->sta.bChannelScan )
+ {
+ return;
+ }
+
+ zfPowerSavingMgrWakeup(dev);
+
+ zmw_enter_critical_section(dev);
+
+ if ( wd->sta.scanMgr.currScanType == ZM_SCAN_MGR_SCAN_NONE )
+ {
+ goto no_scan;
+ }
+
+ //zfBssInfoRefresh(dev);
+ zfBssInfoRefresh(dev, 0);
+ wd->sta.bChannelScan = TRUE;
+ wd->sta.bScheduleScan = FALSE;
+ zfTimerCancel(dev, ZM_EVENT_IN_SCAN);
+ zfTimerCancel(dev, ZM_EVENT_TIMEOUT_SCAN);
+
+ //zm_debug_msg1("start scan = ", KeQueryInterruptTime());
+ wd->sta.scanFrequency = zfChGetFirstChannel(dev, &wd->sta.bPassiveScan);
+ zmw_leave_critical_section(dev);
+
+ /* avoid lose receive packet when site survey */
+ //if ((zfStaIsConnected(dev)) && (!zfPowerSavingMgrIsSleeping(dev)))
+ //{
+ // zfSendNullData(dev, 1);
+ //}
+// zm_debug_msg0("scan 0");
+// zfCoreSetFrequencyV2(dev, wd->sta.scanFrequency, zfScanMgrEventSetFreqCompleteCb);
+
+ #if 1
+ if (zfStaIsConnected(dev))
+ {// If doing site survey !
+ zfHpBeginSiteSurvey(dev, 1);
+ zmw_enter_critical_section(dev);
+ wd->sta.ibssSiteSurveyStatus = 1;
+ zmw_leave_critical_section(dev);
+ }
+ else
+ {
+ zfHpBeginSiteSurvey(dev, 0);
+ zmw_enter_critical_section(dev);
+ wd->sta.ibssSiteSurveyStatus = 0;
+ zmw_leave_critical_section(dev);
+ }
+ #endif
+
+ zm_debug_msg0("scan 0");
+ zfCoreSetFrequencyV2(dev, wd->sta.scanFrequency, zfScanMgrEventSetFreqCompleteCb);
+
+ return;
+
+no_scan:
+ zmw_leave_critical_section(dev);
+ return;
+}