blob: 1a475e07e2b08948854aa46cbdb428095998d543 [file] [log] [blame]
/******************************************************************************
*
* 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);
if (!prStaRec) {
DBGLOG(AIS, ERROR, "prStaRec is NULL!\n");
return;
}
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);
if (!prStaRec) {
DBGLOG(AIS, ERROR, "prStaRec is NULL!\n");
return;
}
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)
prAisBssInfo->eBand = prBssDesc->eBand;
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 = 0;
if (prAdapter->prAisBssInfo->prStaRecOfAP == NULL)
goto out;
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;
}
out:
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 */