| /****************************************************************************** |
| * |
| * This file is provided under a dual license. When you use or |
| * distribute this software, you may choose to be licensed under |
| * version 2 of the GNU General Public License ("GPLv2 License") |
| * or BSD License. |
| * |
| * GPLv2 License |
| * |
| * Copyright(C) 2016 MediaTek Inc. |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of version 2 of the GNU General Public License as |
| * published by the Free Software Foundation. |
| * |
| * This program is distributed in the hope that it will be useful, but |
| * WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| * See http://www.gnu.org/licenses/gpl-2.0.html for more details. |
| * |
| * BSD LICENSE |
| * |
| * Copyright(C) 2016 MediaTek Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in |
| * the documentation and/or other materials provided with the |
| * distribution. |
| * * Neither the name of the copyright holder nor the names of its |
| * contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| * |
| *****************************************************************************/ |
| /* |
| ** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/ais_fsm.c#4 |
| */ |
| |
| /*! \file "aa_fsm.c" |
| * \brief This file defines the FSM for SAA and AAA MODULE. |
| * |
| * This file defines the FSM for SAA and AAA MODULE. |
| */ |
| |
| |
| /******************************************************************************* |
| * C O M P I L E R F L A G S |
| ******************************************************************************** |
| */ |
| |
| /******************************************************************************* |
| * E X T E R N A L R E F E R E N C E S |
| ******************************************************************************** |
| */ |
| #include "precomp.h" |
| |
| /******************************************************************************* |
| * C O N S T A N T S |
| ******************************************************************************** |
| */ |
| #define AIS_ROAMING_CONNECTION_TRIAL_LIMIT 2 |
| #define AIS_JOIN_TIMEOUT 7 |
| |
| #define AIS_FSM_STATE_SEARCH_ACTION_PHASE_0 0 |
| #define AIS_FSM_STATE_SEARCH_ACTION_PHASE_1 1 |
| #define AIS_FSM_STATE_SEARCH_ACTION_PHASE_2 2 |
| |
| /******************************************************************************* |
| * D A T A T Y P E S |
| ******************************************************************************** |
| */ |
| |
| /******************************************************************************* |
| * P U B L I C D A T A |
| ******************************************************************************** |
| */ |
| |
| /******************************************************************************* |
| * P R I V A T E D A T A |
| ******************************************************************************** |
| */ |
| static PUINT_8 apucDebugAisState[AIS_STATE_NUM] = { |
| (PUINT_8) DISP_STRING("IDLE"), |
| (PUINT_8) DISP_STRING("SEARCH"), |
| (PUINT_8) DISP_STRING("SCAN"), |
| (PUINT_8) DISP_STRING("ONLINE_SCAN"), |
| (PUINT_8) DISP_STRING("LOOKING_FOR"), |
| (PUINT_8) DISP_STRING("WAIT_FOR_NEXT_SCAN"), |
| (PUINT_8) DISP_STRING("REQ_CHANNEL_JOIN"), |
| (PUINT_8) DISP_STRING("JOIN"), |
| (PUINT_8) DISP_STRING("JOIN_FAILURE"), |
| (PUINT_8) DISP_STRING("IBSS_ALONE"), |
| (PUINT_8) DISP_STRING("IBSS_MERGE"), |
| (PUINT_8) DISP_STRING("NORMAL_TR"), |
| (PUINT_8) DISP_STRING("DISCONNECTING"), |
| (PUINT_8) DISP_STRING("REQ_REMAIN_ON_CHANNEL"), |
| (PUINT_8) DISP_STRING("REMAIN_ON_CHANNEL") |
| }; |
| |
| /******************************************************************************* |
| * M A C R O S |
| ******************************************************************************** |
| */ |
| |
| /******************************************************************************* |
| * F U N C T I O N D E C L A R A T I O N S |
| ******************************************************************************** |
| */ |
| static VOID aisFsmRunEventScanDoneTimeOut(IN P_ADAPTER_T prAdapter, ULONG ulParam); |
| |
| /******************************************************************************* |
| * F U N C T I O N S |
| ******************************************************************************** |
| */ |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief the function is used to initialize the value of the connection settings for |
| * AIS network |
| * |
| * @param (none) |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID aisInitializeConnectionSettings(IN P_ADAPTER_T prAdapter, IN P_REG_INFO_T prRegInfo) |
| { |
| P_CONNECTION_SETTINGS_T prConnSettings; |
| UINT_8 aucAnyBSSID[] = BC_BSSID; |
| UINT_8 aucZeroMacAddr[] = NULL_MAC_ADDR; |
| int i = 0; |
| |
| prConnSettings = &(prAdapter->rWifiVar.rConnSettings); |
| |
| /* Setup default values for operation */ |
| COPY_MAC_ADDR(prConnSettings->aucMacAddress, aucZeroMacAddr); |
| |
| prConnSettings->ucDelayTimeOfDisconnectEvent = AIS_DELAY_TIME_OF_DISCONNECT_SEC; |
| |
| COPY_MAC_ADDR(prConnSettings->aucBSSID, aucAnyBSSID); |
| prConnSettings->fgIsConnByBssidIssued = FALSE; |
| |
| prConnSettings->fgIsConnReqIssued = FALSE; |
| prConnSettings->fgIsDisconnectedByNonRequest = FALSE; |
| |
| prConnSettings->ucSSIDLen = 0; |
| |
| prConnSettings->eOPMode = NET_TYPE_INFRA; |
| |
| prConnSettings->eConnectionPolicy = CONNECT_BY_SSID_BEST_RSSI; |
| |
| if (prRegInfo) { |
| prConnSettings->ucAdHocChannelNum = (UINT_8) nicFreq2ChannelNum(prRegInfo->u4StartFreq); |
| prConnSettings->eAdHocBand = prRegInfo->u4StartFreq < 5000000 ? BAND_2G4 : BAND_5G; |
| prConnSettings->eAdHocMode = (ENUM_PARAM_AD_HOC_MODE_T) (prRegInfo->u4AdhocMode); |
| } |
| |
| prConnSettings->eAuthMode = AUTH_MODE_OPEN; |
| |
| prConnSettings->eEncStatus = ENUM_ENCRYPTION_DISABLED; |
| |
| prConnSettings->fgIsScanReqIssued = FALSE; |
| |
| /* MIB attributes */ |
| prConnSettings->u2BeaconPeriod = DOT11_BEACON_PERIOD_DEFAULT; |
| |
| prConnSettings->u2RTSThreshold = DOT11_RTS_THRESHOLD_DEFAULT; |
| |
| prConnSettings->u2DesiredNonHTRateSet = RATE_SET_ALL_ABG; |
| |
| /* prConnSettings->u4FreqInKHz; *//* Center frequency */ |
| |
| /* Set U-APSD AC */ |
| prConnSettings->bmfgApsdEnAc = PM_UAPSD_NONE; |
| |
| secInit(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); |
| |
| /* Features */ |
| prConnSettings->fgIsEnableRoaming = FALSE; |
| #if CFG_SUPPORT_ROAMING |
| #if 0 |
| if (prRegInfo) |
| prConnSettings->fgIsEnableRoaming = ((prRegInfo->fgDisRoaming > 0) ? (FALSE) : (TRUE)); |
| #else |
| if (prAdapter->rWifiVar.fgDisRoaming) |
| prConnSettings->fgIsEnableRoaming = FALSE; |
| else |
| prConnSettings->fgIsEnableRoaming = TRUE; |
| #endif |
| #endif /* CFG_SUPPORT_ROAMING */ |
| |
| prConnSettings->fgIsAdHocQoSEnable = FALSE; |
| |
| #if CFG_SUPPORT_802_11AC |
| prConnSettings->eDesiredPhyConfig = PHY_CONFIG_802_11ABGNAC; |
| #else |
| prConnSettings->eDesiredPhyConfig = PHY_CONFIG_802_11ABGN; |
| #endif |
| |
| /* Set default bandwidth modes */ |
| prConnSettings->uc2G4BandwidthMode = CONFIG_BW_20M; |
| prConnSettings->uc5GBandwidthMode = CONFIG_BW_20_40M; |
| |
| prConnSettings->rRsnInfo.ucElemId = 0x30; |
| prConnSettings->rRsnInfo.u2Version = 0x0001; |
| prConnSettings->rRsnInfo.u4GroupKeyCipherSuite = 0; |
| prConnSettings->rRsnInfo.u4PairwiseKeyCipherSuiteCount = 0; |
| for (i = 0; i < MAX_NUM_SUPPORTED_CIPHER_SUITES; i++) |
| prConnSettings->rRsnInfo.au4PairwiseKeyCipherSuite[i] = 0; |
| prConnSettings->rRsnInfo.u4AuthKeyMgtSuiteCount = 0; |
| for (i = 0; i < MAX_NUM_SUPPORTED_AKM_SUITES; i++) |
| prConnSettings->rRsnInfo.au4AuthKeyMgtSuite[i] = 0; |
| prConnSettings->rRsnInfo.u2RsnCap = 0; |
| prConnSettings->rRsnInfo.fgRsnCapPresent = FALSE; |
| } /* end of aisFsmInitializeConnectionSettings() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief the function is used to initialize the value in AIS_FSM_INFO_T for |
| * AIS FSM operation |
| * |
| * @param (none) |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID aisFsmInit(IN P_ADAPTER_T prAdapter) |
| { |
| P_AIS_FSM_INFO_T prAisFsmInfo; |
| P_BSS_INFO_T prAisBssInfo; |
| P_AIS_SPECIFIC_BSS_INFO_T prAisSpecificBssInfo; |
| UINT_8 i; |
| |
| DEBUGFUNC("aisFsmInit()"); |
| DBGLOG(SW1, INFO, "->aisFsmInit()\n"); |
| |
| prAdapter->prAisBssInfo = prAisBssInfo = cnmGetBssInfoAndInit(prAdapter, NETWORK_TYPE_AIS, FALSE); |
| ASSERT(prAisBssInfo); |
| |
| /* update MAC address */ |
| COPY_MAC_ADDR(prAdapter->prAisBssInfo->aucOwnMacAddr, prAdapter->rMyMacAddr); |
| |
| prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); |
| prAisSpecificBssInfo = &(prAdapter->rWifiVar.rAisSpecificBssInfo); |
| |
| /* 4 <1> Initiate FSM */ |
| prAisFsmInfo->ePreviousState = AIS_STATE_IDLE; |
| prAisFsmInfo->eCurrentState = AIS_STATE_IDLE; |
| |
| prAisFsmInfo->ucAvailableAuthTypes = 0; |
| |
| prAisFsmInfo->prTargetBssDesc = (P_BSS_DESC_T) NULL; |
| |
| prAisFsmInfo->ucSeqNumOfReqMsg = 0; |
| prAisFsmInfo->ucSeqNumOfChReq = 0; |
| prAisFsmInfo->ucSeqNumOfScanReq = 0; |
| |
| prAisFsmInfo->fgIsInfraChannelFinished = TRUE; |
| #if CFG_SUPPORT_ROAMING |
| prAisFsmInfo->fgIsRoamingScanPending = FALSE; |
| #endif /* CFG_SUPPORT_ROAMING */ |
| prAisFsmInfo->fgIsChannelRequested = FALSE; |
| prAisFsmInfo->fgIsChannelGranted = FALSE; |
| |
| /* 4 <1.1> Initiate FSM - Timer INIT */ |
| cnmTimerInitTimer(prAdapter, |
| &prAisFsmInfo->rBGScanTimer, |
| (PFN_MGMT_TIMEOUT_FUNC) aisFsmRunEventBGSleepTimeOut, (ULONG) NULL); |
| |
| cnmTimerInitTimer(prAdapter, |
| &prAisFsmInfo->rIbssAloneTimer, |
| (PFN_MGMT_TIMEOUT_FUNC) aisFsmRunEventIbssAloneTimeOut, (ULONG) NULL); |
| |
| cnmTimerInitTimer(prAdapter, |
| &prAisFsmInfo->rIndicationOfDisconnectTimer, |
| (PFN_MGMT_TIMEOUT_FUNC) aisPostponedEventOfDisconnTimeout, (ULONG) NULL); |
| |
| cnmTimerInitTimer(prAdapter, |
| &prAisFsmInfo->rScanDoneTimer, |
| (PFN_MGMT_TIMEOUT_FUNC) aisFsmRunEventScanDoneTimeOut, (ULONG) NULL); |
| |
| cnmTimerInitTimer(prAdapter, |
| &prAisFsmInfo->rJoinTimeoutTimer, |
| (PFN_MGMT_TIMEOUT_FUNC) aisFsmRunEventJoinTimeout, (ULONG) NULL); |
| |
| cnmTimerInitTimer(prAdapter, |
| &prAisFsmInfo->rDeauthDoneTimer, |
| (PFN_MGMT_TIMEOUT_FUNC) aisFsmRunEventDeauthTimeout, (ULONG) NULL); |
| |
| /* 4 <1.2> Initiate PWR STATE */ |
| SET_NET_PWR_STATE_IDLE(prAdapter, prAisBssInfo->ucBssIndex); |
| |
| /* 4 <2> Initiate BSS_INFO_T - common part */ |
| BSS_INFO_INIT(prAdapter, prAisBssInfo); |
| COPY_MAC_ADDR(prAisBssInfo->aucOwnMacAddr, prAdapter->rWifiVar.aucMacAddress); |
| |
| /* 4 <3> Initiate BSS_INFO_T - private part */ |
| /* TODO */ |
| prAisBssInfo->eBand = BAND_2G4; |
| prAisBssInfo->ucPrimaryChannel = 1; |
| prAisBssInfo->prStaRecOfAP = (P_STA_RECORD_T) NULL; |
| prAisBssInfo->ucNss = wlanGetSupportNss(prAdapter, prAisBssInfo->ucBssIndex); |
| prAisBssInfo->eDBDCBand = ENUM_BAND_0; |
| #if (CFG_HW_WMM_BY_BSS == 0) |
| prAisBssInfo->ucWmmQueSet = |
| (prAdapter->rWifiVar.ucDbdcMode == DBDC_MODE_DISABLED) ? DBDC_5G_WMM_INDEX : DBDC_2G_WMM_INDEX; |
| #endif |
| /* 4 <4> Allocate MSDU_INFO_T for Beacon */ |
| prAisBssInfo->prBeacon = cnmMgtPktAlloc(prAdapter, |
| OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem[0]) + MAX_IE_LENGTH); |
| |
| if (prAisBssInfo->prBeacon) { |
| prAisBssInfo->prBeacon->eSrc = TX_PACKET_MGMT; |
| prAisBssInfo->prBeacon->ucStaRecIndex = 0xFF; /* NULL STA_REC */ |
| } else { |
| ASSERT(0); |
| } |
| |
| prAisBssInfo->ucBMCWlanIndex = WTBL_RESERVED_ENTRY; |
| |
| for (i = 0; i < MAX_KEY_NUM; i++) { |
| prAisBssInfo->ucBMCWlanIndexS[i] = WTBL_RESERVED_ENTRY; |
| prAisBssInfo->ucBMCWlanIndexSUsed[i] = FALSE; |
| prAisBssInfo->wepkeyUsed[i] = FALSE; |
| } |
| #if 0 |
| prAisBssInfo->rPmProfSetupInfo.ucBmpDeliveryAC = PM_UAPSD_ALL; |
| prAisBssInfo->rPmProfSetupInfo.ucBmpTriggerAC = PM_UAPSD_ALL; |
| prAisBssInfo->rPmProfSetupInfo.ucUapsdSp = WMM_MAX_SP_LENGTH_2; |
| #else |
| if (prAdapter->u4UapsdAcBmp == 0) { |
| prAdapter->u4UapsdAcBmp = CFG_INIT_UAPSD_AC_BMP; |
| /* ASSERT(prAdapter->u4UapsdAcBmp); */ |
| } |
| prAisBssInfo->rPmProfSetupInfo.ucBmpDeliveryAC = (UINT_8) prAdapter->u4UapsdAcBmp; |
| prAisBssInfo->rPmProfSetupInfo.ucBmpTriggerAC = (UINT_8) prAdapter->u4UapsdAcBmp; |
| prAisBssInfo->rPmProfSetupInfo.ucUapsdSp = (UINT_8) prAdapter->u4MaxSpLen; |
| #endif |
| |
| /* request list initialization */ |
| LINK_INITIALIZE(&prAisFsmInfo->rPendingReqList); |
| |
| /* DBGPRINTF("[2] ucBmpDeliveryAC:0x%x, ucBmpTriggerAC:0x%x, ucUapsdSp:0x%x", */ |
| /* prAisBssInfo->rPmProfSetupInfo.ucBmpDeliveryAC, */ |
| /* prAisBssInfo->rPmProfSetupInfo.ucBmpTriggerAC, */ |
| /* prAisBssInfo->rPmProfSetupInfo.ucUapsdSp); */ |
| |
| /* Bind NetDev & BssInfo */ |
| /* wlanBindBssIdxToNetInterface(prAdapter->prGlueInfo, NET_DEV_WLAN_IDX, prAisBssInfo->ucBssIndex); */ |
| } /* end of aisFsmInit() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief the function is used to uninitialize the value in AIS_FSM_INFO_T for |
| * AIS FSM operation |
| * |
| * @param (none) |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID aisFsmUninit(IN P_ADAPTER_T prAdapter) |
| { |
| P_AIS_FSM_INFO_T prAisFsmInfo; |
| P_BSS_INFO_T prAisBssInfo; |
| |
| DEBUGFUNC("aisFsmUninit()"); |
| DBGLOG(SW1, INFO, "->aisFsmUninit()\n"); |
| |
| prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); |
| prAisBssInfo = prAdapter->prAisBssInfo; |
| |
| /* 4 <1> Stop all timers */ |
| cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rBGScanTimer); |
| cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rIbssAloneTimer); |
| cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rIndicationOfDisconnectTimer); |
| cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rJoinTimeoutTimer); |
| cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rScanDoneTimer); |
| |
| /* 4 <2> flush pending request */ |
| aisFsmFlushRequest(prAdapter); |
| |
| /* 4 <3> Reset driver-domain BSS-INFO */ |
| if (prAisBssInfo) { |
| |
| if (prAisBssInfo->prBeacon) { |
| cnmMgtPktFree(prAdapter, prAisBssInfo->prBeacon); |
| prAisBssInfo->prBeacon = NULL; |
| } |
| |
| cnmFreeBssInfo(prAdapter, prAisBssInfo); |
| prAdapter->prAisBssInfo = NULL; |
| } |
| |
| #if CFG_SUPPORT_802_11W |
| rsnStopSaQuery(prAdapter); |
| #endif |
| } /* end of aisFsmUninit() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Initialization of JOIN STATE |
| * |
| * @param[in] prBssDesc The pointer of BSS_DESC_T which is the BSS we will try to join with. |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID aisFsmStateInit_JOIN(IN P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc) |
| { |
| P_AIS_FSM_INFO_T prAisFsmInfo; |
| P_BSS_INFO_T prAisBssInfo; |
| P_AIS_SPECIFIC_BSS_INFO_T prAisSpecificBssInfo; |
| P_CONNECTION_SETTINGS_T prConnSettings; |
| P_STA_RECORD_T prStaRec; |
| P_MSG_JOIN_REQ_T prJoinReqMsg; |
| |
| DEBUGFUNC("aisFsmStateInit_JOIN()"); |
| |
| prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); |
| prAisBssInfo = prAdapter->prAisBssInfo; |
| prAisSpecificBssInfo = &(prAdapter->rWifiVar.rAisSpecificBssInfo); |
| prConnSettings = &(prAdapter->rWifiVar.rConnSettings); |
| |
| ASSERT(prBssDesc); |
| |
| /* 4 <1> We are going to connect to this BSS. */ |
| prBssDesc->fgIsConnecting = TRUE; |
| |
| /* 4 <2> Setup corresponding STA_RECORD_T */ |
| prStaRec = bssCreateStaRecFromBssDesc(prAdapter, |
| STA_TYPE_LEGACY_AP, prAdapter->prAisBssInfo->ucBssIndex, prBssDesc); |
| |
| prAisFsmInfo->prTargetStaRec = prStaRec; |
| |
| /* 4 <2.1> sync. to firmware domain */ |
| if (prStaRec->ucStaState == STA_STATE_1) |
| cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); |
| |
| /* 4 <3> Update ucAvailableAuthTypes which we can choice during SAA */ |
| if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_DISCONNECTED) { |
| |
| prStaRec->fgIsReAssoc = FALSE; |
| |
| switch (prConnSettings->eAuthMode) { |
| case AUTH_MODE_OPEN: /* Note: Omit break here. */ |
| case AUTH_MODE_WPA: |
| case AUTH_MODE_WPA_PSK: |
| case AUTH_MODE_WPA2: |
| case AUTH_MODE_WPA2_PSK: |
| prAisFsmInfo->ucAvailableAuthTypes = (UINT_8) AUTH_TYPE_OPEN_SYSTEM; |
| break; |
| |
| case AUTH_MODE_SHARED: |
| prAisFsmInfo->ucAvailableAuthTypes = (UINT_8) AUTH_TYPE_SHARED_KEY; |
| break; |
| |
| case AUTH_MODE_AUTO_SWITCH: |
| DBGLOG(AIS, LOUD, "JOIN INIT: eAuthMode == AUTH_MODE_AUTO_SWITCH\n"); |
| prAisFsmInfo->ucAvailableAuthTypes = (UINT_8) (AUTH_TYPE_OPEN_SYSTEM | AUTH_TYPE_SHARED_KEY); |
| break; |
| |
| default: |
| ASSERT(!(prConnSettings->eAuthMode == AUTH_MODE_WPA_NONE)); |
| DBGLOG(AIS, ERROR, |
| "JOIN INIT: Auth Algorithm : %d was not supported by JOIN\n", prConnSettings->eAuthMode); |
| /* TODO(Kevin): error handling ? */ |
| return; |
| } |
| |
| /* TODO(tyhsu): Assume that Roaming Auth Type is equal to ConnSettings eAuthMode */ |
| prAisSpecificBssInfo->ucRoamingAuthTypes = prAisFsmInfo->ucAvailableAuthTypes; |
| |
| prStaRec->ucTxAuthAssocRetryLimit = TX_AUTH_ASSOCI_RETRY_LIMIT; |
| |
| /* Update Bss info before join */ |
| prAisBssInfo->eBand = prBssDesc->eBand; |
| prAisBssInfo->ucPrimaryChannel = prBssDesc->ucChannelNum; |
| |
| } else { |
| ASSERT(prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE); |
| ASSERT(!prBssDesc->fgIsConnected); |
| |
| DBGLOG(AIS, LOUD, "JOIN INIT: AUTH TYPE = %d for Roaming\n", prAisSpecificBssInfo->ucRoamingAuthTypes); |
| |
| prStaRec->fgIsReAssoc = TRUE; /* We do roaming while the medium is connected */ |
| |
| /* TODO(Kevin): We may call a sub function to acquire the Roaming Auth Type */ |
| prAisFsmInfo->ucAvailableAuthTypes = prAisSpecificBssInfo->ucRoamingAuthTypes; |
| |
| prStaRec->ucTxAuthAssocRetryLimit = TX_AUTH_ASSOCI_RETRY_LIMIT_FOR_ROAMING; |
| } |
| |
| /* 4 <4> Use an appropriate Authentication Algorithm Number among the ucAvailableAuthTypes */ |
| if (prAisFsmInfo->ucAvailableAuthTypes & (UINT_8) AUTH_TYPE_OPEN_SYSTEM) { |
| |
| DBGLOG(AIS, LOUD, "JOIN INIT: Try to do Authentication with AuthType == OPEN_SYSTEM.\n"); |
| prAisFsmInfo->ucAvailableAuthTypes &= ~(UINT_8) AUTH_TYPE_OPEN_SYSTEM; |
| |
| prStaRec->ucAuthAlgNum = (UINT_8) AUTH_ALGORITHM_NUM_OPEN_SYSTEM; |
| } else if (prAisFsmInfo->ucAvailableAuthTypes & (UINT_8) AUTH_TYPE_SHARED_KEY) { |
| |
| DBGLOG(AIS, LOUD, "JOIN INIT: Try to do Authentication with AuthType == SHARED_KEY.\n"); |
| |
| prAisFsmInfo->ucAvailableAuthTypes &= ~(UINT_8) AUTH_TYPE_SHARED_KEY; |
| |
| prStaRec->ucAuthAlgNum = (UINT_8) AUTH_ALGORITHM_NUM_SHARED_KEY; |
| } else if (prAisFsmInfo->ucAvailableAuthTypes & (UINT_8) AUTH_TYPE_FAST_BSS_TRANSITION) { |
| |
| DBGLOG(AIS, LOUD, "JOIN INIT: Try to do Authentication with AuthType == FAST_BSS_TRANSITION.\n"); |
| |
| prAisFsmInfo->ucAvailableAuthTypes &= ~(UINT_8) AUTH_TYPE_FAST_BSS_TRANSITION; |
| |
| prStaRec->ucAuthAlgNum = (UINT_8) AUTH_ALGORITHM_NUM_FAST_BSS_TRANSITION; |
| } else { |
| ASSERT(0); |
| } |
| |
| /* 4 <5> Overwrite Connection Setting for eConnectionPolicy == ANY (Used by Assoc Req) */ |
| if (prBssDesc->ucSSIDLen) |
| COPY_SSID(prConnSettings->aucSSID, prConnSettings->ucSSIDLen, prBssDesc->aucSSID, prBssDesc->ucSSIDLen); |
| /* 4 <6> Send a Msg to trigger SAA to start JOIN process. */ |
| prJoinReqMsg = (P_MSG_JOIN_REQ_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_JOIN_REQ_T)); |
| if (!prJoinReqMsg) { |
| |
| ASSERT(0); /* Can't trigger SAA FSM */ |
| return; |
| } |
| |
| prJoinReqMsg->rMsgHdr.eMsgId = MID_AIS_SAA_FSM_START; |
| prJoinReqMsg->ucSeqNum = ++prAisFsmInfo->ucSeqNumOfReqMsg; |
| prJoinReqMsg->prStaRec = prStaRec; |
| |
| if (1) { |
| int j; |
| P_FRAG_INFO_T prFragInfo; |
| |
| for (j = 0; j < MAX_NUM_CONCURRENT_FRAGMENTED_MSDUS; j++) { |
| prFragInfo = &prStaRec->rFragInfo[j]; |
| |
| if (prFragInfo->pr1stFrag) { |
| /* nicRxReturnRFB(prAdapter, prFragInfo->pr1stFrag); */ |
| prFragInfo->pr1stFrag = (P_SW_RFB_T) NULL; |
| } |
| } |
| } |
| |
| mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prJoinReqMsg, MSG_SEND_METHOD_BUF); |
| } /* end of aisFsmInit_JOIN() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Retry JOIN for AUTH_MODE_AUTO_SWITCH |
| * |
| * @param[in] prStaRec Pointer to the STA_RECORD_T |
| * |
| * @retval TRUE We will retry JOIN |
| * @retval FALSE We will not retry JOIN |
| */ |
| /*----------------------------------------------------------------------------*/ |
| BOOLEAN aisFsmStateInit_RetryJOIN(IN P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec) |
| { |
| P_AIS_FSM_INFO_T prAisFsmInfo; |
| P_MSG_JOIN_REQ_T prJoinReqMsg; |
| |
| DEBUGFUNC("aisFsmStateInit_RetryJOIN()"); |
| |
| prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); |
| |
| /* Retry other AuthType if possible */ |
| if (!prAisFsmInfo->ucAvailableAuthTypes) |
| return FALSE; |
| |
| if (prAisFsmInfo->ucAvailableAuthTypes & (UINT_8) AUTH_TYPE_SHARED_KEY) { |
| |
| DBGLOG(AIS, INFO, "RETRY JOIN INIT: Retry Authentication with AuthType == SHARED_KEY.\n"); |
| |
| prAisFsmInfo->ucAvailableAuthTypes &= ~(UINT_8) AUTH_TYPE_SHARED_KEY; |
| |
| prStaRec->ucAuthAlgNum = (UINT_8) AUTH_ALGORITHM_NUM_SHARED_KEY; |
| } else { |
| DBGLOG(AIS, ERROR, "RETRY JOIN INIT: Retry Authentication with Unexpected AuthType.\n"); |
| ASSERT(0); |
| } |
| |
| prAisFsmInfo->ucAvailableAuthTypes = 0; /* No more available Auth Types */ |
| |
| /* Trigger SAA to start JOIN process. */ |
| prJoinReqMsg = (P_MSG_JOIN_REQ_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_JOIN_REQ_T)); |
| if (!prJoinReqMsg) { |
| |
| ASSERT(0); /* Can't trigger SAA FSM */ |
| return FALSE; |
| } |
| |
| prJoinReqMsg->rMsgHdr.eMsgId = MID_AIS_SAA_FSM_START; |
| prJoinReqMsg->ucSeqNum = ++prAisFsmInfo->ucSeqNumOfReqMsg; |
| prJoinReqMsg->prStaRec = prStaRec; |
| |
| mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prJoinReqMsg, MSG_SEND_METHOD_BUF); |
| |
| return TRUE; |
| |
| } /* end of aisFsmRetryJOIN() */ |
| |
| #if CFG_SUPPORT_ADHOC |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief State Initialization of AIS_STATE_IBSS_ALONE |
| * |
| * @param (none) |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID aisFsmStateInit_IBSS_ALONE(IN P_ADAPTER_T prAdapter) |
| { |
| P_AIS_FSM_INFO_T prAisFsmInfo; |
| P_CONNECTION_SETTINGS_T prConnSettings; |
| P_BSS_INFO_T prAisBssInfo; |
| |
| prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); |
| prConnSettings = &(prAdapter->rWifiVar.rConnSettings); |
| prAisBssInfo = prAdapter->prAisBssInfo; |
| |
| /* 4 <1> Check if IBSS was created before ? */ |
| if (prAisBssInfo->fgIsBeaconActivated) { |
| |
| /* 4 <2> Start IBSS Alone Timer for periodic SCAN and then SEARCH */ |
| #if !CFG_SLT_SUPPORT |
| cnmTimerStartTimer(prAdapter, &prAisFsmInfo->rIbssAloneTimer, SEC_TO_MSEC(AIS_IBSS_ALONE_TIMEOUT_SEC)); |
| #endif |
| } |
| |
| aisFsmCreateIBSS(prAdapter); |
| } /* end of aisFsmStateInit_IBSS_ALONE() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief State Initialization of AIS_STATE_IBSS_MERGE |
| * |
| * @param[in] prBssDesc The pointer of BSS_DESC_T which is the IBSS we will try to merge with. |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID aisFsmStateInit_IBSS_MERGE(IN P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc) |
| { |
| P_AIS_FSM_INFO_T prAisFsmInfo; |
| P_CONNECTION_SETTINGS_T prConnSettings; |
| P_BSS_INFO_T prAisBssInfo; |
| P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; |
| |
| ASSERT(prBssDesc); |
| |
| prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); |
| prConnSettings = &(prAdapter->rWifiVar.rConnSettings); |
| prAisBssInfo = prAdapter->prAisBssInfo; |
| |
| /* 4 <1> We will merge with to this BSS immediately. */ |
| prBssDesc->fgIsConnecting = FALSE; |
| prBssDesc->fgIsConnected = TRUE; |
| |
| /* 4 <2> Setup corresponding STA_RECORD_T */ |
| prStaRec = bssCreateStaRecFromBssDesc(prAdapter, |
| STA_TYPE_ADHOC_PEER, prAdapter->prAisBssInfo->ucBssIndex, prBssDesc); |
| |
| prStaRec->fgIsMerging = TRUE; |
| |
| prAisFsmInfo->prTargetStaRec = prStaRec; |
| |
| /* 4 <2.1> sync. to firmware domain */ |
| cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); |
| |
| /* 4 <3> IBSS-Merge */ |
| aisFsmMergeIBSS(prAdapter, prStaRec); |
| } /* end of aisFsmStateInit_IBSS_MERGE() */ |
| |
| #endif /* CFG_SUPPORT_ADHOC */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Process of JOIN Abort |
| * |
| * @param (none) |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID aisFsmStateAbort_JOIN(IN P_ADAPTER_T prAdapter) |
| { |
| P_AIS_FSM_INFO_T prAisFsmInfo; |
| P_MSG_JOIN_ABORT_T prJoinAbortMsg; |
| |
| prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); |
| |
| /* 1. Abort JOIN process */ |
| prJoinAbortMsg = (P_MSG_JOIN_ABORT_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_JOIN_ABORT_T)); |
| if (!prJoinAbortMsg) { |
| |
| ASSERT(0); /* Can't abort SAA FSM */ |
| return; |
| } |
| |
| prJoinAbortMsg->rMsgHdr.eMsgId = MID_AIS_SAA_FSM_ABORT; |
| prJoinAbortMsg->ucSeqNum = prAisFsmInfo->ucSeqNumOfReqMsg; |
| prJoinAbortMsg->prStaRec = prAisFsmInfo->prTargetStaRec; |
| |
| scanRemoveConnFlagOfBssDescByBssid(prAdapter, prAisFsmInfo->prTargetStaRec->aucMacAddr); |
| |
| mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prJoinAbortMsg, MSG_SEND_METHOD_BUF); |
| |
| /* 2. Return channel privilege */ |
| aisFsmReleaseCh(prAdapter); |
| |
| /* 3.1 stop join timeout timer */ |
| cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rJoinTimeoutTimer); |
| |
| /* 3.2 reset local variable */ |
| prAisFsmInfo->fgIsInfraChannelFinished = TRUE; |
| } /* end of aisFsmAbortJOIN() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Process of SCAN Abort |
| * |
| * @param (none) |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID aisFsmStateAbort_SCAN(IN P_ADAPTER_T prAdapter) |
| { |
| P_AIS_FSM_INFO_T prAisFsmInfo; |
| P_MSG_SCN_SCAN_CANCEL prScanCancelMsg; |
| |
| prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); |
| |
| DBGLOG(AIS, STATE, "aisFsmStateAbort_SCAN\n"); |
| |
| /* Abort JOIN process. */ |
| prScanCancelMsg = (P_MSG_SCN_SCAN_CANCEL) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_SCN_SCAN_CANCEL)); |
| if (!prScanCancelMsg) { |
| |
| ASSERT(0); /* Can't abort SCN FSM */ |
| return; |
| } |
| |
| prScanCancelMsg->rMsgHdr.eMsgId = MID_AIS_SCN_SCAN_CANCEL; |
| prScanCancelMsg->ucSeqNum = prAisFsmInfo->ucSeqNumOfScanReq; |
| prScanCancelMsg->ucBssIndex = prAdapter->prAisBssInfo->ucBssIndex; |
| prScanCancelMsg->fgIsChannelExt = FALSE; |
| |
| /* unbuffered message to guarantee scan is cancelled in sequence */ |
| mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prScanCancelMsg, MSG_SEND_METHOD_UNBUF); |
| } /* end of aisFsmAbortSCAN() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Process of NORMAL_TR Abort |
| * |
| * @param (none) |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID aisFsmStateAbort_NORMAL_TR(IN P_ADAPTER_T prAdapter) |
| { |
| P_AIS_FSM_INFO_T prAisFsmInfo; |
| |
| ASSERT(prAdapter); |
| prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); |
| |
| /* TODO(Kevin): Do abort other MGMT func */ |
| |
| /* 1. Release channel to CNM */ |
| aisFsmReleaseCh(prAdapter); |
| |
| /* 2.1 stop join timeout timer */ |
| cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rJoinTimeoutTimer); |
| |
| /* 2.2 reset local variable */ |
| prAisFsmInfo->fgIsInfraChannelFinished = TRUE; |
| } /* end of aisFsmAbortNORMAL_TR() */ |
| |
| #if CFG_SUPPORT_ADHOC |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Process of NORMAL_TR Abort |
| * |
| * @param (none) |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID aisFsmStateAbort_IBSS(IN P_ADAPTER_T prAdapter) |
| { |
| P_AIS_FSM_INFO_T prAisFsmInfo; |
| P_BSS_DESC_T prBssDesc; |
| |
| prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); |
| |
| /* reset BSS-DESC */ |
| if (prAisFsmInfo->prTargetStaRec) { |
| prBssDesc = scanSearchBssDescByTA(prAdapter, prAisFsmInfo->prTargetStaRec->aucMacAddr); |
| |
| if (prBssDesc) { |
| prBssDesc->fgIsConnected = FALSE; |
| prBssDesc->fgIsConnecting = FALSE; |
| } |
| } |
| /* release channel privilege */ |
| aisFsmReleaseCh(prAdapter); |
| } |
| #endif /* CFG_SUPPORT_ADHOC */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief The Core FSM engine of AIS(Ad-hoc, Infra STA) |
| * |
| * @param[in] eNextState Enum value of next AIS STATE |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID aisFsmSteps(IN P_ADAPTER_T prAdapter, ENUM_AIS_STATE_T eNextState) |
| { |
| P_AIS_FSM_INFO_T prAisFsmInfo; |
| P_BSS_INFO_T prAisBssInfo; |
| P_CONNECTION_SETTINGS_T prConnSettings; |
| P_BSS_DESC_T prBssDesc; |
| P_MSG_CH_REQ_T prMsgChReq; |
| P_MSG_SCN_SCAN_REQ_V2 prScanReqMsg; |
| P_AIS_REQ_HDR_T prAisReq; |
| ENUM_BAND_T eBand; |
| UINT_8 ucChannel; |
| UINT_16 u2ScanIELen; |
| BOOLEAN fgIsTransition = (BOOLEAN) FALSE; |
| #if CFG_SUPPORT_DBDC |
| CNM_DBDC_CAP_T rDbdcCap; |
| #endif /*CFG_SUPPORT_DBDC*/ |
| |
| DEBUGFUNC("aisFsmSteps()"); |
| |
| prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); |
| prAisBssInfo = prAdapter->prAisBssInfo; |
| prConnSettings = &(prAdapter->rWifiVar.rConnSettings); |
| |
| do { |
| |
| /* Do entering Next State */ |
| prAisFsmInfo->ePreviousState = prAisFsmInfo->eCurrentState; |
| |
| DBGLOG(AIS, STATE, "[AIS]TRANSITION: [%s] -> [%s]\n", |
| apucDebugAisState[prAisFsmInfo->eCurrentState], apucDebugAisState[eNextState]); |
| |
| /* NOTE(Kevin): This is the only place to change the eCurrentState(except initial) */ |
| prAisFsmInfo->eCurrentState = eNextState; |
| |
| fgIsTransition = (BOOLEAN) FALSE; |
| |
| /* Do tasks of the State that we just entered */ |
| switch (prAisFsmInfo->eCurrentState) { |
| /* NOTE(Kevin): we don't have to rearrange the sequence of following |
| * switch case. Instead I would like to use a common lookup table of array |
| * of function pointer to speed up state search. |
| */ |
| case AIS_STATE_IDLE: |
| |
| prAisReq = aisFsmGetNextRequest(prAdapter); |
| cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rScanDoneTimer); |
| |
| if (prAisReq == NULL || prAisReq->eReqType == AIS_REQUEST_RECONNECT) { |
| if (prConnSettings->fgIsConnReqIssued == TRUE && |
| prConnSettings->fgIsDisconnectedByNonRequest == FALSE) { |
| |
| prAisFsmInfo->fgTryScan = TRUE; |
| |
| if (!IS_NET_ACTIVE(prAdapter, prAdapter->prAisBssInfo->ucBssIndex)) { |
| SET_NET_ACTIVE(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); |
| /* sync with firmware */ |
| nicActivateNetwork(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); |
| } |
| |
| SET_NET_PWR_STATE_ACTIVE(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); |
| |
| prAisBssInfo->fgIsNetRequestInActive = FALSE; |
| |
| /* reset trial count */ |
| prAisFsmInfo->ucConnTrialCount = 0; |
| |
| eNextState = AIS_STATE_SEARCH; |
| fgIsTransition = TRUE; |
| } else { |
| SET_NET_PWR_STATE_IDLE(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); |
| |
| /* sync with firmware */ |
| #if CFG_SUPPORT_PNO |
| prAisBssInfo->fgIsNetRequestInActive = TRUE; |
| if (prAisBssInfo->fgIsPNOEnable) { |
| DBGLOG(BSS, INFO, |
| "[BSSidx][Network]=%d PNOEnable&&OP_MODE_INFRASTRUCTURE,KEEP ACTIVE\n", |
| prAisBssInfo->ucBssIndex); |
| } else |
| #endif |
| { |
| UNSET_NET_ACTIVE(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); |
| nicDeactivateNetwork(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); |
| } |
| |
| /* check for other pending request */ |
| if (prAisReq && (aisFsmIsRequestPending |
| (prAdapter, AIS_REQUEST_SCAN, TRUE) == TRUE)) { |
| wlanClearScanningResult(prAdapter); |
| eNextState = AIS_STATE_SCAN; |
| |
| fgIsTransition = TRUE; |
| } |
| } |
| |
| if (prAisReq) { |
| /* free the message */ |
| cnmMemFree(prAdapter, prAisReq); |
| } |
| } else if (prAisReq->eReqType == AIS_REQUEST_SCAN) { |
| #if CFG_SUPPORT_ROAMING |
| prAisFsmInfo->fgIsRoamingScanPending = FALSE; |
| #endif /* CFG_SUPPORT_ROAMING */ |
| wlanClearScanningResult(prAdapter); |
| |
| eNextState = AIS_STATE_SCAN; |
| fgIsTransition = TRUE; |
| |
| /* free the message */ |
| cnmMemFree(prAdapter, prAisReq); |
| } else if (prAisReq->eReqType == AIS_REQUEST_ROAMING_CONNECT |
| || prAisReq->eReqType == AIS_REQUEST_ROAMING_SEARCH) { |
| /* ignore */ |
| /* free the message */ |
| cnmMemFree(prAdapter, prAisReq); |
| } else if (prAisReq->eReqType == AIS_REQUEST_REMAIN_ON_CHANNEL) { |
| eNextState = AIS_STATE_REQ_REMAIN_ON_CHANNEL; |
| fgIsTransition = TRUE; |
| |
| /* free the message */ |
| cnmMemFree(prAdapter, prAisReq); |
| } |
| |
| prAisFsmInfo->u4SleepInterval = AIS_BG_SCAN_INTERVAL_MIN_SEC; |
| |
| break; |
| |
| case AIS_STATE_SEARCH: |
| /* 4 <1> Search for a matched candidate and save it to prTargetBssDesc. */ |
| #if CFG_SLT_SUPPORT |
| prBssDesc = prAdapter->rWifiVar.rSltInfo.prPseudoBssDesc; |
| #else |
| prBssDesc = scanSearchBssDescByPolicy(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); |
| #endif |
| |
| /* we are under Roaming Condition. */ |
| if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { |
| if (prAisFsmInfo->ucConnTrialCount > AIS_ROAMING_CONNECTION_TRIAL_LIMIT) { |
| #if CFG_SUPPORT_ROAMING |
| roamingFsmRunEventFail(prAdapter, ROAMING_FAIL_REASON_CONNLIMIT); |
| #endif /* CFG_SUPPORT_ROAMING */ |
| /* reset retry count */ |
| prAisFsmInfo->ucConnTrialCount = 0; |
| |
| /* abort connection trial */ |
| prConnSettings->fgIsConnReqIssued = FALSE; |
| |
| eNextState = AIS_STATE_NORMAL_TR; |
| fgIsTransition = TRUE; |
| |
| break; |
| } |
| } |
| /* 4 <2> We are not under Roaming Condition. */ |
| if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_DISCONNECTED) { |
| |
| /* 4 <2.a> If we have the matched one */ |
| if (prBssDesc) { |
| /* 4 <A> Stored the Selected BSS security cipher. */ |
| /* or later asoc req compose IE */ |
| prAisBssInfo->u4RsnSelectedGroupCipher = prBssDesc->u4RsnSelectedGroupCipher; |
| prAisBssInfo->u4RsnSelectedPairwiseCipher = |
| prBssDesc->u4RsnSelectedPairwiseCipher; |
| prAisBssInfo->u4RsnSelectedAKMSuite = prBssDesc->u4RsnSelectedAKMSuite; |
| #if (CFG_HW_WMM_BY_BSS == 1) |
| if (prAisBssInfo->fgIsWmmInited == FALSE) |
| prAisBssInfo->ucWmmQueSet = |
| cnmWmmIndexDecision(prAdapter, prAisBssInfo); |
| #endif |
| #if CFG_SUPPORT_DBDC |
| cnmDbdcEnableDecision(prAdapter, prAisBssInfo->ucBssIndex, prBssDesc->eBand); |
| cnmGetDbdcCapability(prAdapter, prAisBssInfo->ucBssIndex, |
| prBssDesc->eBand, prBssDesc->ucChannelNum, |
| wlanGetSupportNss(prAdapter, prAisBssInfo->ucBssIndex), &rDbdcCap); |
| |
| prAisBssInfo->eDBDCBand = ENUM_BAND_AUTO; |
| prAisBssInfo->ucNss = rDbdcCap.ucNss; |
| #if (CFG_HW_WMM_BY_BSS == 0) |
| prAisBssInfo->ucWmmQueSet = rDbdcCap.ucWmmSetIndex; |
| #endif |
| #endif /*CFG_SUPPORT_DBDC*/ |
| /* 4 <B> Do STATE transition and update current Operation Mode. */ |
| if (prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE) { |
| |
| prAisBssInfo->eCurrentOPMode = OP_MODE_INFRASTRUCTURE; |
| |
| /* Record the target BSS_DESC_T for next STATE. */ |
| prAisFsmInfo->prTargetBssDesc = prBssDesc; |
| |
| /* Transit to channel acquire */ |
| eNextState = AIS_STATE_REQ_CHANNEL_JOIN; |
| fgIsTransition = TRUE; |
| |
| /* increase connection trial count */ |
| prAisFsmInfo->ucConnTrialCount++; |
| } |
| #if CFG_SUPPORT_ADHOC |
| else if (prBssDesc->eBSSType == BSS_TYPE_IBSS) { |
| |
| prAisBssInfo->eCurrentOPMode = OP_MODE_IBSS; |
| |
| /* Record the target BSS_DESC_T for next STATE. */ |
| prAisFsmInfo->prTargetBssDesc = prBssDesc; |
| |
| eNextState = AIS_STATE_IBSS_MERGE; |
| fgIsTransition = TRUE; |
| } |
| #endif /* CFG_SUPPORT_ADHOC */ |
| else { |
| ASSERT(0); |
| eNextState = AIS_STATE_WAIT_FOR_NEXT_SCAN; |
| fgIsTransition = TRUE; |
| } |
| } |
| /* 4 <2.b> If we don't have the matched one */ |
| else { |
| |
| /* increase connection trial count for infrastructure connection */ |
| if (prConnSettings->eOPMode == NET_TYPE_INFRA) |
| prAisFsmInfo->ucConnTrialCount++; |
| |
| /* 4 <A> Try to SCAN */ |
| if (prAisFsmInfo->fgTryScan) { |
| eNextState = AIS_STATE_LOOKING_FOR; |
| |
| fgIsTransition = TRUE; |
| } |
| /* 4 <B> We've do SCAN already, now wait in some STATE. */ |
| else { |
| eNextState = aisFsmStateSearchAction(prAdapter, |
| AIS_FSM_STATE_SEARCH_ACTION_PHASE_0); |
| fgIsTransition = TRUE; |
| } |
| } |
| } |
| /* 4 <3> We are under Roaming Condition. */ |
| else { /* prAdapter->eConnectionState == MEDIA_STATE_CONNECTED. */ |
| |
| /* 4 <3.a> This BSS_DESC_T is our AP. */ |
| /* NOTE(Kevin 2008/05/16): Following cases will go back to NORMAL_TR. |
| * CASE I: During Roaming, APP(WZC/NDISTEST) change the connection |
| * settings. That make we can NOT match the original AP, so the |
| * prBssDesc is NULL. |
| * CASE II: The same reason as CASE I. Because APP change the |
| * eOPMode to other network type in connection setting |
| * (e.g. NET_TYPE_IBSS), so the BssDesc become the IBSS node. |
| * (For CASE I/II, before WZC/NDISTEST set the OID_SSID, it will change |
| * other parameters in connection setting first. So if we do roaming |
| * at the same time, it will hit these cases.) |
| * |
| * CASE III: Normal case, we can't find other candidate to roam |
| * out, so only the current AP will be matched. |
| * |
| * CASE VI: Timestamp of the current AP might be reset |
| */ |
| if (prAisBssInfo->ucReasonOfDisconnect != DISCONNECT_REASON_CODE_REASSOCIATION && |
| ((!prBssDesc) || /* CASE I */ |
| (prBssDesc->eBSSType != BSS_TYPE_INFRASTRUCTURE) || /* CASE II */ |
| (prBssDesc->fgIsConnected) || /* CASE III */ |
| (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, prAisBssInfo->aucBSSID))) /* CASE VI */) { |
| #if DBG |
| if ((prBssDesc) && (prBssDesc->fgIsConnected)) |
| ASSERT(EQUAL_MAC_ADDR(prBssDesc->aucBSSID, prAisBssInfo->aucBSSID)); |
| #endif /* DBG */ |
| /* We already associated with it, go back to NORMAL_TR */ |
| /* TODO(Kevin): Roaming Fail */ |
| #if CFG_SUPPORT_ROAMING |
| roamingFsmRunEventFail(prAdapter, ROAMING_FAIL_REASON_NOCANDIDATE); |
| #endif /* CFG_SUPPORT_ROAMING */ |
| |
| /* Retreat to NORMAL_TR state */ |
| eNextState = AIS_STATE_NORMAL_TR; |
| fgIsTransition = TRUE; |
| } |
| /* 4 <3.b> Try to roam out for JOIN this BSS_DESC_T. */ |
| else { |
| if (prBssDesc == NULL) { |
| fgIsTransition = TRUE; |
| eNextState = aisFsmStateSearchAction(prAdapter, |
| AIS_FSM_STATE_SEARCH_ACTION_PHASE_1); |
| } else { |
| aisFsmStateSearchAction(prAdapter, AIS_FSM_STATE_SEARCH_ACTION_PHASE_2); |
| /* 4 <A> Record the target BSS_DESC_T for next STATE. */ |
| prAisFsmInfo->prTargetBssDesc = prBssDesc; |
| |
| /* tyhsu: increase connection trial count */ |
| prAisFsmInfo->ucConnTrialCount++; |
| |
| /* Transit to channel acquire */ |
| eNextState = AIS_STATE_REQ_CHANNEL_JOIN; |
| fgIsTransition = TRUE; |
| } |
| } |
| } |
| |
| break; |
| |
| case AIS_STATE_WAIT_FOR_NEXT_SCAN: |
| |
| DBGLOG(AIS, LOUD, "SCAN: Idle Begin - Current Time = %u\n", kalGetTimeTick()); |
| |
| cnmTimerStartTimer(prAdapter, |
| &prAisFsmInfo->rBGScanTimer, SEC_TO_MSEC(prAisFsmInfo->u4SleepInterval)); |
| |
| SET_NET_PWR_STATE_IDLE(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); |
| |
| if (prAisFsmInfo->u4SleepInterval < AIS_BG_SCAN_INTERVAL_MAX_SEC) |
| prAisFsmInfo->u4SleepInterval <<= 1; |
| |
| break; |
| |
| case AIS_STATE_SCAN: |
| case AIS_STATE_ONLINE_SCAN: |
| case AIS_STATE_LOOKING_FOR: |
| |
| if (!IS_NET_ACTIVE(prAdapter, prAdapter->prAisBssInfo->ucBssIndex)) { |
| SET_NET_ACTIVE(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); |
| |
| /* sync with firmware */ |
| nicActivateNetwork(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); |
| prAisBssInfo->fgIsNetRequestInActive = FALSE; |
| } |
| |
| /* IE length decision */ |
| if (prAisFsmInfo->u4ScanIELength > 0) { |
| u2ScanIELen = (UINT_16) prAisFsmInfo->u4ScanIELength; |
| } else { |
| #if CFG_SUPPORT_WPS2 |
| u2ScanIELen = prAdapter->prGlueInfo->u2WSCIELen; |
| #else |
| u2ScanIELen = 0; |
| #endif |
| } |
| |
| prScanReqMsg = (P_MSG_SCN_SCAN_REQ_V2) cnmMemAlloc(prAdapter, |
| RAM_TYPE_MSG, |
| OFFSET_OF |
| (MSG_SCN_SCAN_REQ_V2, aucIE) + u2ScanIELen); |
| if (!prScanReqMsg) { |
| ASSERT(0); /* Can't trigger SCAN FSM */ |
| return; |
| } |
| |
| prScanReqMsg->rMsgHdr.eMsgId = MID_AIS_SCN_SCAN_REQ_V2; |
| prScanReqMsg->ucSeqNum = ++prAisFsmInfo->ucSeqNumOfScanReq; |
| prScanReqMsg->ucBssIndex = prAdapter->prAisBssInfo->ucBssIndex; |
| |
| #if CFG_SUPPORT_RDD_TEST_MODE |
| prScanReqMsg->eScanType = SCAN_TYPE_PASSIVE_SCAN; |
| #else |
| if (prAisFsmInfo->eCurrentState == AIS_STATE_SCAN |
| || prAisFsmInfo->eCurrentState == AIS_STATE_ONLINE_SCAN) { |
| if (prAisFsmInfo->ucScanSSIDNum == 0) { |
| #if CFG_SUPPORT_AIS_PASSIVE_SCAN |
| prScanReqMsg->eScanType = SCAN_TYPE_PASSIVE_SCAN; |
| |
| prScanReqMsg->ucSSIDType = 0; |
| prScanReqMsg->ucSSIDNum = 0; |
| #else |
| prScanReqMsg->eScanType = SCAN_TYPE_ACTIVE_SCAN; |
| |
| prScanReqMsg->ucSSIDType = SCAN_REQ_SSID_WILDCARD; |
| prScanReqMsg->ucSSIDNum = 0; |
| #endif |
| } else if (prAisFsmInfo->ucScanSSIDNum == 1 |
| && prAisFsmInfo->arScanSSID[0].u4SsidLen == 0) { |
| prScanReqMsg->eScanType = SCAN_TYPE_ACTIVE_SCAN; |
| |
| prScanReqMsg->ucSSIDType = SCAN_REQ_SSID_WILDCARD; |
| prScanReqMsg->ucSSIDNum = 0; |
| } else { |
| prScanReqMsg->eScanType = SCAN_TYPE_ACTIVE_SCAN; |
| |
| prScanReqMsg->ucSSIDType = SCAN_REQ_SSID_SPECIFIED; |
| prScanReqMsg->ucSSIDNum = prAisFsmInfo->ucScanSSIDNum; |
| prScanReqMsg->prSsid = prAisFsmInfo->arScanSSID; |
| } |
| } else { |
| prScanReqMsg->eScanType = SCAN_TYPE_ACTIVE_SCAN; |
| |
| COPY_SSID(prAisFsmInfo->rRoamingSSID.aucSsid, |
| prAisFsmInfo->rRoamingSSID.u4SsidLen, |
| prConnSettings->aucSSID, prConnSettings->ucSSIDLen); |
| |
| /* Scan for determined SSID */ |
| prScanReqMsg->ucSSIDType = SCAN_REQ_SSID_SPECIFIED; |
| prScanReqMsg->ucSSIDNum = 1; |
| prScanReqMsg->prSsid = &(prAisFsmInfo->rRoamingSSID); |
| } |
| #endif |
| |
| /* using default channel dwell time/timeout value */ |
| prScanReqMsg->u2ProbeDelay = 0; |
| prScanReqMsg->u2ChannelDwellTime = 0; |
| prScanReqMsg->u2TimeoutValue = 0; |
| |
| /* check if tethering is running and need to fix on specific channel */ |
| if (cnmAisInfraChannelFixed(prAdapter, &eBand, &ucChannel) == TRUE) { |
| prScanReqMsg->eScanChannel = SCAN_CHANNEL_SPECIFIED; |
| prScanReqMsg->ucChannelListNum = 1; |
| prScanReqMsg->arChnlInfoList[0].eBand = eBand; |
| prScanReqMsg->arChnlInfoList[0].ucChannelNum = ucChannel; |
| #if CFG_SCAN_CHANNEL_SPECIFIED |
| } else if (is_valid_scan_chnl_cnt(prAisFsmInfo->ucScanChannelListNum)) { |
| prScanReqMsg->eScanChannel = SCAN_CHANNEL_SPECIFIED; |
| prScanReqMsg->ucChannelListNum = prAisFsmInfo->ucScanChannelListNum; |
| kalMemCopy(prScanReqMsg->arChnlInfoList, prAisFsmInfo->arScanChnlInfoList, |
| sizeof(RF_CHANNEL_INFO_T) * prScanReqMsg->ucChannelListNum); |
| #endif |
| } else if (prAdapter->aePreferBand[prAdapter->prAisBssInfo->ucBssIndex] == BAND_NULL) { |
| if (prAdapter->fgEnable5GBand == TRUE) |
| prScanReqMsg->eScanChannel = SCAN_CHANNEL_FULL; |
| else |
| prScanReqMsg->eScanChannel = SCAN_CHANNEL_2G4; |
| |
| } else if (prAdapter->aePreferBand[prAdapter->prAisBssInfo->ucBssIndex] == BAND_2G4) { |
| prScanReqMsg->eScanChannel = SCAN_CHANNEL_2G4; |
| } else if (prAdapter->aePreferBand[prAdapter->prAisBssInfo->ucBssIndex] == BAND_5G) { |
| prScanReqMsg->eScanChannel = SCAN_CHANNEL_5G; |
| } else { |
| prScanReqMsg->eScanChannel = SCAN_CHANNEL_FULL; |
| ASSERT(0); |
| } |
| |
| if (prAisFsmInfo->u4ScanIELength > 0) { |
| kalMemCopy(prScanReqMsg->aucIE, prAisFsmInfo->aucScanIEBuf, |
| prAisFsmInfo->u4ScanIELength); |
| } else { |
| #if CFG_SUPPORT_WPS2 |
| if (prAdapter->prGlueInfo->u2WSCIELen > 0) { |
| kalMemCopy(prScanReqMsg->aucIE, |
| &prAdapter->prGlueInfo->aucWSCIE, prAdapter->prGlueInfo->u2WSCIELen); |
| } |
| } |
| #endif |
| |
| prScanReqMsg->u2IELen = u2ScanIELen; |
| |
| mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prScanReqMsg, MSG_SEND_METHOD_BUF); |
| |
| prAisFsmInfo->fgTryScan = FALSE; /* Will enable background sleep for infrastructure */ |
| |
| break; |
| |
| case AIS_STATE_REQ_CHANNEL_JOIN: |
| /* send message to CNM for acquiring channel */ |
| prMsgChReq = (P_MSG_CH_REQ_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_CH_REQ_T)); |
| if (!prMsgChReq) { |
| ASSERT(0); /* Can't indicate CNM for channel acquiring */ |
| return; |
| } |
| |
| prMsgChReq->rMsgHdr.eMsgId = MID_MNY_CNM_CH_REQ; |
| prMsgChReq->ucBssIndex = prAdapter->prAisBssInfo->ucBssIndex; |
| prMsgChReq->ucTokenID = ++prAisFsmInfo->ucSeqNumOfChReq; |
| prMsgChReq->eReqType = CH_REQ_TYPE_JOIN; |
| prMsgChReq->u4MaxInterval = AIS_JOIN_CH_REQUEST_INTERVAL; |
| prMsgChReq->ucPrimaryChannel = prAisFsmInfo->prTargetBssDesc->ucChannelNum; |
| prMsgChReq->eRfSco = prAisFsmInfo->prTargetBssDesc->eSco; |
| prMsgChReq->eRfBand = prAisFsmInfo->prTargetBssDesc->eBand; |
| #if CFG_SUPPORT_DBDC |
| prMsgChReq->eDBDCBand = ENUM_BAND_AUTO; |
| #endif /*CFG_SUPPORT_DBDC*/ |
| /* To do: check if 80/160MHz bandwidth is needed here */ |
| prMsgChReq->eRfChannelWidth = prAisFsmInfo->prTargetBssDesc->eChannelWidth; |
| prMsgChReq->ucRfCenterFreqSeg1 = prAisFsmInfo->prTargetBssDesc->ucCenterFreqS1; |
| prMsgChReq->ucRfCenterFreqSeg2 = prAisFsmInfo->prTargetBssDesc->ucCenterFreqS2; |
| |
| rlmReviseMaxBw(prAdapter, prAisBssInfo->ucBssIndex, &prMsgChReq->eRfSco, |
| (P_ENUM_CHANNEL_WIDTH_P)&prMsgChReq->eRfChannelWidth, |
| &prMsgChReq->ucRfCenterFreqSeg1, &prMsgChReq->ucPrimaryChannel); |
| |
| mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgChReq, MSG_SEND_METHOD_BUF); |
| |
| prAisFsmInfo->fgIsChannelRequested = TRUE; |
| break; |
| |
| case AIS_STATE_JOIN: |
| aisFsmStateInit_JOIN(prAdapter, prAisFsmInfo->prTargetBssDesc); |
| break; |
| |
| case AIS_STATE_JOIN_FAILURE: |
| prConnSettings->fgIsDisconnectedByNonRequest = TRUE; |
| |
| nicMediaJoinFailure(prAdapter, prAdapter->prAisBssInfo->ucBssIndex, WLAN_STATUS_JOIN_TIMEOUT); |
| |
| eNextState = AIS_STATE_IDLE; |
| fgIsTransition = TRUE; |
| |
| break; |
| |
| #if CFG_SUPPORT_ADHOC |
| case AIS_STATE_IBSS_ALONE: |
| aisFsmStateInit_IBSS_ALONE(prAdapter); |
| break; |
| |
| case AIS_STATE_IBSS_MERGE: |
| aisFsmStateInit_IBSS_MERGE(prAdapter, prAisFsmInfo->prTargetBssDesc); |
| break; |
| #endif /* CFG_SUPPORT_ADHOC */ |
| |
| case AIS_STATE_NORMAL_TR: |
| if (prAisFsmInfo->fgIsInfraChannelFinished == FALSE) { |
| /* Don't do anything when rJoinTimeoutTimer is still ticking */ |
| } else { |
| /* 1. Process for pending scan */ |
| if (aisFsmIsRequestPending(prAdapter, AIS_REQUEST_SCAN, TRUE) == TRUE) { |
| wlanClearScanningResult(prAdapter); |
| eNextState = AIS_STATE_ONLINE_SCAN; |
| fgIsTransition = TRUE; |
| } |
| /* 2. Process for pending roaming scan */ |
| else if (aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_SEARCH, TRUE) == TRUE) { |
| eNextState = AIS_STATE_LOOKING_FOR; |
| fgIsTransition = TRUE; |
| } |
| /* 3. Process for pending roaming scan */ |
| else if (aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_CONNECT, TRUE) == TRUE) { |
| eNextState = AIS_STATE_SEARCH; |
| fgIsTransition = TRUE; |
| } else |
| if (aisFsmIsRequestPending |
| (prAdapter, AIS_REQUEST_REMAIN_ON_CHANNEL, TRUE) == TRUE) { |
| eNextState = AIS_STATE_REQ_REMAIN_ON_CHANNEL; |
| fgIsTransition = TRUE; |
| } |
| } |
| |
| break; |
| |
| case AIS_STATE_DISCONNECTING: |
| /* send for deauth frame for disconnection */ |
| authSendDeauthFrame(prAdapter, |
| prAisBssInfo, |
| prAisBssInfo->prStaRecOfAP, |
| (P_SW_RFB_T) NULL, REASON_CODE_DEAUTH_LEAVING_BSS, aisDeauthXmitComplete); |
| cnmTimerStartTimer(prAdapter, &prAisFsmInfo->rDeauthDoneTimer, 100); |
| break; |
| |
| case AIS_STATE_REQ_REMAIN_ON_CHANNEL: |
| /* send message to CNM for acquiring channel */ |
| prMsgChReq = (P_MSG_CH_REQ_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_CH_REQ_T)); |
| if (!prMsgChReq) { |
| ASSERT(0); /* Can't indicate CNM for channel acquiring */ |
| return; |
| } |
| |
| /* zero-ize */ |
| kalMemZero(prMsgChReq, sizeof(MSG_CH_REQ_T)); |
| |
| /* filling */ |
| prMsgChReq->rMsgHdr.eMsgId = MID_MNY_CNM_CH_REQ; |
| prMsgChReq->ucBssIndex = prAdapter->prAisBssInfo->ucBssIndex; |
| prMsgChReq->ucTokenID = ++prAisFsmInfo->ucSeqNumOfChReq; |
| prMsgChReq->eReqType = CH_REQ_TYPE_JOIN; |
| prMsgChReq->u4MaxInterval = prAisFsmInfo->rChReqInfo.u4DurationMs; |
| prMsgChReq->ucPrimaryChannel = prAisFsmInfo->rChReqInfo.ucChannelNum; |
| prMsgChReq->eRfSco = prAisFsmInfo->rChReqInfo.eSco; |
| prMsgChReq->eRfBand = prAisFsmInfo->rChReqInfo.eBand; |
| #if CFG_SUPPORT_DBDC |
| prMsgChReq->eDBDCBand = ENUM_BAND_AUTO; |
| #endif |
| mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgChReq, MSG_SEND_METHOD_BUF); |
| |
| prAisFsmInfo->fgIsChannelRequested = TRUE; |
| |
| break; |
| |
| case AIS_STATE_REMAIN_ON_CHANNEL: |
| SET_NET_ACTIVE(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); |
| |
| /* sync with firmware */ |
| nicActivateNetwork(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); |
| prAisBssInfo->fgIsNetRequestInActive = FALSE; |
| break; |
| |
| default: |
| ASSERT(0); /* Make sure we have handle all STATEs */ |
| break; |
| |
| } |
| } while (fgIsTransition); |
| |
| return; |
| |
| } /* end of aisFsmSteps() */ |
| |
| enum _ENUM_AIS_STATE_T aisFsmStateSearchAction(IN struct _ADAPTER_T *prAdapter, UINT_8 ucPhase) |
| { |
| struct _CONNECTION_SETTINGS_T *prConnSettings; |
| struct _BSS_INFO_T *prAisBssInfo; |
| struct _AIS_FSM_INFO_T *prAisFsmInfo; |
| struct _BSS_DESC_T *prBssDesc; |
| enum _ENUM_AIS_STATE_T eState = AIS_STATE_IDLE; |
| |
| prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); |
| prAisBssInfo = prAdapter->prAisBssInfo; |
| prConnSettings = &(prAdapter->rWifiVar.rConnSettings); |
| |
| #if CFG_SLT_SUPPORT |
| prBssDesc = prAdapter->rWifiVar.rSltInfo.prPseudoBssDesc; |
| #else |
| prBssDesc = scanSearchBssDescByPolicy(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); |
| #endif |
| |
| if (ucPhase == AIS_FSM_STATE_SEARCH_ACTION_PHASE_0) { |
| if (prConnSettings->eOPMode == NET_TYPE_INFRA) { |
| |
| /* issue reconnect request, */ |
| /*and retreat to idle state for scheduling */ |
| aisFsmInsertRequest(prAdapter, AIS_REQUEST_RECONNECT); |
| eState = AIS_STATE_IDLE; |
| } |
| #if CFG_SUPPORT_ADHOC |
| else if ((prConnSettings->eOPMode == NET_TYPE_IBSS) |
| || (prConnSettings->eOPMode == NET_TYPE_AUTO_SWITCH) |
| || (prConnSettings->eOPMode == NET_TYPE_DEDICATED_IBSS)) { |
| prAisBssInfo->eCurrentOPMode = OP_MODE_IBSS; |
| prAisFsmInfo->prTargetBssDesc = NULL; |
| eState = AIS_STATE_IBSS_ALONE; |
| } |
| #endif /* CFG_SUPPORT_ADHOC */ |
| else { |
| ASSERT(0); |
| eState = AIS_STATE_WAIT_FOR_NEXT_SCAN; |
| } |
| } else if (ucPhase == AIS_FSM_STATE_SEARCH_ACTION_PHASE_1) { |
| /* increase connection trial count for infrastructure connection */ |
| if (prConnSettings->eOPMode == NET_TYPE_INFRA) |
| prAisFsmInfo->ucConnTrialCount++; |
| /* 4 <A> Try to SCAN */ |
| if (prAisFsmInfo->fgTryScan) |
| eState = AIS_STATE_LOOKING_FOR; |
| |
| /* 4 <B> We've do SCAN already, now wait in some STATE. */ |
| else { |
| if (prConnSettings->eOPMode == NET_TYPE_INFRA) { |
| |
| /* issue reconnect request, and */ |
| /* retreat to idle state for scheduling */ |
| aisFsmInsertRequest(prAdapter, AIS_REQUEST_RECONNECT); |
| |
| eState = AIS_STATE_IDLE; |
| } |
| #if CFG_SUPPORT_ADHOC |
| else if ((prConnSettings->eOPMode == NET_TYPE_IBSS) |
| || (prConnSettings->eOPMode == NET_TYPE_AUTO_SWITCH) |
| || (prConnSettings->eOPMode == NET_TYPE_DEDICATED_IBSS)) { |
| |
| prAisBssInfo->eCurrentOPMode = OP_MODE_IBSS; |
| prAisFsmInfo->prTargetBssDesc = NULL; |
| |
| eState = AIS_STATE_IBSS_ALONE; |
| } |
| #endif /* CFG_SUPPORT_ADHOC */ |
| else { |
| ASSERT(0); |
| eState = AIS_STATE_WAIT_FOR_NEXT_SCAN; |
| } |
| } |
| } else { |
| #if DBG |
| if (prAisBssInfo->ucReasonOfDisconnect != DISCONNECT_REASON_CODE_REASSOCIATION) |
| ASSERT(UNEQUAL_MAC_ADDR(prBssDesc->aucBSSID, prAisBssInfo->aucBSSID)); |
| #endif /* DBG */ |
| } |
| return eState; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief |
| * |
| * \param[in] |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID aisFsmRunEventScanDone(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) |
| { |
| P_MSG_SCN_SCAN_DONE prScanDoneMsg; |
| P_AIS_FSM_INFO_T prAisFsmInfo; |
| ENUM_AIS_STATE_T eNextState; |
| UINT_8 ucSeqNumOfCompMsg; |
| P_CONNECTION_SETTINGS_T prConnSettings; |
| |
| DEBUGFUNC("aisFsmRunEventScanDone()"); |
| |
| ASSERT(prAdapter); |
| ASSERT(prMsgHdr); |
| DBGLOG(AIS, INFO, "ScanDone\n"); |
| |
| DBGLOG(AIS, LOUD, "EVENT-SCAN DONE: Current Time = %u\n", kalGetTimeTick()); |
| |
| prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); |
| prConnSettings = &(prAdapter->rWifiVar.rConnSettings); |
| |
| prScanDoneMsg = (P_MSG_SCN_SCAN_DONE) prMsgHdr; |
| ASSERT(prScanDoneMsg->ucBssIndex == prAdapter->prAisBssInfo->ucBssIndex); |
| |
| ucSeqNumOfCompMsg = prScanDoneMsg->ucSeqNum; |
| cnmMemFree(prAdapter, prMsgHdr); |
| |
| eNextState = prAisFsmInfo->eCurrentState; |
| |
| if (ucSeqNumOfCompMsg != prAisFsmInfo->ucSeqNumOfScanReq) { |
| DBGLOG(AIS, WARN, "SEQ NO of AIS SCN DONE MSG is not matched.\n"); |
| } else { |
| cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rScanDoneTimer); |
| switch (prAisFsmInfo->eCurrentState) { |
| case AIS_STATE_SCAN: |
| prConnSettings->fgIsScanReqIssued = FALSE; |
| |
| /* reset scan IE buffer */ |
| prAisFsmInfo->u4ScanIELength = 0; |
| |
| kalScanDone(prAdapter->prGlueInfo, KAL_NETWORK_TYPE_AIS_INDEX, WLAN_STATUS_SUCCESS); |
| eNextState = AIS_STATE_IDLE; |
| #if CFG_SUPPORT_AGPS_ASSIST |
| scanReportScanResultToAgps(prAdapter); |
| #endif |
| |
| break; |
| |
| case AIS_STATE_ONLINE_SCAN: |
| prConnSettings->fgIsScanReqIssued = FALSE; |
| |
| /* reset scan IE buffer */ |
| prAisFsmInfo->u4ScanIELength = 0; |
| |
| kalScanDone(prAdapter->prGlueInfo, KAL_NETWORK_TYPE_AIS_INDEX, WLAN_STATUS_SUCCESS); |
| #if CFG_SUPPORT_ROAMING |
| eNextState = aisFsmRoamingScanResultsUpdate(prAdapter); |
| #else |
| eNextState = AIS_STATE_NORMAL_TR; |
| #endif /* CFG_SUPPORT_ROAMING */ |
| #if CFG_SUPPORT_AGPS_ASSIST |
| scanReportScanResultToAgps(prAdapter); |
| #endif |
| |
| break; |
| |
| case AIS_STATE_LOOKING_FOR: |
| #if CFG_SUPPORT_ROAMING |
| eNextState = aisFsmRoamingScanResultsUpdate(prAdapter); |
| #else |
| eNextState = AIS_STATE_SEARCH; |
| #endif /* CFG_SUPPORT_ROAMING */ |
| break; |
| |
| default: |
| break; |
| |
| } |
| } |
| |
| if (eNextState != prAisFsmInfo->eCurrentState) |
| aisFsmSteps(prAdapter, eNextState); |
| } /* end of aisFsmRunEventScanDone() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief |
| * |
| * \param[in] |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID aisFsmRunEventAbort(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) |
| { |
| P_MSG_AIS_ABORT_T prAisAbortMsg; |
| P_AIS_FSM_INFO_T prAisFsmInfo; |
| UINT_8 ucReasonOfDisconnect; |
| BOOLEAN fgDelayIndication; |
| P_CONNECTION_SETTINGS_T prConnSettings; |
| |
| DEBUGFUNC("aisFsmRunEventAbort()"); |
| |
| ASSERT(prAdapter); |
| ASSERT(prMsgHdr); |
| prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); |
| prConnSettings = &(prAdapter->rWifiVar.rConnSettings); |
| |
| /* 4 <1> Extract information of Abort Message and then free memory. */ |
| prAisAbortMsg = (P_MSG_AIS_ABORT_T) prMsgHdr; |
| ucReasonOfDisconnect = prAisAbortMsg->ucReasonOfDisconnect; |
| fgDelayIndication = prAisAbortMsg->fgDelayIndication; |
| |
| cnmMemFree(prAdapter, prMsgHdr); |
| |
| DBGLOG(AIS, STATE, "EVENT-ABORT: Current State %s, ucReasonOfDisconnect:%d\n", |
| apucDebugAisState[prAisFsmInfo->eCurrentState], ucReasonOfDisconnect); |
| |
| /* record join request time */ |
| GET_CURRENT_SYSTIME(&(prAisFsmInfo->rJoinReqTime)); |
| |
| /* 4 <2> clear previous pending connection request and insert new one */ |
| if (ucReasonOfDisconnect == DISCONNECT_REASON_CODE_DEAUTHENTICATED |
| || ucReasonOfDisconnect == DISCONNECT_REASON_CODE_DISASSOCIATED) { |
| prConnSettings->fgIsDisconnectedByNonRequest = TRUE; |
| } else { |
| prConnSettings->fgIsDisconnectedByNonRequest = FALSE; |
| } |
| |
| /* to support user space triggered roaming */ |
| if (ucReasonOfDisconnect == DISCONNECT_REASON_CODE_REASSOCIATION && |
| prAisFsmInfo->eCurrentState != AIS_STATE_DISCONNECTING) { |
| |
| if (prAisFsmInfo->eCurrentState == AIS_STATE_NORMAL_TR && |
| prAisFsmInfo->fgIsInfraChannelFinished == TRUE) { |
| aisFsmSteps(prAdapter, AIS_STATE_SEARCH); |
| } else { |
| aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_SEARCH, TRUE); |
| aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_CONNECT, TRUE); |
| aisFsmInsertRequest(prAdapter, AIS_REQUEST_ROAMING_CONNECT); |
| } |
| return; |
| } |
| |
| aisFsmIsRequestPending(prAdapter, AIS_REQUEST_RECONNECT, TRUE); |
| aisFsmInsertRequest(prAdapter, AIS_REQUEST_RECONNECT); |
| |
| if (prAisFsmInfo->eCurrentState != AIS_STATE_DISCONNECTING) { |
| /* 4 <3> invoke abort handler */ |
| DBGLOG(AIS, STATE, "ucReasonOfDisconnect:%d\n", ucReasonOfDisconnect); |
| aisFsmStateAbort(prAdapter, ucReasonOfDisconnect, fgDelayIndication); |
| } |
| } /* end of aisFsmRunEventAbort() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief This function handles AIS-FSM abort event/command |
| * |
| * \param[in] prAdapter Pointer of ADAPTER_T |
| * ucReasonOfDisconnect Reason for disonnection |
| * fgDelayIndication Option to delay disconnection indication |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID aisFsmStateAbort(IN P_ADAPTER_T prAdapter, UINT_8 ucReasonOfDisconnect, BOOLEAN fgDelayIndication) |
| { |
| P_AIS_FSM_INFO_T prAisFsmInfo; |
| P_BSS_INFO_T prAisBssInfo; |
| P_CONNECTION_SETTINGS_T prConnSettings; |
| BOOLEAN fgIsCheckConnected; |
| |
| ASSERT(prAdapter); |
| |
| prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); |
| prAisBssInfo = prAdapter->prAisBssInfo; |
| prConnSettings = &(prAdapter->rWifiVar.rConnSettings); |
| fgIsCheckConnected = FALSE; |
| |
| DBGLOG(AIS, STATE, "aisFsmStateAbort DiscReason[%d], CurState[%d]\n", |
| ucReasonOfDisconnect, prAisFsmInfo->eCurrentState); |
| |
| /* 4 <1> Save information of Abort Message and then free memory. */ |
| prAisBssInfo->ucReasonOfDisconnect = ucReasonOfDisconnect; |
| |
| /* 4 <2> Abort current job. */ |
| switch (prAisFsmInfo->eCurrentState) { |
| case AIS_STATE_IDLE: |
| case AIS_STATE_SEARCH: |
| case AIS_STATE_JOIN_FAILURE: |
| break; |
| |
| case AIS_STATE_WAIT_FOR_NEXT_SCAN: |
| /* Do cancel timer */ |
| cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rBGScanTimer); |
| |
| /* in case roaming is triggered */ |
| fgIsCheckConnected = TRUE; |
| break; |
| |
| case AIS_STATE_SCAN: |
| /* Do abort SCAN */ |
| aisFsmStateAbort_SCAN(prAdapter); |
| |
| /* queue for later handling */ |
| if (aisFsmIsRequestPending(prAdapter, AIS_REQUEST_SCAN, FALSE) == FALSE) |
| aisFsmInsertRequest(prAdapter, AIS_REQUEST_SCAN); |
| |
| break; |
| |
| case AIS_STATE_LOOKING_FOR: |
| /* Do abort SCAN */ |
| aisFsmStateAbort_SCAN(prAdapter); |
| |
| /* in case roaming is triggered */ |
| fgIsCheckConnected = TRUE; |
| break; |
| |
| case AIS_STATE_REQ_CHANNEL_JOIN: |
| /* Release channel to CNM */ |
| aisFsmReleaseCh(prAdapter); |
| |
| /* in case roaming is triggered */ |
| fgIsCheckConnected = TRUE; |
| break; |
| |
| case AIS_STATE_JOIN: |
| /* Do abort JOIN */ |
| aisFsmStateAbort_JOIN(prAdapter); |
| |
| /* in case roaming is triggered */ |
| fgIsCheckConnected = TRUE; |
| break; |
| |
| #if CFG_SUPPORT_ADHOC |
| case AIS_STATE_IBSS_ALONE: |
| case AIS_STATE_IBSS_MERGE: |
| aisFsmStateAbort_IBSS(prAdapter); |
| break; |
| #endif /* CFG_SUPPORT_ADHOC */ |
| |
| case AIS_STATE_ONLINE_SCAN: |
| /* Do abort SCAN */ |
| aisFsmStateAbort_SCAN(prAdapter); |
| |
| /* queue for later handling */ |
| if (aisFsmIsRequestPending(prAdapter, AIS_REQUEST_SCAN, FALSE) == FALSE) |
| aisFsmInsertRequest(prAdapter, AIS_REQUEST_SCAN); |
| |
| fgIsCheckConnected = TRUE; |
| break; |
| |
| case AIS_STATE_NORMAL_TR: |
| fgIsCheckConnected = TRUE; |
| break; |
| |
| case AIS_STATE_DISCONNECTING: |
| /* Do abort NORMAL_TR */ |
| aisFsmStateAbort_NORMAL_TR(prAdapter); |
| |
| break; |
| |
| case AIS_STATE_REQ_REMAIN_ON_CHANNEL: |
| /* release channel */ |
| aisFsmReleaseCh(prAdapter); |
| break; |
| |
| case AIS_STATE_REMAIN_ON_CHANNEL: |
| /* 1. release channel */ |
| aisFsmReleaseCh(prAdapter); |
| |
| /* 2. stop channel timeout timer */ |
| cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rChannelTimeoutTimer); |
| |
| break; |
| |
| default: |
| break; |
| } |
| |
| if (fgIsCheckConnected && (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED)) { |
| |
| /* switch into DISCONNECTING state for sending DEAUTH if necessary */ |
| if (prAisBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE && |
| prAisBssInfo->ucReasonOfDisconnect == DISCONNECT_REASON_CODE_NEW_CONNECTION && |
| prAisBssInfo->prStaRecOfAP && prAisBssInfo->prStaRecOfAP->fgIsInUse) { |
| aisFsmSteps(prAdapter, AIS_STATE_DISCONNECTING); |
| |
| return; |
| } |
| /* Do abort NORMAL_TR */ |
| aisFsmStateAbort_NORMAL_TR(prAdapter); |
| } |
| |
| aisFsmDisconnect(prAdapter, fgDelayIndication); |
| |
| return; |
| |
| } /* end of aisFsmStateAbort() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function will handle the Join Complete Event from SAA FSM for AIS FSM |
| * |
| * @param[in] prMsgHdr Message of Join Complete of SAA FSM. |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID aisFsmRunEventJoinComplete(IN struct _ADAPTER_T *prAdapter, IN struct _MSG_HDR_T *prMsgHdr) |
| { |
| struct _MSG_SAA_FSM_COMP_T *prJoinCompMsg; |
| struct _AIS_FSM_INFO_T *prAisFsmInfo; |
| enum _ENUM_AIS_STATE_T eNextState; |
| struct _SW_RFB_T *prAssocRspSwRfb; |
| |
| DEBUGFUNC("aisFsmRunEventJoinComplete()"); |
| ASSERT(prMsgHdr); |
| |
| prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); |
| prJoinCompMsg = (struct _MSG_SAA_FSM_COMP_T *)prMsgHdr; |
| prAssocRspSwRfb = prJoinCompMsg->prSwRfb; |
| |
| eNextState = prAisFsmInfo->eCurrentState; |
| |
| /* Check State and SEQ NUM */ |
| if (prAisFsmInfo->eCurrentState == AIS_STATE_JOIN) { |
| /* Check SEQ NUM */ |
| if (prJoinCompMsg->ucSeqNum == prAisFsmInfo->ucSeqNumOfReqMsg) |
| eNextState = aisFsmJoinCompleteAction(prAdapter, prMsgHdr); |
| #if DBG |
| else |
| DBGLOG(AIS, WARN, "SEQ NO of AIS JOIN COMP MSG is not matched.\n"); |
| #endif /* DBG */ |
| } |
| if (eNextState != prAisFsmInfo->eCurrentState) |
| aisFsmSteps(prAdapter, eNextState); |
| |
| if (prAssocRspSwRfb) |
| nicRxReturnRFB(prAdapter, prAssocRspSwRfb); |
| |
| cnmMemFree(prAdapter, prMsgHdr); |
| } /* end of aisFsmRunEventJoinComplete() */ |
| |
| enum _ENUM_AIS_STATE_T aisFsmJoinCompleteAction(IN struct _ADAPTER_T *prAdapter, IN struct _MSG_HDR_T *prMsgHdr) |
| { |
| struct _MSG_SAA_FSM_COMP_T *prJoinCompMsg; |
| struct _AIS_FSM_INFO_T *prAisFsmInfo; |
| enum _ENUM_AIS_STATE_T eNextState; |
| struct _STA_RECORD_T *prStaRec; |
| struct _SW_RFB_T *prAssocRspSwRfb; |
| struct _BSS_INFO_T *prAisBssInfo; |
| OS_SYSTIME rCurrentTime; |
| |
| DEBUGFUNC("aisFsmJoinCompleteAction()"); |
| |
| ASSERT(prMsgHdr); |
| |
| GET_CURRENT_SYSTIME(&rCurrentTime); |
| |
| prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); |
| prJoinCompMsg = (struct _MSG_SAA_FSM_COMP_T *)prMsgHdr; |
| prStaRec = prJoinCompMsg->prStaRec; |
| prAssocRspSwRfb = prJoinCompMsg->prSwRfb; |
| prAisBssInfo = prAdapter->prAisBssInfo; |
| eNextState = prAisFsmInfo->eCurrentState; |
| |
| do { |
| /* 4 <1> JOIN was successful */ |
| if (prJoinCompMsg->rJoinStatus == WLAN_STATUS_SUCCESS) { |
| |
| /* 1. Reset retry count */ |
| prAisFsmInfo->ucConnTrialCount = 0; |
| |
| /* Completion of roaming */ |
| if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { |
| |
| #if CFG_SUPPORT_ROAMING |
| /* 2. Deactivate previous BSS */ |
| aisFsmRoamingDisconnectPrevAP(prAdapter, prStaRec); |
| |
| /* 3. Update bss based on roaming staRec */ |
| aisUpdateBssInfoForRoamingAP(prAdapter, prStaRec, prAssocRspSwRfb); |
| #endif /* CFG_SUPPORT_ROAMING */ |
| } else { |
| /* 4 <1.1> Change FW's Media State immediately. */ |
| aisChangeMediaState(prAdapter, PARAM_MEDIA_STATE_CONNECTED); |
| |
| /* 4 <1.2> Deactivate previous AP's STA_RECORD_T in Driver if have. */ |
| if ((prAisBssInfo->prStaRecOfAP) && |
| (prAisBssInfo->prStaRecOfAP != prStaRec) && |
| (prAisBssInfo->prStaRecOfAP->fgIsInUse)) { |
| |
| cnmStaRecChangeState(prAdapter, prAisBssInfo->prStaRecOfAP, STA_STATE_1); |
| cnmStaRecFree(prAdapter, prAisBssInfo->prStaRecOfAP); |
| } |
| |
| /* For temp solution, need to refine */ |
| /* 4 <1.4> Update BSS_INFO_T */ |
| aisUpdateBssInfoForJOIN(prAdapter, prStaRec, prAssocRspSwRfb); |
| |
| /* 4 <1.3> Activate current AP's STA_RECORD_T in Driver. */ |
| cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); |
| |
| /* 4 <1.5> Update RSSI if necessary */ |
| nicUpdateRSSI(prAdapter, |
| prAdapter->prAisBssInfo->ucBssIndex, |
| (INT_8) (RCPI_TO_dBm(prStaRec->ucRCPI)), 0); |
| |
| /* 4 <1.6> Indicate Connected Event to Host immediately. */ |
| /* Require BSSID, Association ID, Beacon Interval */ |
| /* .. from AIS_BSS_INFO_T */ |
| aisIndicationOfMediaStateToHost(prAdapter, PARAM_MEDIA_STATE_CONNECTED, FALSE); |
| |
| if (prAdapter->rWifiVar.ucTpTestMode == ENUM_TP_TEST_MODE_THROUGHPUT) |
| nicEnterTPTestMode(prAdapter, TEST_MODE_THROUGHPUT); |
| else if (prAdapter->rWifiVar.ucTpTestMode == ENUM_TP_TEST_MODE_SIGMA_AC_N_PMF) |
| nicEnterTPTestMode(prAdapter, TEST_MODE_SIGMA_AC_N_PMF); |
| else if (prAdapter->rWifiVar.ucTpTestMode == ENUM_TP_TEST_MODE_SIGMA_WMM_PS) |
| nicEnterTPTestMode(prAdapter, TEST_MODE_SIGMA_WMM_PS); |
| } |
| |
| #if CFG_SUPPORT_ROAMING |
| /* if user space roaming is enabled, we should disable driver/fw roaming */ |
| #ifdef CONFIG_CFG80211_ALLOW_RECONNECT |
| if (prAdapter->rWifiVar.rConnSettings.eConnectionPolicy != CONNECT_BY_BSSID) |
| #endif |
| roamingFsmRunEventStart(prAdapter); |
| #endif /* CFG_SUPPORT_ROAMING */ |
| |
| /* 4 <1.7> Set the Next State of AIS FSM */ |
| eNextState = AIS_STATE_NORMAL_TR; |
| } |
| /* 4 <2> JOIN was not successful */ |
| else { |
| /* 4 <2.1> Redo JOIN process with other Auth Type if possible */ |
| if (aisFsmStateInit_RetryJOIN(prAdapter, prStaRec) == FALSE) { |
| struct _BSS_DESC_T *prBssDesc; |
| |
| /* 1. Increase Failure Count */ |
| prStaRec->ucJoinFailureCount++; |
| |
| /* 2. release channel */ |
| aisFsmReleaseCh(prAdapter); |
| |
| /* 3.1 stop join timeout timer */ |
| cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rJoinTimeoutTimer); |
| |
| /* 3.2 reset local variable */ |
| prAisFsmInfo->fgIsInfraChannelFinished = TRUE; |
| |
| prBssDesc = scanSearchBssDescByBssid(prAdapter, prStaRec->aucMacAddr); |
| |
| if (prBssDesc == NULL) |
| break; |
| |
| /* ASSERT(prBssDesc); */ |
| /* ASSERT(prBssDesc->fgIsConnecting); */ |
| prBssDesc->ucJoinFailureCount++; |
| if (prBssDesc->ucJoinFailureCount > SCN_BSS_JOIN_FAIL_THRESOLD) { |
| GET_CURRENT_SYSTIME(&prBssDesc->rJoinFailTime); |
| DBGLOG(AIS, INFO, |
| "Bss " MACSTR " join fail %d times, temp disable it at time: %u\n", |
| MAC2STR(prBssDesc->aucBSSID), SCN_BSS_JOIN_FAIL_THRESOLD, |
| prBssDesc->rJoinFailTime); |
| } |
| |
| if (prBssDesc) |
| prBssDesc->fgIsConnecting = FALSE; |
| |
| /* 3.3 Free STA-REC */ |
| if (prStaRec != prAisBssInfo->prStaRecOfAP) |
| cnmStaRecFree(prAdapter, prStaRec); |
| |
| if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { |
| #if CFG_SUPPORT_ROAMING |
| eNextState = AIS_STATE_WAIT_FOR_NEXT_SCAN; |
| #endif /* CFG_SUPPORT_ROAMING */ |
| } else |
| if (CHECK_FOR_TIMEOUT |
| (rCurrentTime, prAisFsmInfo->rJoinReqTime, SEC_TO_SYSTIME(AIS_JOIN_TIMEOUT))) { |
| /* 4.a temrminate join operation */ |
| eNextState = AIS_STATE_JOIN_FAILURE; |
| } else { |
| /* 4.b send reconnect request */ |
| aisFsmInsertRequest(prAdapter, AIS_REQUEST_RECONNECT); |
| |
| eNextState = AIS_STATE_IDLE; |
| } |
| } |
| } |
| } while (0); |
| return eNextState; |
| } |
| |
| #if CFG_SUPPORT_ADHOC |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function will handle the Grant Msg of IBSS Create which was sent by |
| * CNM to indicate that channel was changed for creating IBSS. |
| * |
| * @param[in] prAdapter Pointer of ADAPTER_T |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID aisFsmCreateIBSS(IN P_ADAPTER_T prAdapter) |
| { |
| P_AIS_FSM_INFO_T prAisFsmInfo; |
| |
| ASSERT(prAdapter); |
| |
| prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); |
| |
| do { |
| /* Check State */ |
| if (prAisFsmInfo->eCurrentState == AIS_STATE_IBSS_ALONE) |
| aisUpdateBssInfoForCreateIBSS(prAdapter); |
| |
| } while (FALSE); |
| } /* end of aisFsmCreateIBSS() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function will handle the Grant Msg of IBSS Merge which was sent by |
| * CNM to indicate that channel was changed for merging IBSS. |
| * |
| * @param[in] prAdapter Pointer of ADAPTER_T |
| * @param[in] prStaRec Pointer of STA_RECORD_T for merge |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID aisFsmMergeIBSS(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) |
| { |
| P_AIS_FSM_INFO_T prAisFsmInfo; |
| ENUM_AIS_STATE_T eNextState; |
| P_BSS_INFO_T prAisBssInfo; |
| |
| ASSERT(prAdapter); |
| ASSERT(prStaRec); |
| |
| prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); |
| prAisBssInfo = prAdapter->prAisBssInfo; |
| |
| do { |
| |
| eNextState = prAisFsmInfo->eCurrentState; |
| |
| switch (prAisFsmInfo->eCurrentState) { |
| case AIS_STATE_IBSS_MERGE: |
| { |
| P_BSS_DESC_T prBssDesc; |
| |
| /* 4 <1.1> Change FW's Media State immediately. */ |
| aisChangeMediaState(prAdapter, PARAM_MEDIA_STATE_CONNECTED); |
| |
| /* 4 <1.2> Deactivate previous Peers' STA_RECORD_T in Driver if have. */ |
| bssInitializeClientList(prAdapter, prAisBssInfo); |
| |
| /* 4 <1.3> Unmark connection flag of previous BSS_DESC_T. */ |
| prBssDesc = scanSearchBssDescByBssid(prAdapter, prAisBssInfo->aucBSSID); |
| if (prBssDesc != NULL) { |
| prBssDesc->fgIsConnecting = FALSE; |
| prBssDesc->fgIsConnected = FALSE; |
| } |
| /* 4 <1.4> Add Peers' STA_RECORD_T to Client List */ |
| bssAddClient(prAdapter, prAisBssInfo, prStaRec); |
| |
| /* 4 <1.5> Activate current Peer's STA_RECORD_T in Driver. */ |
| cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); |
| prStaRec->fgIsMerging = FALSE; |
| |
| /* 4 <1.6> Update BSS_INFO_T */ |
| aisUpdateBssInfoForMergeIBSS(prAdapter, prStaRec); |
| |
| /* 4 <1.7> Enable other features */ |
| |
| /* 4 <1.8> Indicate Connected Event to Host immediately. */ |
| aisIndicationOfMediaStateToHost(prAdapter, PARAM_MEDIA_STATE_CONNECTED, FALSE); |
| |
| /* 4 <1.9> Set the Next State of AIS FSM */ |
| eNextState = AIS_STATE_NORMAL_TR; |
| |
| /* 4 <1.10> Release channel privilege */ |
| aisFsmReleaseCh(prAdapter); |
| |
| #if CFG_SLT_SUPPORT |
| prAdapter->rWifiVar.rSltInfo.prPseudoStaRec = prStaRec; |
| #endif |
| } |
| break; |
| |
| default: |
| break; |
| } |
| |
| if (eNextState != prAisFsmInfo->eCurrentState) |
| aisFsmSteps(prAdapter, eNextState); |
| |
| } while (FALSE); |
| } /* end of aisFsmMergeIBSS() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function will handle the Notification of existing IBSS was found |
| * from SCN. |
| * |
| * @param[in] prMsgHdr Message of Notification of an IBSS was present. |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID aisFsmRunEventFoundIBSSPeer(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) |
| { |
| P_MSG_AIS_IBSS_PEER_FOUND_T prAisIbssPeerFoundMsg; |
| P_AIS_FSM_INFO_T prAisFsmInfo; |
| ENUM_AIS_STATE_T eNextState; |
| P_STA_RECORD_T prStaRec; |
| P_BSS_INFO_T prAisBssInfo; |
| P_BSS_DESC_T prBssDesc; |
| BOOLEAN fgIsMergeIn; |
| |
| ASSERT(prMsgHdr); |
| |
| prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); |
| prAisBssInfo = prAdapter->prAisBssInfo; |
| |
| prAisIbssPeerFoundMsg = (P_MSG_AIS_IBSS_PEER_FOUND_T) prMsgHdr; |
| |
| ASSERT(prAisIbssPeerFoundMsg->ucBssIndex == prAdapter->prAisBssInfo->ucBssIndex); |
| |
| prStaRec = prAisIbssPeerFoundMsg->prStaRec; |
| ASSERT(prStaRec); |
| |
| fgIsMergeIn = prAisIbssPeerFoundMsg->fgIsMergeIn; |
| |
| cnmMemFree(prAdapter, prMsgHdr); |
| |
| eNextState = prAisFsmInfo->eCurrentState; |
| switch (prAisFsmInfo->eCurrentState) { |
| case AIS_STATE_IBSS_ALONE: |
| { |
| /* 4 <1> An IBSS Peer 'merged in'. */ |
| if (fgIsMergeIn) { |
| |
| /* 4 <1.1> Change FW's Media State immediately. */ |
| aisChangeMediaState(prAdapter, PARAM_MEDIA_STATE_CONNECTED); |
| |
| /* 4 <1.2> Add Peers' STA_RECORD_T to Client List */ |
| bssAddClient(prAdapter, prAisBssInfo, prStaRec); |
| |
| #if CFG_SLT_SUPPORT |
| /* 4 <1.3> Mark connection flag of BSS_DESC_T. */ |
| prBssDesc = scanSearchBssDescByTA(prAdapter, prStaRec->aucMacAddr); |
| |
| if (prBssDesc != NULL) { |
| prBssDesc->fgIsConnecting = FALSE; |
| prBssDesc->fgIsConnected = TRUE; |
| } else { |
| ASSERT(0); /* Should be able to find a BSS_DESC_T here. */ |
| } |
| |
| /* 4 <1.4> Activate current Peer's STA_RECORD_T in Driver. */ |
| prStaRec->fgIsQoS = TRUE; /* TODO(Kevin): TBD */ |
| #else |
| /* 4 <1.3> Mark connection flag of BSS_DESC_T. */ |
| prBssDesc = scanSearchBssDescByBssid(prAdapter, prAisBssInfo->aucBSSID); |
| |
| if (prBssDesc != NULL) { |
| prBssDesc->fgIsConnecting = FALSE; |
| prBssDesc->fgIsConnected = TRUE; |
| } else { |
| ASSERT(0); /* Should be able to find a BSS_DESC_T here. */ |
| } |
| |
| /* 4 <1.4> Activate current Peer's STA_RECORD_T in Driver. */ |
| prStaRec->fgIsQoS = FALSE; /* TODO(Kevin): TBD */ |
| |
| #endif |
| |
| cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); |
| prStaRec->fgIsMerging = FALSE; |
| |
| /* 4 <1.6> sync. to firmware */ |
| nicUpdateBss(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); |
| |
| /* 4 <1.7> Indicate Connected Event to Host immediately. */ |
| aisIndicationOfMediaStateToHost(prAdapter, PARAM_MEDIA_STATE_CONNECTED, FALSE); |
| |
| /* 4 <1.8> indicate PM for connected */ |
| nicPmIndicateBssConnected(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); |
| |
| /* 4 <1.9> Set the Next State of AIS FSM */ |
| eNextState = AIS_STATE_NORMAL_TR; |
| |
| /* 4 <1.10> Release channel privilege */ |
| aisFsmReleaseCh(prAdapter); |
| } |
| /* 4 <2> We need 'merge out' to this IBSS */ |
| else { |
| |
| /* 4 <2.1> Get corresponding BSS_DESC_T */ |
| prBssDesc = scanSearchBssDescByTA(prAdapter, prStaRec->aucMacAddr); |
| |
| prAisFsmInfo->prTargetBssDesc = prBssDesc; |
| |
| /* 4 <2.2> Set the Next State of AIS FSM */ |
| eNextState = AIS_STATE_IBSS_MERGE; |
| } |
| } |
| break; |
| |
| case AIS_STATE_NORMAL_TR: |
| { |
| |
| /* 4 <3> An IBSS Peer 'merged in'. */ |
| if (fgIsMergeIn) { |
| |
| /* 4 <3.1> Add Peers' STA_RECORD_T to Client List */ |
| bssAddClient(prAdapter, prAisBssInfo, prStaRec); |
| |
| #if CFG_SLT_SUPPORT |
| /* 4 <3.2> Activate current Peer's STA_RECORD_T in Driver. */ |
| prStaRec->fgIsQoS = TRUE; /* TODO(Kevin): TBD */ |
| #else |
| /* 4 <3.2> Activate current Peer's STA_RECORD_T in Driver. */ |
| prStaRec->fgIsQoS = FALSE; /* TODO(Kevin): TBD */ |
| #endif |
| |
| cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); |
| prStaRec->fgIsMerging = FALSE; |
| |
| } |
| /* 4 <4> We need 'merge out' to this IBSS */ |
| else { |
| |
| /* 4 <4.1> Get corresponding BSS_DESC_T */ |
| prBssDesc = scanSearchBssDescByTA(prAdapter, prStaRec->aucMacAddr); |
| |
| prAisFsmInfo->prTargetBssDesc = prBssDesc; |
| |
| /* 4 <4.2> Set the Next State of AIS FSM */ |
| eNextState = AIS_STATE_IBSS_MERGE; |
| |
| } |
| } |
| break; |
| |
| default: |
| break; |
| } |
| |
| if (eNextState != prAisFsmInfo->eCurrentState) |
| aisFsmSteps(prAdapter, eNextState); |
| } /* end of aisFsmRunEventFoundIBSSPeer() */ |
| #endif /* CFG_SUPPORT_ADHOC */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function will indicate the Media State to HOST |
| * |
| * @param[in] eConnectionState Current Media State |
| * @param[in] fgDelayIndication Set TRUE for postponing the Disconnect Indication. |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID |
| aisIndicationOfMediaStateToHost(IN P_ADAPTER_T prAdapter, |
| ENUM_PARAM_MEDIA_STATE_T eConnectionState, BOOLEAN fgDelayIndication) |
| { |
| EVENT_CONNECTION_STATUS rEventConnStatus; |
| P_CONNECTION_SETTINGS_T prConnSettings; |
| P_BSS_INFO_T prAisBssInfo; |
| P_AIS_FSM_INFO_T prAisFsmInfo; |
| |
| DEBUGFUNC("aisIndicationOfMediaStateToHost()"); |
| |
| prConnSettings = &(prAdapter->rWifiVar.rConnSettings); |
| prAisBssInfo = prAdapter->prAisBssInfo; |
| prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); |
| |
| DBGLOG(AIS, LOUD, "AIS indicate Media State to Host Current State [%d]\n", prAisBssInfo->eConnectionState); |
| |
| /* NOTE(Kevin): Move following line to aisChangeMediaState() macro per CM's request. */ |
| /* prAisBssInfo->eConnectionState = eConnectionState; */ |
| |
| /* For indicating the Disconnect Event only if current media state is |
| * disconnected and we didn't do indication yet. |
| */ |
| if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_DISCONNECTED) { |
| if (prAisBssInfo->eConnectionStateIndicated == eConnectionState) |
| return; |
| |
| } |
| |
| if (!fgDelayIndication) { |
| /* 4 <0> Cancel Delay Timer */ |
| cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rIndicationOfDisconnectTimer); |
| |
| /* 4 <1> Fill EVENT_CONNECTION_STATUS */ |
| rEventConnStatus.ucMediaStatus = (UINT_8) eConnectionState; |
| |
| if (eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { |
| rEventConnStatus.ucReasonOfDisconnect = DISCONNECT_REASON_CODE_RESERVED; |
| |
| if (prAisBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { |
| rEventConnStatus.ucInfraMode = (UINT_8) NET_TYPE_INFRA; |
| rEventConnStatus.u2AID = prAisBssInfo->u2AssocId; |
| rEventConnStatus.u2ATIMWindow = 0; |
| } else if (prAisBssInfo->eCurrentOPMode == OP_MODE_IBSS) { |
| rEventConnStatus.ucInfraMode = (UINT_8) NET_TYPE_IBSS; |
| rEventConnStatus.u2AID = 0; |
| rEventConnStatus.u2ATIMWindow = prAisBssInfo->u2ATIMWindow; |
| } else { |
| ASSERT(0); |
| } |
| |
| COPY_SSID(rEventConnStatus.aucSsid, |
| rEventConnStatus.ucSsidLen, prConnSettings->aucSSID, prConnSettings->ucSSIDLen); |
| |
| COPY_MAC_ADDR(rEventConnStatus.aucBssid, prAisBssInfo->aucBSSID); |
| |
| rEventConnStatus.u2BeaconPeriod = prAisBssInfo->u2BeaconInterval; |
| rEventConnStatus.u4FreqInKHz = nicChannelNum2Freq(prAisBssInfo->ucPrimaryChannel); |
| |
| switch (prAisBssInfo->ucNonHTBasicPhyType) { |
| case PHY_TYPE_HR_DSSS_INDEX: |
| rEventConnStatus.ucNetworkType = (UINT_8) PARAM_NETWORK_TYPE_DS; |
| break; |
| |
| case PHY_TYPE_ERP_INDEX: |
| rEventConnStatus.ucNetworkType = (UINT_8) PARAM_NETWORK_TYPE_OFDM24; |
| break; |
| |
| case PHY_TYPE_OFDM_INDEX: |
| rEventConnStatus.ucNetworkType = (UINT_8) PARAM_NETWORK_TYPE_OFDM5; |
| break; |
| |
| default: |
| ASSERT(0); |
| rEventConnStatus.ucNetworkType = (UINT_8) PARAM_NETWORK_TYPE_DS; |
| break; |
| } |
| } else { |
| /* Clear the pmkid cache while media disconnect */ |
| secClearPmkid(prAdapter); |
| rEventConnStatus.ucReasonOfDisconnect = prAisBssInfo->ucReasonOfDisconnect; |
| } |
| |
| /* 4 <2> Indication */ |
| nicMediaStateChange(prAdapter, prAdapter->prAisBssInfo->ucBssIndex, &rEventConnStatus); |
| prAisBssInfo->eConnectionStateIndicated = eConnectionState; |
| } else { |
| /* NOTE: Only delay the Indication of Disconnect Event */ |
| ASSERT(eConnectionState == PARAM_MEDIA_STATE_DISCONNECTED); |
| |
| DBGLOG(AIS, INFO, "Postpone the indication of Disconnect for %d seconds\n", |
| prConnSettings->ucDelayTimeOfDisconnectEvent); |
| |
| cnmTimerStartTimer(prAdapter, |
| &prAisFsmInfo->rIndicationOfDisconnectTimer, |
| SEC_TO_MSEC(prConnSettings->ucDelayTimeOfDisconnectEvent)); |
| } |
| } /* end of aisIndicationOfMediaStateToHost() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function will indicate an Event of "Media Disconnect" to HOST |
| * |
| * @param[in] u4Param Unused timer parameter |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID aisPostponedEventOfDisconnTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParamPtr) |
| { |
| P_BSS_INFO_T prAisBssInfo; |
| P_CONNECTION_SETTINGS_T prConnSettings; |
| |
| prAisBssInfo = prAdapter->prAisBssInfo; |
| prConnSettings = &(prAdapter->rWifiVar.rConnSettings); |
| |
| DBGLOG(AIS, EVENT, "aisPostponedEventOfDisconnTimeout\n"); |
| |
| /* 4 <1> Deactivate previous AP's STA_RECORD_T in Driver if have. */ |
| if (prAisBssInfo->prStaRecOfAP) { |
| /* cnmStaRecChangeState(prAdapter, prAisBssInfo->prStaRecOfAP, STA_STATE_1); */ |
| |
| prAisBssInfo->prStaRecOfAP = (P_STA_RECORD_T) NULL; |
| } |
| /* 4 <2> Remove pending connection request */ |
| aisFsmIsRequestPending(prAdapter, AIS_REQUEST_RECONNECT, TRUE); |
| prConnSettings->fgIsDisconnectedByNonRequest = TRUE; |
| prAisBssInfo->u2DeauthReason = REASON_CODE_BEACON_TIMEOUT; |
| /* 4 <3> Indicate Disconnected Event to Host immediately. */ |
| aisIndicationOfMediaStateToHost(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED, FALSE); |
| } /* end of aisPostponedEventOfDisconnTimeout() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function will update the contain of BSS_INFO_T for AIS network once |
| * the association was completed. |
| * |
| * @param[in] prStaRec Pointer to the STA_RECORD_T |
| * @param[in] prAssocRspSwRfb Pointer to SW RFB of ASSOC RESP FRAME. |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID aisUpdateBssInfoForJOIN(IN P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec, P_SW_RFB_T prAssocRspSwRfb) |
| { |
| P_AIS_FSM_INFO_T prAisFsmInfo; |
| P_BSS_INFO_T prAisBssInfo; |
| P_CONNECTION_SETTINGS_T prConnSettings; |
| P_WLAN_ASSOC_RSP_FRAME_T prAssocRspFrame; |
| P_BSS_DESC_T prBssDesc; |
| UINT_16 u2IELength; |
| PUINT_8 pucIE; |
| |
| DEBUGFUNC("aisUpdateBssInfoForJOIN()"); |
| |
| ASSERT(prStaRec); |
| ASSERT(prAssocRspSwRfb); |
| |
| prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); |
| prAisBssInfo = prAdapter->prAisBssInfo; |
| prConnSettings = &(prAdapter->rWifiVar.rConnSettings); |
| prAssocRspFrame = (P_WLAN_ASSOC_RSP_FRAME_T) prAssocRspSwRfb->pvHeader; |
| |
| DBGLOG(AIS, INFO, "Update AIS_BSS_INFO_T and apply settings to MAC\n"); |
| |
| /* 3 <1> Update BSS_INFO_T from AIS_FSM_INFO_T or User Settings */ |
| /* 4 <1.1> Setup Operation Mode */ |
| prAisBssInfo->eCurrentOPMode = OP_MODE_INFRASTRUCTURE; |
| |
| /* 4 <1.2> Setup SSID */ |
| COPY_SSID(prAisBssInfo->aucSSID, prAisBssInfo->ucSSIDLen, prConnSettings->aucSSID, prConnSettings->ucSSIDLen); |
| |
| /* 4 <1.3> Setup Channel, Band */ |
| prAisBssInfo->ucPrimaryChannel = prAisFsmInfo->prTargetBssDesc->ucChannelNum; |
| prAisBssInfo->eBand = prAisFsmInfo->prTargetBssDesc->eBand; |
| |
| /* 3 <2> Update BSS_INFO_T from STA_RECORD_T */ |
| /* 4 <2.1> Save current AP's STA_RECORD_T and current AID */ |
| prAisBssInfo->prStaRecOfAP = prStaRec; |
| prAisBssInfo->u2AssocId = prStaRec->u2AssocId; |
| |
| /* 4 <2.2> Setup Capability */ |
| prAisBssInfo->u2CapInfo = prStaRec->u2CapInfo; /* Use AP's Cap Info as BSS Cap Info */ |
| |
| if (prAisBssInfo->u2CapInfo & CAP_INFO_SHORT_PREAMBLE) |
| prAisBssInfo->fgIsShortPreambleAllowed = TRUE; |
| else |
| prAisBssInfo->fgIsShortPreambleAllowed = FALSE; |
| |
| #if CFG_SUPPORT_TDLS |
| prAisBssInfo->fgTdlsIsProhibited = prStaRec->fgTdlsIsProhibited; |
| prAisBssInfo->fgTdlsIsChSwProhibited = prStaRec->fgTdlsIsChSwProhibited; |
| #endif /* CFG_SUPPORT_TDLS */ |
| |
| /* 4 <2.3> Setup PHY Attributes and Basic Rate Set/Operational Rate Set */ |
| prAisBssInfo->ucPhyTypeSet = prStaRec->ucDesiredPhyTypeSet; |
| |
| prAisBssInfo->ucNonHTBasicPhyType = prStaRec->ucNonHTBasicPhyType; |
| |
| prAisBssInfo->u2OperationalRateSet = prStaRec->u2OperationalRateSet; |
| prAisBssInfo->u2BSSBasicRateSet = prStaRec->u2BSSBasicRateSet; |
| |
| nicTxUpdateBssDefaultRate(prAisBssInfo); |
| |
| /* 3 <3> Update BSS_INFO_T from SW_RFB_T (Association Resp Frame) */ |
| /* 4 <3.1> Setup BSSID */ |
| COPY_MAC_ADDR(prAisBssInfo->aucBSSID, prAssocRspFrame->aucBSSID); |
| |
| u2IELength = (UINT_16) ((prAssocRspSwRfb->u2PacketLen - prAssocRspSwRfb->u2HeaderLen) - |
| (OFFSET_OF(WLAN_ASSOC_RSP_FRAME_T, aucInfoElem[0]) - WLAN_MAC_MGMT_HEADER_LEN)); |
| pucIE = prAssocRspFrame->aucInfoElem; |
| |
| /* 4 <3.2> Parse WMM and setup QBSS flag */ |
| /* Parse WMM related IEs and configure HW CRs accordingly */ |
| mqmProcessAssocRsp(prAdapter, prAssocRspSwRfb, pucIE, u2IELength); |
| |
| prAisBssInfo->fgIsQBSS = prStaRec->fgIsQoS; |
| |
| /* 3 <4> Update BSS_INFO_T from BSS_DESC_T */ |
| prBssDesc = scanSearchBssDescByBssid(prAdapter, prAssocRspFrame->aucBSSID); |
| if (prBssDesc) { |
| prBssDesc->fgIsConnecting = FALSE; |
| prBssDesc->fgIsConnected = TRUE; |
| prBssDesc->ucJoinFailureCount = 0; |
| /* 4 <4.1> Setup MIB for current BSS */ |
| prAisBssInfo->u2BeaconInterval = prBssDesc->u2BeaconInterval; |
| } else { |
| /* should never happen */ |
| ASSERT(0); |
| } |
| |
| /* NOTE: Defer ucDTIMPeriod updating to when beacon is received after connection */ |
| prAisBssInfo->ucDTIMPeriod = 0; |
| prAisBssInfo->u2ATIMWindow = 0; |
| |
| prAisBssInfo->ucBeaconTimeoutCount = AIS_BEACON_TIMEOUT_COUNT_INFRA; |
| #if CFG_SUPPORT_ROAMING_SKIP_ONE_AP |
| prAisBssInfo->ucRoamSkipTimes = ROAMING_ONE_AP_SKIP_TIMES; |
| prAisBssInfo->fgGoodRcpiArea = FALSE; |
| prAisBssInfo->fgPoorRcpiArea = FALSE; |
| #endif |
| |
| /* 4 <4.2> Update HT information and set channel */ |
| /* Record HT related parameters in rStaRec and rBssInfo |
| * Note: it shall be called before nicUpdateBss() |
| */ |
| rlmProcessAssocRsp(prAdapter, prAssocRspSwRfb, pucIE, u2IELength); |
| |
| secPostUpdateAddr(prAdapter, prAdapter->prAisBssInfo); |
| |
| /* 4 <4.3> Sync with firmware for BSS-INFO */ |
| nicUpdateBss(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); |
| |
| /* 4 <4.4> *DEFER OPERATION* nicPmIndicateBssConnected() will be invoked */ |
| /* inside scanProcessBeaconAndProbeResp() after 1st beacon is received */ |
| } /* end of aisUpdateBssInfoForJOIN() */ |
| |
| #if CFG_SUPPORT_ADHOC |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function will create an Ad-Hoc network and start sending Beacon Frames. |
| * |
| * @param (none) |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID aisUpdateBssInfoForCreateIBSS(IN P_ADAPTER_T prAdapter) |
| { |
| P_AIS_FSM_INFO_T prAisFsmInfo; |
| P_BSS_INFO_T prAisBssInfo; |
| P_CONNECTION_SETTINGS_T prConnSettings; |
| |
| prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); |
| prAisBssInfo = prAdapter->prAisBssInfo; |
| prConnSettings = &(prAdapter->rWifiVar.rConnSettings); |
| |
| if (prAisBssInfo->fgIsBeaconActivated) |
| return; |
| |
| /* 3 <1> Update BSS_INFO_T per Network Basis */ |
| /* 4 <1.1> Setup Operation Mode */ |
| prAisBssInfo->eCurrentOPMode = OP_MODE_IBSS; |
| |
| /* 4 <1.2> Setup SSID */ |
| COPY_SSID(prAisBssInfo->aucSSID, prAisBssInfo->ucSSIDLen, prConnSettings->aucSSID, prConnSettings->ucSSIDLen); |
| |
| /* 4 <1.3> Clear current AP's STA_RECORD_T and current AID */ |
| prAisBssInfo->prStaRecOfAP = (P_STA_RECORD_T) NULL; |
| prAisBssInfo->u2AssocId = 0; |
| |
| /* 4 <1.4> Setup Channel, Band and Phy Attributes */ |
| prAisBssInfo->ucPrimaryChannel = prConnSettings->ucAdHocChannelNum; |
| prAisBssInfo->eBand = prConnSettings->eAdHocBand; |
| |
| if (prAisBssInfo->eBand == BAND_2G4) { |
| /* Depend on eBand */ |
| prAisBssInfo->ucPhyTypeSet = prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11BGN; |
| /* Depend on eCurrentOPMode and ucPhyTypeSet */ |
| prAisBssInfo->ucConfigAdHocAPMode = AD_HOC_MODE_MIXED_11BG; |
| } else { |
| /* Depend on eBand */ |
| prAisBssInfo->ucPhyTypeSet = prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11ANAC; |
| /* Depend on eCurrentOPMode and ucPhyTypeSet */ |
| prAisBssInfo->ucConfigAdHocAPMode = AD_HOC_MODE_11A; |
| } |
| |
| /* 4 <1.5> Setup MIB for current BSS */ |
| prAisBssInfo->u2BeaconInterval = prConnSettings->u2BeaconPeriod; |
| prAisBssInfo->ucDTIMPeriod = 0; |
| prAisBssInfo->u2ATIMWindow = prConnSettings->u2AtimWindow; |
| |
| prAisBssInfo->ucBeaconTimeoutCount = AIS_BEACON_TIMEOUT_COUNT_ADHOC; |
| |
| if (prConnSettings->eEncStatus == ENUM_ENCRYPTION1_ENABLED || |
| prConnSettings->eEncStatus == ENUM_ENCRYPTION2_ENABLED || |
| prConnSettings->eEncStatus == ENUM_ENCRYPTION3_ENABLED) { |
| prAisBssInfo->fgIsProtection = TRUE; |
| } else { |
| prAisBssInfo->fgIsProtection = FALSE; |
| } |
| |
| /* 3 <2> Update BSS_INFO_T common part */ |
| ibssInitForAdHoc(prAdapter, prAisBssInfo); |
| /* 4 <2.1> Initialize client list */ |
| bssInitializeClientList(prAdapter, prAisBssInfo); |
| |
| /* 3 <3> Set MAC HW */ |
| /* 4 <3.1> Setup channel and bandwidth */ |
| rlmBssInitForAPandIbss(prAdapter, prAisBssInfo); |
| |
| /* 4 <3.2> use command packets to inform firmware */ |
| nicUpdateBss(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); |
| |
| /* 4 <3.3> enable beaconing */ |
| bssUpdateBeaconContent(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); |
| |
| /* 4 <3.4> Update AdHoc PM parameter */ |
| nicPmIndicateBssCreated(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); |
| |
| /* 3 <4> Set ACTIVE flag. */ |
| prAisBssInfo->fgIsBeaconActivated = TRUE; |
| prAisBssInfo->fgHoldSameBssidForIBSS = TRUE; |
| |
| /* 3 <5> Start IBSS Alone Timer */ |
| cnmTimerStartTimer(prAdapter, &prAisFsmInfo->rIbssAloneTimer, SEC_TO_MSEC(AIS_IBSS_ALONE_TIMEOUT_SEC)); |
| } /* end of aisCreateIBSS() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function will update the contain of BSS_INFO_T for AIS network once |
| * the existing IBSS was found. |
| * |
| * @param[in] prStaRec Pointer to the STA_RECORD_T |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID aisUpdateBssInfoForMergeIBSS(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) |
| { |
| P_AIS_FSM_INFO_T prAisFsmInfo; |
| P_BSS_INFO_T prAisBssInfo; |
| P_CONNECTION_SETTINGS_T prConnSettings; |
| P_BSS_DESC_T prBssDesc; |
| /* UINT_16 u2IELength; */ |
| /* PUINT_8 pucIE; */ |
| |
| ASSERT(prStaRec); |
| |
| prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); |
| prAisBssInfo = prAdapter->prAisBssInfo; |
| prConnSettings = &(prAdapter->rWifiVar.rConnSettings); |
| |
| cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rIbssAloneTimer); |
| |
| if (!prAisBssInfo->fgIsBeaconActivated) { |
| |
| /* 3 <1> Update BSS_INFO_T per Network Basis */ |
| /* 4 <1.1> Setup Operation Mode */ |
| prAisBssInfo->eCurrentOPMode = OP_MODE_IBSS; |
| |
| /* 4 <1.2> Setup SSID */ |
| COPY_SSID(prAisBssInfo->aucSSID, |
| prAisBssInfo->ucSSIDLen, prConnSettings->aucSSID, prConnSettings->ucSSIDLen); |
| |
| /* 4 <1.3> Clear current AP's STA_RECORD_T and current AID */ |
| prAisBssInfo->prStaRecOfAP = (P_STA_RECORD_T) NULL; |
| prAisBssInfo->u2AssocId = 0; |
| } |
| /* 3 <2> Update BSS_INFO_T from STA_RECORD_T */ |
| /* 4 <2.1> Setup Capability */ |
| prAisBssInfo->u2CapInfo = prStaRec->u2CapInfo; /* Use Peer's Cap Info as IBSS Cap Info */ |
| |
| if (prAisBssInfo->u2CapInfo & CAP_INFO_SHORT_PREAMBLE) { |
| prAisBssInfo->fgIsShortPreambleAllowed = TRUE; |
| prAisBssInfo->fgUseShortPreamble = TRUE; |
| } else { |
| prAisBssInfo->fgIsShortPreambleAllowed = FALSE; |
| prAisBssInfo->fgUseShortPreamble = FALSE; |
| } |
| |
| /* 7.3.1.4 For IBSS, the Short Slot Time subfield shall be set to 0. */ |
| prAisBssInfo->fgUseShortSlotTime = FALSE; /* Set to FALSE for AdHoc */ |
| prAisBssInfo->u2CapInfo &= ~CAP_INFO_SHORT_SLOT_TIME; |
| |
| if (prAisBssInfo->u2CapInfo & CAP_INFO_PRIVACY) |
| prAisBssInfo->fgIsProtection = TRUE; |
| else |
| prAisBssInfo->fgIsProtection = FALSE; |
| |
| /* 4 <2.2> Setup PHY Attributes and Basic Rate Set/Operational Rate Set */ |
| prAisBssInfo->ucPhyTypeSet = prStaRec->ucDesiredPhyTypeSet; |
| |
| prAisBssInfo->ucNonHTBasicPhyType = prStaRec->ucNonHTBasicPhyType; |
| |
| prAisBssInfo->u2OperationalRateSet = prStaRec->u2OperationalRateSet; |
| prAisBssInfo->u2BSSBasicRateSet = prStaRec->u2BSSBasicRateSet; |
| |
| rateGetDataRatesFromRateSet(prAisBssInfo->u2OperationalRateSet, |
| prAisBssInfo->u2BSSBasicRateSet, |
| prAisBssInfo->aucAllSupportedRates, &prAisBssInfo->ucAllSupportedRatesLen); |
| |
| /* 3 <3> X Update BSS_INFO_T from SW_RFB_T (Association Resp Frame) */ |
| |
| /* 3 <4> Update BSS_INFO_T from BSS_DESC_T */ |
| prBssDesc = scanSearchBssDescByTA(prAdapter, prStaRec->aucMacAddr); |
| if (prBssDesc) { |
| prBssDesc->fgIsConnecting = FALSE; |
| prBssDesc->fgIsConnected = TRUE; |
| |
| /* 4 <4.1> Setup BSSID */ |
| COPY_MAC_ADDR(prAisBssInfo->aucBSSID, prBssDesc->aucBSSID); |
| |
| /* 4 <4.2> Setup Channel, Band */ |
| prAisBssInfo->ucPrimaryChannel = prBssDesc->ucChannelNum; |
| prAisBssInfo->eBand = prBssDesc->eBand; |
| |
| /* 4 <4.3> Setup MIB for current BSS */ |
| prAisBssInfo->u2BeaconInterval = prBssDesc->u2BeaconInterval; |
| prAisBssInfo->ucDTIMPeriod = 0; |
| prAisBssInfo->u2ATIMWindow = 0; /* TBD(Kevin) */ |
| |
| prAisBssInfo->ucBeaconTimeoutCount = AIS_BEACON_TIMEOUT_COUNT_ADHOC; |
| } else { |
| /* should never happen */ |
| ASSERT(0); |
| } |
| |
| /* 3 <5> Set MAC HW */ |
| /* 4 <5.1> Find Lowest Basic Rate Index for default TX Rate of MMPDU */ |
| nicTxUpdateBssDefaultRate(prAisBssInfo); |
| |
| /* 4 <5.2> Setup channel and bandwidth */ |
| rlmBssInitForAPandIbss(prAdapter, prAisBssInfo); |
| |
| /* 4 <5.3> use command packets to inform firmware */ |
| nicUpdateBss(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); |
| |
| /* 4 <5.4> enable beaconing */ |
| bssUpdateBeaconContent(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); |
| |
| /* 4 <5.5> Update AdHoc PM parameter */ |
| nicPmIndicateBssConnected(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); |
| |
| /* 3 <6> Set ACTIVE flag. */ |
| prAisBssInfo->fgIsBeaconActivated = TRUE; |
| prAisBssInfo->fgHoldSameBssidForIBSS = TRUE; |
| } /* end of aisUpdateBssInfoForMergeIBSS() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function will validate the Rx Probe Request Frame and then return |
| * result to BSS to indicate if need to send the corresponding Probe Response |
| * Frame if the specified conditions were matched. |
| * |
| * @param[in] prAdapter Pointer to the Adapter structure. |
| * @param[in] prSwRfb Pointer to SW RFB data structure. |
| * @param[out] pu4ControlFlags Control flags for replying the Probe Response |
| * |
| * @retval TRUE Reply the Probe Response |
| * @retval FALSE Don't reply the Probe Response |
| */ |
| /*----------------------------------------------------------------------------*/ |
| BOOLEAN aisValidateProbeReq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT PUINT_32 pu4ControlFlags) |
| { |
| P_WLAN_MAC_MGMT_HEADER_T prMgtHdr; |
| P_BSS_INFO_T prBssInfo; |
| P_IE_SSID_T prIeSsid = (P_IE_SSID_T) NULL; |
| PUINT_8 pucIE; |
| UINT_16 u2IELength; |
| UINT_16 u2Offset = 0; |
| BOOLEAN fgReplyProbeResp = FALSE; |
| |
| ASSERT(prSwRfb); |
| ASSERT(pu4ControlFlags); |
| |
| prBssInfo = prAdapter->prAisBssInfo; |
| |
| /* 4 <1> Parse Probe Req IE and Get IE ptr (SSID, Supported Rate IE, ...) */ |
| prMgtHdr = (P_WLAN_MAC_MGMT_HEADER_T) prSwRfb->pvHeader; |
| |
| u2IELength = prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen; |
| pucIE = (PUINT_8) ((ULONG) prSwRfb->pvHeader + prSwRfb->u2HeaderLen); |
| |
| IE_FOR_EACH(pucIE, u2IELength, u2Offset) { |
| if (IE_ID(pucIE) == ELEM_ID_SSID) { |
| if ((!prIeSsid) && (IE_LEN(pucIE) <= ELEM_MAX_LEN_SSID)) |
| prIeSsid = (P_IE_SSID_T) pucIE; |
| |
| break; |
| } |
| } /* end of IE_FOR_EACH */ |
| |
| /* 4 <2> Check network conditions */ |
| |
| if (prBssInfo->eCurrentOPMode == OP_MODE_IBSS) { |
| |
| if ((prIeSsid) && ((prIeSsid->ucLength == BC_SSID_LEN) || /* WILDCARD SSID */ |
| EQUAL_SSID(prBssInfo->aucSSID, prBssInfo->ucSSIDLen, /* CURRENT SSID */ |
| prIeSsid->aucSSID, prIeSsid->ucLength))) { |
| fgReplyProbeResp = TRUE; |
| } |
| } |
| |
| return fgReplyProbeResp; |
| |
| } /* end of aisValidateProbeReq() */ |
| |
| #endif /* CFG_SUPPORT_ADHOC */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function will modify and update necessary information to firmware |
| * for disconnection handling |
| * |
| * @param[in] prAdapter Pointer to the Adapter structure. |
| * |
| * @retval None |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID aisFsmDisconnect(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgDelayIndication) |
| { |
| P_BSS_INFO_T prAisBssInfo; |
| |
| ASSERT(prAdapter); |
| |
| prAisBssInfo = prAdapter->prAisBssInfo; |
| |
| nicPmIndicateBssAbort(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); |
| |
| #if CFG_SUPPORT_ADHOC |
| if (prAisBssInfo->fgIsBeaconActivated) { |
| nicUpdateBeaconIETemplate(prAdapter, |
| IE_UPD_METHOD_DELETE_ALL, prAdapter->prAisBssInfo->ucBssIndex, 0, NULL, 0); |
| |
| prAisBssInfo->fgIsBeaconActivated = FALSE; |
| } |
| #endif |
| |
| rlmBssAborted(prAdapter, prAisBssInfo); |
| |
| /* 4 <3> Unset the fgIsConnected flag of BSS_DESC_T and send Deauth if needed. */ |
| if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { |
| |
| { |
| if (prAdapter->rWifiVar.ucTpTestMode != ENUM_TP_TEST_MODE_NORMAL) |
| nicEnterTPTestMode(prAdapter, TEST_MODE_NONE); |
| |
| #if 0 |
| if (prAdapter->rWifiVar.ucSigmaTestMode) |
| nicEnterTPTestMode(prAdapter, TEST_MODE_NONE); |
| #endif |
| } |
| |
| if (prAisBssInfo->ucReasonOfDisconnect == DISCONNECT_REASON_CODE_RADIO_LOST) { |
| scanRemoveBssDescByBssid(prAdapter, prAisBssInfo->aucBSSID); |
| |
| /* remove from scanning results as well */ |
| wlanClearBssInScanningResult(prAdapter, prAisBssInfo->aucBSSID); |
| |
| /* trials for re-association */ |
| if (fgDelayIndication) { |
| aisFsmIsRequestPending(prAdapter, AIS_REQUEST_RECONNECT, TRUE); |
| aisFsmInsertRequest(prAdapter, AIS_REQUEST_RECONNECT); |
| } |
| } else { |
| scanRemoveConnFlagOfBssDescByBssid(prAdapter, prAisBssInfo->aucBSSID); |
| } |
| |
| if (fgDelayIndication) { |
| if (prAisBssInfo->eCurrentOPMode != OP_MODE_IBSS) |
| prAisBssInfo->fgHoldSameBssidForIBSS = FALSE; |
| } else { |
| prAisBssInfo->fgHoldSameBssidForIBSS = FALSE; |
| } |
| } else { |
| prAisBssInfo->fgHoldSameBssidForIBSS = FALSE; |
| } |
| |
| /* 4 <4> Change Media State immediately. */ |
| if (prAisBssInfo->ucReasonOfDisconnect != DISCONNECT_REASON_CODE_REASSOCIATION) { |
| aisChangeMediaState(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED); |
| |
| /* 4 <4.1> sync. with firmware */ |
| nicUpdateBss(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); |
| } |
| |
| if (!fgDelayIndication) { |
| /* 4 <5> Deactivate previous AP's STA_RECORD_T or all Clients in Driver if have. */ |
| if (prAisBssInfo->prStaRecOfAP) { |
| /* cnmStaRecChangeState(prAdapter, prAisBssInfo->prStaRecOfAP, STA_STATE_1); */ |
| prAisBssInfo->prStaRecOfAP = (P_STA_RECORD_T) NULL; |
| } |
| } |
| #if CFG_SUPPORT_ROAMING |
| roamingFsmRunEventAbort(prAdapter); |
| |
| /* clear pending roaming connection request */ |
| aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_SEARCH, TRUE); |
| aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_CONNECT, TRUE); |
| #endif /* CFG_SUPPORT_ROAMING */ |
| |
| /* 4 <6> Indicate Disconnected Event to Host */ |
| aisIndicationOfMediaStateToHost(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED, fgDelayIndication); |
| |
| |
| /* 4 <7> Trigger AIS FSM */ |
| aisFsmSteps(prAdapter, AIS_STATE_IDLE); |
| } /* end of aisFsmDisconnect() */ |
| |
| static VOID aisFsmRunEventScanDoneTimeOut(IN P_ADAPTER_T prAdapter, ULONG ulParam) |
| { |
| P_AIS_FSM_INFO_T prAisFsmInfo; |
| ENUM_AIS_STATE_T eNextState; |
| P_CONNECTION_SETTINGS_T prConnSettings; |
| |
| DEBUGFUNC("aisFsmRunEventScanDoneTimeOut()"); |
| |
| ASSERT(prAdapter); |
| |
| prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); |
| prConnSettings = &(prAdapter->rWifiVar.rConnSettings); |
| |
| DBGLOG(AIS, STATE, "aisFsmRunEventScanDoneTimeOut Current[%d]\n", prAisFsmInfo->eCurrentState); |
| |
| /* report all scanned frames to upper layer to avoid scanned frame is timeout */ |
| /* must be put before kalScanDone */ |
| /* scanReportBss2Cfg80211(prAdapter,BSS_TYPE_INFRASTRUCTURE,NULL); */ |
| |
| prConnSettings->fgIsScanReqIssued = FALSE; |
| kalScanDone(prAdapter->prGlueInfo, KAL_NETWORK_TYPE_AIS_INDEX, WLAN_STATUS_SUCCESS); |
| eNextState = prAisFsmInfo->eCurrentState; |
| |
| switch (prAisFsmInfo->eCurrentState) { |
| case AIS_STATE_SCAN: |
| prAisFsmInfo->u4ScanIELength = 0; |
| eNextState = AIS_STATE_IDLE; |
| break; |
| case AIS_STATE_ONLINE_SCAN: |
| /* reset scan IE buffer */ |
| prAisFsmInfo->u4ScanIELength = 0; |
| #if CFG_SUPPORT_ROAMING |
| eNextState = aisFsmRoamingScanResultsUpdate(prAdapter); |
| #else |
| eNextState = AIS_STATE_NORMAL_TR; |
| #endif /* CFG_SUPPORT_ROAMING */ |
| break; |
| default: |
| break; |
| } |
| |
| /* try to stop scan in CONNSYS */ |
| aisFsmStateAbort_SCAN(prAdapter); |
| |
| /* wlanQueryDebugCode(prAdapter); *//* display current SCAN FSM in FW, debug use */ |
| |
| if (eNextState != prAisFsmInfo->eCurrentState) |
| aisFsmSteps(prAdapter, eNextState); |
| } /* end of aisFsmBGSleepTimeout() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function will indicate an Event of "Background Scan Time-Out" to AIS FSM. |
| * |
| * @param[in] u4Param Unused timer parameter |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID aisFsmRunEventBGSleepTimeOut(IN P_ADAPTER_T prAdapter, ULONG ulParamPtr) |
| { |
| P_AIS_FSM_INFO_T prAisFsmInfo; |
| ENUM_AIS_STATE_T eNextState; |
| |
| DEBUGFUNC("aisFsmRunEventBGSleepTimeOut()"); |
| |
| prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); |
| |
| eNextState = prAisFsmInfo->eCurrentState; |
| |
| switch (prAisFsmInfo->eCurrentState) { |
| case AIS_STATE_WAIT_FOR_NEXT_SCAN: |
| DBGLOG(AIS, LOUD, "EVENT - SCAN TIMER: Idle End - Current Time = %u\n", kalGetTimeTick()); |
| |
| eNextState = AIS_STATE_LOOKING_FOR; |
| |
| SET_NET_PWR_STATE_ACTIVE(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); |
| |
| break; |
| |
| default: |
| break; |
| } |
| |
| /* Call aisFsmSteps() when we are going to change AIS STATE */ |
| if (eNextState != prAisFsmInfo->eCurrentState) |
| aisFsmSteps(prAdapter, eNextState); |
| } /* end of aisFsmBGSleepTimeout() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function will indicate an Event of "IBSS ALONE Time-Out" to AIS FSM. |
| * |
| * @param[in] u4Param Unused timer parameter |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID aisFsmRunEventIbssAloneTimeOut(IN P_ADAPTER_T prAdapter, ULONG ulParamPtr) |
| { |
| P_AIS_FSM_INFO_T prAisFsmInfo; |
| ENUM_AIS_STATE_T eNextState; |
| |
| DEBUGFUNC("aisFsmRunEventIbssAloneTimeOut()"); |
| |
| prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); |
| eNextState = prAisFsmInfo->eCurrentState; |
| |
| switch (prAisFsmInfo->eCurrentState) { |
| case AIS_STATE_IBSS_ALONE: |
| |
| /* There is no one participate in our AdHoc during this TIMEOUT Interval |
| * so go back to search for a valid IBSS again. |
| */ |
| |
| DBGLOG(AIS, LOUD, "EVENT-IBSS ALONE TIMER: Start pairing\n"); |
| |
| prAisFsmInfo->fgTryScan = TRUE; |
| |
| /* abort timer */ |
| aisFsmReleaseCh(prAdapter); |
| |
| /* Pull back to SEARCH to find candidate again */ |
| eNextState = AIS_STATE_SEARCH; |
| |
| break; |
| |
| default: |
| break; |
| } |
| |
| /* Call aisFsmSteps() when we are going to change AIS STATE */ |
| if (eNextState != prAisFsmInfo->eCurrentState) |
| aisFsmSteps(prAdapter, eNextState); |
| } /* end of aisIbssAloneTimeOut() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function will indicate an Event of "Join Time-Out" to AIS FSM. |
| * |
| * @param[in] u4Param Unused timer parameter |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID aisFsmRunEventJoinTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParamPtr) |
| { |
| P_BSS_INFO_T prAisBssInfo; |
| P_AIS_FSM_INFO_T prAisFsmInfo; |
| ENUM_AIS_STATE_T eNextState; |
| OS_SYSTIME rCurrentTime; |
| |
| DEBUGFUNC("aisFsmRunEventJoinTimeout()"); |
| |
| prAisBssInfo = prAdapter->prAisBssInfo; |
| prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); |
| |
| eNextState = prAisFsmInfo->eCurrentState; |
| |
| GET_CURRENT_SYSTIME(&rCurrentTime); |
| |
| switch (prAisFsmInfo->eCurrentState) { |
| case AIS_STATE_JOIN: |
| DBGLOG(AIS, LOUD, "EVENT- JOIN TIMEOUT\n"); |
| |
| /* 1. Do abort JOIN */ |
| aisFsmStateAbort_JOIN(prAdapter); |
| |
| /* 2. Increase Join Failure Count */ |
| prAisFsmInfo->prTargetStaRec->ucJoinFailureCount++; |
| |
| if (prAisFsmInfo->prTargetStaRec->ucJoinFailureCount < JOIN_MAX_RETRY_FAILURE_COUNT) { |
| /* 3.1 Retreat to AIS_STATE_SEARCH state for next try */ |
| eNextState = AIS_STATE_SEARCH; |
| } else if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { |
| /* roaming cases */ |
| /* 3.2 Retreat to AIS_STATE_WAIT_FOR_NEXT_SCAN state for next try */ |
| eNextState = AIS_STATE_WAIT_FOR_NEXT_SCAN; |
| } else |
| if (!CHECK_FOR_TIMEOUT |
| (rCurrentTime, prAisFsmInfo->rJoinReqTime, SEC_TO_SYSTIME(AIS_JOIN_TIMEOUT))) { |
| /* 3.3 Retreat to AIS_STATE_WAIT_FOR_NEXT_SCAN state for next try */ |
| eNextState = AIS_STATE_WAIT_FOR_NEXT_SCAN; |
| } else { |
| /* 3.4 Retreat to AIS_STATE_JOIN_FAILURE to terminate join operation */ |
| eNextState = AIS_STATE_JOIN_FAILURE; |
| } |
| |
| break; |
| |
| case AIS_STATE_NORMAL_TR: |
| /* 1. release channel */ |
| aisFsmReleaseCh(prAdapter); |
| prAisFsmInfo->fgIsInfraChannelFinished = TRUE; |
| |
| /* 2. process if there is pending scan */ |
| if (aisFsmIsRequestPending(prAdapter, AIS_REQUEST_SCAN, TRUE) == TRUE) { |
| wlanClearScanningResult(prAdapter); |
| eNextState = AIS_STATE_ONLINE_SCAN; |
| } |
| |
| break; |
| |
| default: |
| /* release channel */ |
| aisFsmReleaseCh(prAdapter); |
| break; |
| |
| } |
| |
| /* Call aisFsmSteps() when we are going to change AIS STATE */ |
| if (eNextState != prAisFsmInfo->eCurrentState) |
| aisFsmSteps(prAdapter, eNextState); |
| } /* end of aisFsmRunEventJoinTimeout() */ |
| |
| VOID aisFsmRunEventDeauthTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParamPtr) |
| { |
| aisDeauthXmitComplete(prAdapter, NULL, TX_RESULT_LIFE_TIMEOUT); |
| } |
| |
| #if CFG_SUPPORT_LAST_SEC_MCS_INFO |
| VOID aisRxMcsCollectionTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParamPtr) |
| { |
| static UINT_8 ucSmapleCnt; |
| UINT_8 ucStaIdx = prAdapter->prAisBssInfo->prStaRecOfAP->ucIndex; |
| |
| if (prAdapter->arStaRec[ucStaIdx].fgIsValid && prAdapter->arStaRec[ucStaIdx].fgIsInUse) { |
| prAdapter->arStaRec[ucStaIdx].au4RxVect0Que[ucSmapleCnt] = prAdapter->arStaRec[ucStaIdx].u4RxVector0; |
| prAdapter->arStaRec[ucStaIdx].au4RxVect1Que[ucSmapleCnt] = prAdapter->arStaRec[ucStaIdx].u4RxVector1; |
| ucSmapleCnt = (ucSmapleCnt + 1) % MCS_INFO_SAMPLE_CNT; |
| } |
| |
| cnmTimerStartTimer(prAdapter, &prAdapter->rRxMcsInfoTimer, 100); |
| } |
| #endif |
| |
| #if defined(CFG_TEST_MGMT_FSM) && (CFG_TEST_MGMT_FSM != 0) |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief |
| * |
| * \param[in] |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID aisTest(VOID) |
| { |
| P_MSG_AIS_ABORT_T prAisAbortMsg; |
| P_CONNECTION_SETTINGS_T prConnSettings; |
| UINT_8 aucSSID[] = "pci-11n"; |
| UINT_8 ucSSIDLen = 7; |
| |
| prConnSettings = &(prAdapter->rWifiVar.rConnSettings); |
| |
| /* Set Connection Request Issued Flag */ |
| prConnSettings->fgIsConnReqIssued = TRUE; |
| prConnSettings->ucSSIDLen = ucSSIDLen; |
| kalMemCopy(prConnSettings->aucSSID, aucSSID, ucSSIDLen); |
| |
| prAisAbortMsg = (P_MSG_AIS_ABORT_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_AIS_ABORT_T)); |
| if (!prAisAbortMsg) { |
| |
| ASSERT(0); /* Can't trigger SCAN FSM */ |
| return; |
| } |
| |
| prAisAbortMsg->rMsgHdr.eMsgId = MID_HEM_AIS_FSM_ABORT; |
| |
| mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prAisAbortMsg, MSG_SEND_METHOD_BUF); |
| |
| wifi_send_msg(INDX_WIFI, MSG_ID_WIFI_IST, 0); |
| } |
| #endif /* CFG_TEST_MGMT_FSM */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief This function is used to handle OID_802_11_BSSID_LIST_SCAN |
| * |
| * \param[in] prAdapter Pointer of ADAPTER_T |
| * \param[in] prSsid Pointer of SSID_T if specified |
| * \param[in] pucIe Pointer to buffer of extra information elements to be attached |
| * \param[in] u4IeLength Length of information elements |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID aisFsmScanRequest(IN P_ADAPTER_T prAdapter, IN P_PARAM_SSID_T prSsid, IN PUINT_8 pucIe, IN UINT_32 u4IeLength) |
| { |
| P_CONNECTION_SETTINGS_T prConnSettings; |
| P_BSS_INFO_T prAisBssInfo; |
| P_AIS_FSM_INFO_T prAisFsmInfo; |
| |
| DEBUGFUNC("aisFsmScanRequest()"); |
| |
| ASSERT(prAdapter); |
| ASSERT(u4IeLength <= MAX_IE_LENGTH); |
| |
| prAisBssInfo = prAdapter->prAisBssInfo; |
| prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); |
| prConnSettings = &(prAdapter->rWifiVar.rConnSettings); |
| |
| if (!prConnSettings->fgIsScanReqIssued) { |
| prConnSettings->fgIsScanReqIssued = TRUE; |
| |
| if (prSsid == NULL) { |
| prAisFsmInfo->ucScanSSIDNum = 0; |
| } else { |
| prAisFsmInfo->ucScanSSIDNum = 1; |
| |
| COPY_SSID(prAisFsmInfo->arScanSSID[0].aucSsid, |
| prAisFsmInfo->arScanSSID[0].u4SsidLen, prSsid->aucSsid, prSsid->u4SsidLen); |
| } |
| |
| if (u4IeLength > 0) { |
| prAisFsmInfo->u4ScanIELength = u4IeLength; |
| kalMemCopy(prAisFsmInfo->aucScanIEBuf, pucIe, u4IeLength); |
| } else { |
| prAisFsmInfo->u4ScanIELength = 0; |
| } |
| |
| if (prAisFsmInfo->eCurrentState == AIS_STATE_NORMAL_TR) { |
| if (prAisBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE |
| && prAisFsmInfo->fgIsInfraChannelFinished == FALSE) { |
| /* 802.1x might not finished yet, pend it for later handling .. */ |
| aisFsmInsertRequest(prAdapter, AIS_REQUEST_SCAN); |
| } else { |
| if (prAisFsmInfo->fgIsChannelGranted == TRUE) { |
| DBGLOG(AIS, WARN, |
| "Scan Request with channel granted for join operation: %d, %d", |
| prAisFsmInfo->fgIsChannelGranted, prAisFsmInfo->fgIsChannelRequested); |
| } |
| |
| /* start online scan */ |
| wlanClearScanningResult(prAdapter); |
| aisFsmSteps(prAdapter, AIS_STATE_ONLINE_SCAN); |
| } |
| } else if (prAisFsmInfo->eCurrentState == AIS_STATE_IDLE) { |
| wlanClearScanningResult(prAdapter); |
| aisFsmSteps(prAdapter, AIS_STATE_SCAN); |
| } else { |
| aisFsmInsertRequest(prAdapter, AIS_REQUEST_SCAN); |
| } |
| } else { |
| DBGLOG(AIS, WARN, "Scan Request dropped. (state: %d)\n", prAisFsmInfo->eCurrentState); |
| } |
| } /* end of aisFsmScanRequest() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief This function is used to handle OID_802_11_BSSID_LIST_SCAN |
| * |
| * \param[in] prAdapter Pointer of ADAPTER_T |
| * \param[in] ucSsidNum Number of SSID |
| * \param[in] prSsid Pointer to the array of SSID_T if specified |
| * \param[in] pucIe Pointer to buffer of extra information elements to be attached |
| * \param[in] u4IeLength Length of information elements |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID |
| aisFsmScanRequestAdv(IN P_ADAPTER_T prAdapter, |
| IN UINT_8 ucSsidNum, IN P_PARAM_SSID_T prSsid, |
| IN UINT_8 ucChannelListNum, IN P_RF_CHANNEL_INFO_T prChnlInfoList, |
| IN PUINT_8 pucIe, IN UINT_32 u4IeLength) |
| { |
| UINT_32 i; |
| P_CONNECTION_SETTINGS_T prConnSettings; |
| P_BSS_INFO_T prAisBssInfo; |
| P_AIS_FSM_INFO_T prAisFsmInfo; |
| |
| DEBUGFUNC("aisFsmScanRequestAdv()"); |
| |
| ASSERT(prAdapter); |
| ASSERT(ucSsidNum <= SCN_SSID_MAX_NUM); |
| ASSERT(u4IeLength <= MAX_IE_LENGTH); |
| |
| prAisBssInfo = prAdapter->prAisBssInfo; |
| prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); |
| prConnSettings = &(prAdapter->rWifiVar.rConnSettings); |
| |
| if (!prConnSettings->fgIsScanReqIssued) { |
| prConnSettings->fgIsScanReqIssued = TRUE; |
| |
| if (ucSsidNum == 0) { |
| prAisFsmInfo->ucScanSSIDNum = 0; |
| } else { |
| prAisFsmInfo->ucScanSSIDNum = ucSsidNum; |
| |
| for (i = 0; i < ucSsidNum; i++) { |
| COPY_SSID(prAisFsmInfo->arScanSSID[i].aucSsid, |
| prAisFsmInfo->arScanSSID[i].u4SsidLen, |
| prSsid[i].aucSsid, prSsid[i].u4SsidLen); |
| } |
| } |
| |
| if (u4IeLength > 0) { |
| prAisFsmInfo->u4ScanIELength = u4IeLength; |
| kalMemCopy(prAisFsmInfo->aucScanIEBuf, pucIe, u4IeLength); |
| } else { |
| prAisFsmInfo->u4ScanIELength = 0; |
| } |
| |
| #if CFG_SCAN_CHANNEL_SPECIFIED |
| if (ucChannelListNum) { |
| prAisFsmInfo->ucScanChannelListNum = ucChannelListNum; |
| kalMemCopy(prAisFsmInfo->arScanChnlInfoList, prChnlInfoList, |
| sizeof(RF_CHANNEL_INFO_T) * prAisFsmInfo->ucScanChannelListNum); |
| } else |
| prAisFsmInfo->ucScanChannelListNum = 0; |
| #endif |
| |
| if (prAisFsmInfo->eCurrentState == AIS_STATE_NORMAL_TR) { |
| if (prAisBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE |
| && prAisFsmInfo->fgIsInfraChannelFinished == FALSE) { |
| /* 802.1x might not finished yet, pend it for later handling .. */ |
| aisFsmInsertRequest(prAdapter, AIS_REQUEST_SCAN); |
| } else { |
| if (prAisFsmInfo->fgIsChannelGranted == TRUE) { |
| DBGLOG(AIS, WARN, |
| "Scan Request with channel granted for join operation: %d, %d", |
| prAisFsmInfo->fgIsChannelGranted, prAisFsmInfo->fgIsChannelRequested); |
| } |
| |
| /* start online scan */ |
| wlanClearScanningResult(prAdapter); |
| aisFsmSteps(prAdapter, AIS_STATE_ONLINE_SCAN); |
| } |
| } else if (prAisFsmInfo->eCurrentState == AIS_STATE_IDLE) { |
| wlanClearScanningResult(prAdapter); |
| aisFsmSteps(prAdapter, AIS_STATE_SCAN); |
| } else { |
| aisFsmInsertRequest(prAdapter, AIS_REQUEST_SCAN); |
| } |
| } else { |
| DBGLOG(AIS, WARN, "Scan Request dropped. (state: %d)\n", prAisFsmInfo->eCurrentState); |
| } |
| } /* end of aisFsmScanRequestAdv() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief This function is invoked when CNM granted channel privilege |
| * |
| * \param[in] prAdapter Pointer of ADAPTER_T |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID aisFsmRunEventChGrant(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) |
| { |
| P_BSS_INFO_T prAisBssInfo; |
| P_AIS_FSM_INFO_T prAisFsmInfo; |
| P_MSG_CH_GRANT_T prMsgChGrant; |
| UINT_8 ucTokenID; |
| UINT_32 u4GrantInterval; |
| |
| ASSERT(prAdapter); |
| ASSERT(prMsgHdr); |
| |
| prAisBssInfo = prAdapter->prAisBssInfo; |
| prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); |
| prMsgChGrant = (P_MSG_CH_GRANT_T) prMsgHdr; |
| |
| ucTokenID = prMsgChGrant->ucTokenID; |
| u4GrantInterval = prMsgChGrant->u4GrantInterval; |
| #if CFG_SUPPORT_DBDC |
| if (prAisBssInfo->eDBDCBand == ENUM_BAND_AUTO) |
| prAisBssInfo->eDBDCBand = prMsgChGrant->eDBDCBand; |
| #endif |
| |
| #if CFG_SISO_SW_DEVELOP |
| /* Driver record granted CH in BSS info */ |
| prAisBssInfo->fgIsGranted = TRUE; |
| prAisBssInfo->eBandGranted = prMsgChGrant->eRfBand; |
| prAisBssInfo->ucPrimaryChannelGranted = prMsgChGrant->ucPrimaryChannel; |
| #endif |
| |
| /* 1. free message */ |
| cnmMemFree(prAdapter, prMsgHdr); |
| |
| if (prAisFsmInfo->eCurrentState == AIS_STATE_REQ_CHANNEL_JOIN && prAisFsmInfo->ucSeqNumOfChReq == ucTokenID) { |
| /* 2. channel privilege has been approved */ |
| prAisFsmInfo->u4ChGrantedInterval = u4GrantInterval; |
| |
| /* 3. state transition to join/ibss-alone/ibss-merge */ |
| /* 3.1 set timeout timer in cases join could not be completed */ |
| cnmTimerStartTimer(prAdapter, |
| &prAisFsmInfo->rJoinTimeoutTimer, |
| prAisFsmInfo->u4ChGrantedInterval - AIS_JOIN_CH_GRANT_THRESHOLD); |
| /* 3.2 set local variable to indicate join timer is ticking */ |
| prAisFsmInfo->fgIsInfraChannelFinished = FALSE; |
| |
| /* 3.3 switch to join state */ |
| aisFsmSteps(prAdapter, AIS_STATE_JOIN); |
| |
| prAisFsmInfo->fgIsChannelGranted = TRUE; |
| } else if (prAisFsmInfo->eCurrentState == AIS_STATE_REQ_REMAIN_ON_CHANNEL && |
| prAisFsmInfo->ucSeqNumOfChReq == ucTokenID) { |
| /* 2. channel privilege has been approved */ |
| prAisFsmInfo->u4ChGrantedInterval = u4GrantInterval; |
| |
| /* 3.1 set timeout timer in cases upper layer cancel_remain_on_channel never comes */ |
| cnmTimerStartTimer(prAdapter, &prAisFsmInfo->rChannelTimeoutTimer, prAisFsmInfo->u4ChGrantedInterval); |
| |
| /* 3.2 switch to remain_on_channel state */ |
| aisFsmSteps(prAdapter, AIS_STATE_REMAIN_ON_CHANNEL); |
| |
| /* 3.3. indicate upper layer for channel ready */ |
| kalReadyOnChannel(prAdapter->prGlueInfo, |
| prAisFsmInfo->rChReqInfo.u8Cookie, |
| prAisFsmInfo->rChReqInfo.eBand, |
| prAisFsmInfo->rChReqInfo.eSco, |
| prAisFsmInfo->rChReqInfo.ucChannelNum, prAisFsmInfo->rChReqInfo.u4DurationMs); |
| |
| prAisFsmInfo->fgIsChannelGranted = TRUE; |
| } else { /* mismatched grant */ |
| /* 2. return channel privilege to CNM immediately */ |
| aisFsmReleaseCh(prAdapter); |
| } |
| } /* end of aisFsmRunEventChGrant() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief This function is to inform CNM that channel privilege |
| * has been released |
| * |
| * \param[in] prAdapter Pointer of ADAPTER_T |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID aisFsmReleaseCh(IN P_ADAPTER_T prAdapter) |
| { |
| P_AIS_FSM_INFO_T prAisFsmInfo; |
| P_MSG_CH_ABORT_T prMsgChAbort; |
| |
| ASSERT(prAdapter); |
| |
| prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); |
| |
| if (prAisFsmInfo->fgIsChannelGranted == TRUE || prAisFsmInfo->fgIsChannelRequested == TRUE) { |
| |
| prAisFsmInfo->fgIsChannelRequested = FALSE; |
| prAisFsmInfo->fgIsChannelGranted = FALSE; |
| |
| /* 1. return channel privilege to CNM immediately */ |
| prMsgChAbort = (P_MSG_CH_ABORT_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_CH_ABORT_T)); |
| if (!prMsgChAbort) { |
| ASSERT(0); /* Can't release Channel to CNM */ |
| return; |
| } |
| |
| prMsgChAbort->rMsgHdr.eMsgId = MID_MNY_CNM_CH_ABORT; |
| prMsgChAbort->ucBssIndex = prAdapter->prAisBssInfo->ucBssIndex; |
| prMsgChAbort->ucTokenID = prAisFsmInfo->ucSeqNumOfChReq; |
| #if CFG_SUPPORT_DBDC |
| prMsgChAbort->eDBDCBand = ENUM_BAND_AUTO; |
| #endif /*CFG_SUPPORT_DBDC*/ |
| mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgChAbort, MSG_SEND_METHOD_BUF); |
| } |
| } /* end of aisFsmReleaseCh() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief This function is to inform AIS that corresponding beacon has not |
| * been received for a while and probing is not successful |
| * |
| * \param[in] prAdapter Pointer of ADAPTER_T |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID aisBssBeaconTimeout(IN P_ADAPTER_T prAdapter) |
| { |
| P_BSS_INFO_T prAisBssInfo; |
| BOOLEAN fgDoAbortIndication = FALSE; |
| P_CONNECTION_SETTINGS_T prConnSettings; |
| |
| ASSERT(prAdapter); |
| |
| prAisBssInfo = prAdapter->prAisBssInfo; |
| prConnSettings = &(prAdapter->rWifiVar.rConnSettings); |
| |
| /* 4 <1> Diagnose Connection for Beacon Timeout Event */ |
| if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { |
| if (prAisBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { |
| P_STA_RECORD_T prStaRec = prAisBssInfo->prStaRecOfAP; |
| |
| if (prStaRec) |
| fgDoAbortIndication = TRUE; |
| |
| } else if (prAisBssInfo->eCurrentOPMode == OP_MODE_IBSS) { |
| fgDoAbortIndication = TRUE; |
| } |
| } |
| /* 4 <2> invoke abort handler */ |
| if (fgDoAbortIndication) { |
| prConnSettings->fgIsDisconnectedByNonRequest = FALSE; |
| DBGLOG(AIS, EVENT, "aisBssBeaconTimeout\n"); |
| aisFsmStateAbort(prAdapter, DISCONNECT_REASON_CODE_RADIO_LOST, TRUE); |
| } |
| } /* end of aisBssBeaconTimeout() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief This function is to inform AIS that corresponding beacon has not |
| * been received for a while and probing is not successful |
| * |
| * \param[in] prAdapter Pointer of ADAPTER_T |
| * |
| * \return none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID aisBssLinkDown(IN P_ADAPTER_T prAdapter) |
| { |
| P_BSS_INFO_T prAisBssInfo; |
| BOOLEAN fgDoAbortIndication = FALSE; |
| P_CONNECTION_SETTINGS_T prConnSettings; |
| |
| ASSERT(prAdapter); |
| |
| prAisBssInfo = prAdapter->prAisBssInfo; |
| prConnSettings = &(prAdapter->rWifiVar.rConnSettings); |
| |
| /* 4 <1> Diagnose Connection for Beacon Timeout Event */ |
| if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { |
| if (prAisBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { |
| P_STA_RECORD_T prStaRec = prAisBssInfo->prStaRecOfAP; |
| |
| if (prStaRec) |
| fgDoAbortIndication = TRUE; |
| |
| } else if (prAisBssInfo->eCurrentOPMode == OP_MODE_IBSS) { |
| fgDoAbortIndication = TRUE; |
| } |
| } |
| /* 4 <2> invoke abort handler */ |
| if (fgDoAbortIndication) { |
| prConnSettings->fgIsDisconnectedByNonRequest = TRUE; |
| DBGLOG(AIS, EVENT, "aisBssLinkDown\n"); |
| aisFsmStateAbort(prAdapter, DISCONNECT_REASON_CODE_DISASSOCIATED, FALSE); |
| } |
| |
| /* kalIndicateStatusAndComplete(prAdapter->prGlueInfo, WLAN_STATUS_SCAN_COMPLETE, NULL, 0); */ |
| } /* end of aisBssBeaconTimeout() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * \brief This function is to inform AIS that DEAUTH frame has been |
| * sent and thus state machine could go ahead |
| * |
| * \param[in] prAdapter Pointer of ADAPTER_T |
| * \param[in] prMsduInfo Pointer of MSDU_INFO_T for DEAUTH frame |
| * \param[in] prAdapter Pointer of ADAPTER_T |
| * |
| * \return WLAN_STATUS_SUCCESS |
| */ |
| /*----------------------------------------------------------------------------*/ |
| WLAN_STATUS |
| aisDeauthXmitComplete(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) |
| { |
| P_AIS_FSM_INFO_T prAisFsmInfo; |
| |
| ASSERT(prAdapter); |
| |
| prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); |
| if (rTxDoneStatus == TX_RESULT_SUCCESS) |
| cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rDeauthDoneTimer); |
| |
| if (prAisFsmInfo->eCurrentState == AIS_STATE_DISCONNECTING) { |
| DBGLOG(AIS, EVENT, "aisDeauthXmitComplete\n"); |
| if (rTxDoneStatus != TX_RESULT_DROPPED_IN_DRIVER && rTxDoneStatus != TX_RESULT_QUEUE_CLEARANCE) |
| aisFsmStateAbort(prAdapter, DISCONNECT_REASON_CODE_NEW_CONNECTION, FALSE); |
| } else { |
| DBGLOG(AIS, WARN, "DEAUTH frame transmitted without further handling"); |
| } |
| |
| return WLAN_STATUS_SUCCESS; |
| |
| } /* end of aisDeauthXmitComplete() */ |
| |
| #if CFG_SUPPORT_ROAMING |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function will indicate an Event of "Looking for a candidate due to weak signal" to AIS FSM. |
| * |
| * @param[in] u4ReqScan Requesting Scan or not |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID aisFsmRunEventRoamingDiscovery(IN P_ADAPTER_T prAdapter, UINT_32 u4ReqScan) |
| { |
| P_AIS_FSM_INFO_T prAisFsmInfo; |
| P_CONNECTION_SETTINGS_T prConnSettings; |
| ENUM_AIS_REQUEST_TYPE_T eAisRequest; |
| |
| DBGLOG(AIS, LOUD, "aisFsmRunEventRoamingDiscovery()\n"); |
| |
| prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); |
| prConnSettings = &(prAdapter->rWifiVar.rConnSettings); |
| |
| /* search candidates by best rssi */ |
| prConnSettings->eConnectionPolicy = CONNECT_BY_SSID_BEST_RSSI; |
| |
| /* TODO: Stop roaming event in FW */ |
| #if CFG_SUPPORT_WFD |
| #if CFG_ENABLE_WIFI_DIRECT |
| { |
| /* Check WFD is running */ |
| P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; |
| |
| prWfdCfgSettings = &(prAdapter->rWifiVar.rWfdConfigureSettings); |
| if ((prWfdCfgSettings->ucWfdEnable != 0)) { |
| DBGLOG(ROAMING, INFO, "WFD is running. Stop roaming.\n"); |
| roamingFsmRunEventRoam(prAdapter); |
| roamingFsmRunEventFail(prAdapter, ROAMING_FAIL_REASON_NOCANDIDATE); |
| return; |
| } |
| } |
| #endif |
| #endif |
| |
| /* results are still new */ |
| if (!u4ReqScan) { |
| roamingFsmRunEventRoam(prAdapter); |
| eAisRequest = AIS_REQUEST_ROAMING_CONNECT; |
| } else { |
| if (prAisFsmInfo->eCurrentState == AIS_STATE_ONLINE_SCAN |
| || prAisFsmInfo->eCurrentState == AIS_STATE_LOOKING_FOR) { |
| eAisRequest = AIS_REQUEST_ROAMING_CONNECT; |
| } else { |
| eAisRequest = AIS_REQUEST_ROAMING_SEARCH; |
| } |
| } |
| |
| if (prAisFsmInfo->eCurrentState == AIS_STATE_NORMAL_TR && prAisFsmInfo->fgIsInfraChannelFinished == TRUE) { |
| if (eAisRequest == AIS_REQUEST_ROAMING_SEARCH) |
| aisFsmSteps(prAdapter, AIS_STATE_LOOKING_FOR); |
| else |
| aisFsmSteps(prAdapter, AIS_STATE_SEARCH); |
| } else { |
| aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_SEARCH, TRUE); |
| aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_CONNECT, TRUE); |
| |
| aisFsmInsertRequest(prAdapter, eAisRequest); |
| } |
| } /* end of aisFsmRunEventRoamingDiscovery() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Update the time of ScanDone for roaming and transit to Roam state. |
| * |
| * @param (none) |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| ENUM_AIS_STATE_T aisFsmRoamingScanResultsUpdate(IN P_ADAPTER_T prAdapter) |
| { |
| P_AIS_FSM_INFO_T prAisFsmInfo; |
| P_ROAMING_INFO_T prRoamingFsmInfo; |
| ENUM_AIS_STATE_T eNextState; |
| |
| DBGLOG(AIS, LOUD, "->aisFsmRoamingScanResultsUpdate()\n"); |
| |
| prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); |
| prRoamingFsmInfo = (P_ROAMING_INFO_T) &(prAdapter->rWifiVar.rRoamingInfo); |
| |
| roamingFsmScanResultsUpdate(prAdapter); |
| |
| eNextState = prAisFsmInfo->eCurrentState; |
| if (prRoamingFsmInfo->eCurrentState == ROAMING_STATE_DISCOVERY) { |
| roamingFsmRunEventRoam(prAdapter); |
| eNextState = AIS_STATE_SEARCH; |
| } else if (prAisFsmInfo->eCurrentState == AIS_STATE_LOOKING_FOR) { |
| eNextState = AIS_STATE_SEARCH; |
| } else if (prAisFsmInfo->eCurrentState == AIS_STATE_ONLINE_SCAN) { |
| eNextState = AIS_STATE_NORMAL_TR; |
| } |
| |
| return eNextState; |
| } /* end of aisFsmRoamingScanResultsUpdate() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function will modify and update necessary information to firmware |
| * for disconnection of last AP before switching to roaming bss. |
| * |
| * @param IN prAdapter Pointer to the Adapter structure. |
| * prTargetStaRec Target of StaRec of roaming |
| * |
| * @retval None |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID aisFsmRoamingDisconnectPrevAP(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prTargetStaRec) |
| { |
| P_BSS_INFO_T prAisBssInfo; |
| |
| DBGLOG(AIS, EVENT, "aisFsmRoamingDisconnectPrevAP()"); |
| |
| ASSERT(prAdapter); |
| |
| prAisBssInfo = prAdapter->prAisBssInfo; |
| |
| nicPmIndicateBssAbort(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); |
| |
| /* Not invoke rlmBssAborted() here to avoid prAisBssInfo->fg40mBwAllowed |
| * to be reset. RLM related parameters will be reset again when handling |
| * association response in rlmProcessAssocRsp(). 20110413 |
| */ |
| /* rlmBssAborted(prAdapter, prAisBssInfo); */ |
| |
| /* 4 <3> Unset the fgIsConnected flag of BSS_DESC_T and send Deauth if needed. */ |
| if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) |
| scanRemoveConnFlagOfBssDescByBssid(prAdapter, prAisBssInfo->aucBSSID); |
| |
| /* 4 <4> Change Media State immediately. */ |
| aisChangeMediaState(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED); |
| |
| /* 4 <4.1> sync. with firmware */ |
| prTargetStaRec->ucBssIndex = (MAX_BSS_INDEX + 1); /* Virtial BSSID */ |
| nicUpdateBss(prAdapter, prAdapter->prAisBssInfo->ucBssIndex); |
| |
| secRemoveBssBcEntry(prAdapter, prAisBssInfo, TRUE); |
| prTargetStaRec->ucBssIndex = prAdapter->prAisBssInfo->ucBssIndex; |
| } /* end of aisFsmRoamingDisconnectPrevAP() */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function will update the contain of BSS_INFO_T for AIS network once |
| * the roaming was completed. |
| * |
| * @param IN prAdapter Pointer to the Adapter structure. |
| * prStaRec StaRec of roaming AP |
| * prAssocRspSwRfb |
| * |
| * @retval None |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID aisUpdateBssInfoForRoamingAP(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_SW_RFB_T prAssocRspSwRfb) |
| { |
| P_BSS_INFO_T prAisBssInfo; |
| |
| DBGLOG(AIS, LOUD, "aisUpdateBssInfoForRoamingAP()"); |
| |
| ASSERT(prAdapter); |
| |
| prAisBssInfo = prAdapter->prAisBssInfo; |
| |
| /* 4 <1.1> Change FW's Media State immediately. */ |
| aisChangeMediaState(prAdapter, PARAM_MEDIA_STATE_CONNECTED); |
| |
| /* 4 <1.2> Deactivate previous AP's STA_RECORD_T in Driver if have. */ |
| if ((prAisBssInfo->prStaRecOfAP) && |
| (prAisBssInfo->prStaRecOfAP != prStaRec) && (prAisBssInfo->prStaRecOfAP->fgIsInUse)) { |
| /* cnmStaRecChangeState(prAdapter, prAisBssInfo->prStaRecOfAP, STA_STATE_1); */ |
| cnmStaRecFree(prAdapter, prAisBssInfo->prStaRecOfAP); |
| } |
| |
| /* 4 <1.4> Update BSS_INFO_T */ |
| aisUpdateBssInfoForJOIN(prAdapter, prStaRec, prAssocRspSwRfb); |
| |
| /* 4 <1.3> Activate current AP's STA_RECORD_T in Driver. */ |
| cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); |
| |
| /* 4 <1.6> Indicate Connected Event to Host immediately. */ |
| /* Require BSSID, Association ID, Beacon Interval.. from AIS_BSS_INFO_T */ |
| aisIndicationOfMediaStateToHost(prAdapter, PARAM_MEDIA_STATE_CONNECTED, FALSE); |
| } /* end of aisFsmRoamingUpdateBss() */ |
| |
| #endif /* CFG_SUPPORT_ROAMING */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Check if there is any pending request and remove it (optional) |
| * |
| * @param prAdapter |
| * eReqType |
| * bRemove |
| * |
| * @return TRUE |
| * FALSE |
| */ |
| /*----------------------------------------------------------------------------*/ |
| BOOLEAN aisFsmIsRequestPending(IN P_ADAPTER_T prAdapter, IN ENUM_AIS_REQUEST_TYPE_T eReqType, IN BOOLEAN bRemove) |
| { |
| P_AIS_FSM_INFO_T prAisFsmInfo; |
| P_AIS_REQ_HDR_T prPendingReqHdr, prPendingReqHdrNext; |
| |
| ASSERT(prAdapter); |
| prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); |
| |
| /* traverse through pending request list */ |
| LINK_FOR_EACH_ENTRY_SAFE(prPendingReqHdr, |
| prPendingReqHdrNext, &(prAisFsmInfo->rPendingReqList), rLinkEntry, AIS_REQ_HDR_T) { |
| /* check for specified type */ |
| if (prPendingReqHdr->eReqType == eReqType) { |
| /* check if need to remove */ |
| if (bRemove == TRUE) { |
| LINK_REMOVE_KNOWN_ENTRY(&(prAisFsmInfo->rPendingReqList), |
| &(prPendingReqHdr->rLinkEntry)); |
| |
| cnmMemFree(prAdapter, prPendingReqHdr); |
| } |
| |
| return TRUE; |
| } |
| } |
| |
| return FALSE; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Get next pending request |
| * |
| * @param prAdapter |
| * |
| * @return P_AIS_REQ_HDR_T |
| */ |
| /*----------------------------------------------------------------------------*/ |
| P_AIS_REQ_HDR_T aisFsmGetNextRequest(IN P_ADAPTER_T prAdapter) |
| { |
| P_AIS_FSM_INFO_T prAisFsmInfo; |
| P_AIS_REQ_HDR_T prPendingReqHdr; |
| |
| ASSERT(prAdapter); |
| prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); |
| |
| LINK_REMOVE_HEAD(&(prAisFsmInfo->rPendingReqList), prPendingReqHdr, P_AIS_REQ_HDR_T); |
| |
| return prPendingReqHdr; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Insert a new request |
| * |
| * @param prAdapter |
| * eReqType |
| * |
| * @return TRUE |
| * FALSE |
| */ |
| /*----------------------------------------------------------------------------*/ |
| BOOLEAN aisFsmInsertRequest(IN P_ADAPTER_T prAdapter, IN ENUM_AIS_REQUEST_TYPE_T eReqType) |
| { |
| P_AIS_REQ_HDR_T prAisReq; |
| P_AIS_FSM_INFO_T prAisFsmInfo; |
| |
| ASSERT(prAdapter); |
| prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); |
| |
| prAisReq = (P_AIS_REQ_HDR_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(AIS_REQ_HDR_T)); |
| |
| if (!prAisReq) { |
| ASSERT(0); /* Can't generate new message */ |
| return FALSE; |
| } |
| |
| prAisReq->eReqType = eReqType; |
| |
| /* attach request into pending request list */ |
| LINK_INSERT_TAIL(&prAisFsmInfo->rPendingReqList, &prAisReq->rLinkEntry); |
| |
| return TRUE; |
| } |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief Flush all pending requests |
| * |
| * @param prAdapter |
| * |
| * @return (none) |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID aisFsmFlushRequest(IN P_ADAPTER_T prAdapter) |
| { |
| P_AIS_REQ_HDR_T prAisReq; |
| |
| ASSERT(prAdapter); |
| |
| while ((prAisReq = aisFsmGetNextRequest(prAdapter)) != NULL) |
| cnmMemFree(prAdapter, prAisReq); |
| } |
| |
| VOID aisFsmRunEventRemainOnChannel(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) |
| { |
| P_MSG_REMAIN_ON_CHANNEL_T prRemainOnChannel; |
| P_AIS_FSM_INFO_T prAisFsmInfo; |
| P_CONNECTION_SETTINGS_T prConnSettings; |
| |
| DEBUGFUNC("aisFsmRunEventRemainOnChannel()"); |
| |
| ASSERT(prAdapter); |
| ASSERT(prMsgHdr); |
| |
| prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); |
| prConnSettings = &(prAdapter->rWifiVar.rConnSettings); |
| |
| prRemainOnChannel = (P_MSG_REMAIN_ON_CHANNEL_T) prMsgHdr; |
| |
| /* record parameters */ |
| prAisFsmInfo->rChReqInfo.eBand = prRemainOnChannel->eBand; |
| prAisFsmInfo->rChReqInfo.eSco = prRemainOnChannel->eSco; |
| prAisFsmInfo->rChReqInfo.ucChannelNum = prRemainOnChannel->ucChannelNum; |
| prAisFsmInfo->rChReqInfo.u4DurationMs = prRemainOnChannel->u4DurationMs; |
| prAisFsmInfo->rChReqInfo.u8Cookie = prRemainOnChannel->u8Cookie; |
| |
| if (prAisFsmInfo->eCurrentState == AIS_STATE_IDLE || prAisFsmInfo->eCurrentState == AIS_STATE_NORMAL_TR) { |
| /* transit to next state */ |
| aisFsmSteps(prAdapter, AIS_STATE_REQ_REMAIN_ON_CHANNEL); |
| } else { |
| aisFsmInsertRequest(prAdapter, AIS_REQUEST_REMAIN_ON_CHANNEL); |
| } |
| |
| /* free messages */ |
| cnmMemFree(prAdapter, prMsgHdr); |
| } |
| |
| VOID aisFsmRunEventCancelRemainOnChannel(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) |
| { |
| P_AIS_FSM_INFO_T prAisFsmInfo; |
| P_BSS_INFO_T prAisBssInfo; |
| P_MSG_CANCEL_REMAIN_ON_CHANNEL_T prCancelRemainOnChannel; |
| |
| ASSERT(prAdapter); |
| prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); |
| prAisBssInfo = prAdapter->prAisBssInfo; |
| |
| prCancelRemainOnChannel = (P_MSG_CANCEL_REMAIN_ON_CHANNEL_T) prMsgHdr; |
| |
| /* 1. Check the cookie first */ |
| if (prCancelRemainOnChannel->u8Cookie == prAisFsmInfo->rChReqInfo.u8Cookie) { |
| |
| /* 2. release channel privilege/request */ |
| if (prAisFsmInfo->eCurrentState == AIS_STATE_REQ_REMAIN_ON_CHANNEL) { |
| /* 2.1 elease channel */ |
| aisFsmReleaseCh(prAdapter); |
| } else if (prAisFsmInfo->eCurrentState == AIS_STATE_REMAIN_ON_CHANNEL) { |
| /* 2.1 release channel */ |
| aisFsmReleaseCh(prAdapter); |
| |
| /* 2.2 stop channel timeout timer */ |
| cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rChannelTimeoutTimer); |
| } |
| |
| /* 3. clear pending request of remain_on_channel */ |
| aisFsmIsRequestPending(prAdapter, AIS_REQUEST_REMAIN_ON_CHANNEL, TRUE); |
| |
| /* 4. decide which state to retreat */ |
| if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) |
| aisFsmSteps(prAdapter, AIS_STATE_NORMAL_TR); |
| else |
| aisFsmSteps(prAdapter, AIS_STATE_IDLE); |
| |
| } |
| |
| /* 5. free message */ |
| cnmMemFree(prAdapter, prMsgHdr); |
| } |
| |
| VOID aisFsmRunEventMgmtFrameTx(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) |
| { |
| P_AIS_FSM_INFO_T prAisFsmInfo; |
| P_MSG_MGMT_TX_REQUEST_T prMgmtTxMsg = (P_MSG_MGMT_TX_REQUEST_T) NULL; |
| |
| do { |
| ASSERT((prAdapter != NULL) && (prMsgHdr != NULL)); |
| |
| prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); |
| |
| if (prAisFsmInfo == NULL) |
| break; |
| |
| prMgmtTxMsg = (P_MSG_MGMT_TX_REQUEST_T) prMsgHdr; |
| |
| aisFuncTxMgmtFrame(prAdapter, |
| &prAisFsmInfo->rMgmtTxInfo, prMgmtTxMsg->prMgmtMsduInfo, prMgmtTxMsg->u8Cookie); |
| |
| } while (FALSE); |
| |
| if (prMsgHdr) |
| cnmMemFree(prAdapter, prMsgHdr); |
| } /* aisFsmRunEventMgmtFrameTx */ |
| |
| VOID aisFsmRunEventChannelTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParamPtr) |
| { |
| P_AIS_FSM_INFO_T prAisFsmInfo; |
| P_BSS_INFO_T prAisBssInfo; |
| |
| DEBUGFUNC("aisFsmRunEventRemainOnChannel()"); |
| |
| ASSERT(prAdapter); |
| prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); |
| prAisBssInfo = prAdapter->prAisBssInfo; |
| |
| if (prAisFsmInfo->eCurrentState == AIS_STATE_REMAIN_ON_CHANNEL) { |
| /* 1. release channel */ |
| aisFsmReleaseCh(prAdapter); |
| |
| /* 2. stop channel timeout timer */ |
| cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rChannelTimeoutTimer); |
| |
| /* 3. expiration indication to upper layer */ |
| kalRemainOnChannelExpired(prAdapter->prGlueInfo, |
| prAisFsmInfo->rChReqInfo.u8Cookie, |
| prAisFsmInfo->rChReqInfo.eBand, |
| prAisFsmInfo->rChReqInfo.eSco, prAisFsmInfo->rChReqInfo.ucChannelNum); |
| |
| /* 4. decide which state to retreat */ |
| if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) |
| aisFsmSteps(prAdapter, AIS_STATE_NORMAL_TR); |
| else |
| aisFsmSteps(prAdapter, AIS_STATE_IDLE); |
| |
| } else { |
| DBGLOG(AIS, WARN, "Unexpected remain_on_channel timeout event\n"); |
| DBGLOG(AIS, STATE, "CURRENT State: [%s]\n", apucDebugAisState[prAisFsmInfo->eCurrentState]); |
| } |
| } |
| |
| WLAN_STATUS |
| aisFsmRunEventMgmtFrameTxDone(IN P_ADAPTER_T prAdapter, |
| IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) |
| { |
| P_AIS_FSM_INFO_T prAisFsmInfo; |
| P_AIS_MGMT_TX_REQ_INFO_T prMgmtTxReqInfo = (P_AIS_MGMT_TX_REQ_INFO_T) NULL; |
| BOOLEAN fgIsSuccess = FALSE; |
| |
| do { |
| ASSERT((prAdapter != NULL) && (prMsduInfo != NULL)); |
| |
| prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); |
| prMgmtTxReqInfo = &(prAisFsmInfo->rMgmtTxInfo); |
| |
| if (rTxDoneStatus == TX_RESULT_SUCCESS) |
| fgIsSuccess = TRUE; |
| |
| if (prMgmtTxReqInfo->prMgmtTxMsdu == prMsduInfo) { |
| kalIndicateMgmtTxStatus(prAdapter->prGlueInfo, |
| prMgmtTxReqInfo->u8Cookie, |
| fgIsSuccess, prMsduInfo->prPacket, (UINT_32) prMsduInfo->u2FrameLength); |
| |
| prMgmtTxReqInfo->prMgmtTxMsdu = NULL; |
| } |
| |
| } while (FALSE); |
| |
| return WLAN_STATUS_SUCCESS; |
| |
| } /* aisFsmRunEventMgmtFrameTxDone */ |
| |
| WLAN_STATUS |
| aisFuncTxMgmtFrame(IN P_ADAPTER_T prAdapter, |
| IN P_AIS_MGMT_TX_REQ_INFO_T prMgmtTxReqInfo, IN P_MSDU_INFO_T prMgmtTxMsdu, IN UINT_64 u8Cookie) |
| { |
| WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; |
| P_MSDU_INFO_T prTxMsduInfo = (P_MSDU_INFO_T) NULL; |
| P_WLAN_MAC_HEADER_T prWlanHdr = (P_WLAN_MAC_HEADER_T) NULL; |
| P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; |
| |
| do { |
| ASSERT((prAdapter != NULL) && (prMgmtTxReqInfo != NULL)); |
| |
| if (prMgmtTxReqInfo->fgIsMgmtTxRequested) { |
| |
| /* 1. prMgmtTxReqInfo->prMgmtTxMsdu != NULL */ |
| /* Packet on driver, not done yet, drop it. */ |
| prTxMsduInfo = prMgmtTxReqInfo->prMgmtTxMsdu; |
| if (prTxMsduInfo != NULL) { |
| |
| kalIndicateMgmtTxStatus(prAdapter->prGlueInfo, |
| prMgmtTxReqInfo->u8Cookie, |
| FALSE, |
| prTxMsduInfo->prPacket, (UINT_32) prTxMsduInfo->u2FrameLength); |
| |
| /* Leave it to TX Done handler. */ |
| /* cnmMgtPktFree(prAdapter, prTxMsduInfo); */ |
| prMgmtTxReqInfo->prMgmtTxMsdu = NULL; |
| } |
| /* 2. prMgmtTxReqInfo->prMgmtTxMsdu == NULL */ |
| /* Packet transmitted, wait tx done. (cookie issue) */ |
| } |
| |
| ASSERT(prMgmtTxReqInfo->prMgmtTxMsdu == NULL); |
| |
| prWlanHdr = (P_WLAN_MAC_HEADER_T) ((ULONG) prMgmtTxMsdu->prPacket + MAC_TX_RESERVED_FIELD); |
| prStaRec = cnmGetStaRecByAddress(prAdapter, prAdapter->prAisBssInfo->ucBssIndex, prWlanHdr->aucAddr1); |
| |
| TX_SET_MMPDU(prAdapter, |
| prMgmtTxMsdu, |
| (prStaRec != |
| NULL) ? (prStaRec->ucBssIndex) : (prAdapter->prAisBssInfo->ucBssIndex), |
| (prStaRec != NULL) ? (prStaRec->ucIndex) : (STA_REC_INDEX_NOT_FOUND), |
| WLAN_MAC_MGMT_HEADER_LEN, prMgmtTxMsdu->u2FrameLength, |
| aisFsmRunEventMgmtFrameTxDone, MSDU_RATE_MODE_AUTO); |
| prMgmtTxReqInfo->u8Cookie = u8Cookie; |
| prMgmtTxReqInfo->prMgmtTxMsdu = prMgmtTxMsdu; |
| prMgmtTxReqInfo->fgIsMgmtTxRequested = TRUE; |
| |
| nicTxConfigPktControlFlag(prMgmtTxMsdu, MSDU_CONTROL_FLAG_FORCE_TX, TRUE); |
| |
| /* send to TX queue */ |
| nicTxEnqueueMsdu(prAdapter, prMgmtTxMsdu); |
| |
| } while (FALSE); |
| |
| return rWlanStatus; |
| } /* aisFuncTxMgmtFrame */ |
| |
| /*----------------------------------------------------------------------------*/ |
| /*! |
| * @brief This function will validate the Rx Action Frame and indicate to uppoer layer |
| * if the specified conditions were matched. |
| * |
| * @param[in] prAdapter Pointer to the Adapter structure. |
| * @param[in] prSwRfb Pointer to SW RFB data structure. |
| * @param[out] pu4ControlFlags Control flags for replying the Probe Response |
| * |
| * @retval none |
| */ |
| /*----------------------------------------------------------------------------*/ |
| VOID aisFuncValidateRxActionFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) |
| { |
| P_AIS_FSM_INFO_T prAisFsmInfo = (P_AIS_FSM_INFO_T) NULL; |
| |
| DEBUGFUNC("aisFuncValidateRxActionFrame"); |
| |
| do { |
| |
| ASSERT((prAdapter != NULL) && (prSwRfb != NULL)); |
| |
| prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); |
| |
| if (1 /* prAisFsmInfo->u4AisPacketFilter & PARAM_PACKET_FILTER_ACTION_FRAME */) { |
| /* Leave the action frame to wpa_supplicant. */ |
| kalIndicateRxMgmtFrame(prAdapter->prGlueInfo, prSwRfb); |
| } |
| |
| } while (FALSE); |
| |
| return; |
| |
| } /* aisFuncValidateRxActionFrame */ |