blob: a9d9b63e02205716ec92dfa57cf8284362b29523 [file] [log] [blame]
/*
* Copyright (c) 2012-2019 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all
* copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/*
* This file was originally distributed by Qualcomm Atheros, Inc.
* under proprietary terms before Copyright ownership was assigned
* to the Linux Foundation.
*/
/** ------------------------------------------------------------------------- *
------------------------------------------------------------------------- *
\file csrApiRoam.c
Implementation for the Common Roaming interfaces.
Copyright (C) 2008 Qualcomm, Incorporated
========================================================================== */
/*===========================================================================
EDIT HISTORY FOR FILE
This section contains comments describing changes made to the module.
Notice that changes are listed in reverse chronological order.
when who what, where, why
---------- --- --------------------------------------------------------
06/03/10 js Added support to hostapd driven
* deauth/disassoc/mic failure
===========================================================================*/
#include "aniGlobal.h" //for tpAniSirGlobal
#include "wlan_qct_wda.h"
#include "halMsgApi.h" //for HAL_STA_INVALID_IDX.
#include "limUtils.h"
#include "palApi.h"
#include "csrInsideApi.h"
#include "smsDebug.h"
#include "sme_Trace.h"
#include "logDump.h"
#include "smeQosInternal.h"
#include "wlan_qct_tl.h"
#include "smeInside.h"
#include "vos_diag_core_event.h"
#include "vos_diag_core_log.h"
#include "csrApi.h"
#include "pmc.h"
#include "vos_nvitem.h"
#include "macTrace.h"
#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
#include "csrNeighborRoam.h"
#endif /* WLAN_FEATURE_NEIGHBOR_ROAMING */
#if defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD)
#include "csrEse.h"
#endif /* FEATURE_WLAN_ESE && !FEATURE_WLAN_ESE_UPLOAD */
#include "vos_utils.h"
#ifdef WLAN_FEATURE_LFR_MBB
#include "csr_roam_mbb.h"
#endif
#define CSR_NUM_IBSS_START_CHANNELS_50 4
#define CSR_NUM_IBSS_START_CHANNELS_24 3
#define CSR_DEF_IBSS_START_CHANNEL_50 36
#define CSR_DEF_IBSS_START_CHANNEL_24 1
/*---------------------------------------------------------------------------
OBIWAN recommends [8 10]% : pick 9%
---------------------------------------------------------------------------*/
#define CSR_VCC_UL_MAC_LOSS_THRESHOLD 9
/*---------------------------------------------------------------------------
OBIWAN recommends -85dBm
---------------------------------------------------------------------------*/
#define CSR_VCC_RSSI_THRESHOLD 80
#define CSR_MIN_GLOBAL_STAT_QUERY_PERIOD 500 //ms
#define CSR_MIN_GLOBAL_STAT_QUERY_PERIOD_IN_BMPS 2000 //ms
#define CSR_MIN_TL_STAT_QUERY_PERIOD 500 //ms
#define CSR_DIAG_LOG_STAT_PERIOD 3000 //ms
//We use constatnt 4 here
//This macro returns true when higher AC parameter is bigger than lower AC for a difference
//The bigger the number, the less chance of TX
//It must put lower AC as the first parameter.
#define SME_DETECT_AC_WEIGHT_DIFF(loAC, hiAC) (v_BOOL_t)(((hiAC) > (loAC)) ? (((hiAC)-(loAC)) > 4) : 0)
//Flag to send/do not send disassoc frame over the air
#define CSR_DONT_SEND_DISASSOC_OVER_THE_AIR 1
#define RSSI_HACK_BMPS (-40)
#define MAX_CB_VALUE_IN_INI (2)
#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
static tANI_BOOLEAN bRoamScanOffloadStarted = VOS_FALSE;
#endif
/*--------------------------------------------------------------------------
Static Type declarations
------------------------------------------------------------------------*/
static tCsrRoamSession csrRoamRoamSession[CSR_ROAM_SESSION_MAX];
/*--------------------------------------------------------------------------
Type declarations
------------------------------------------------------------------------*/
#ifdef WLAN_FEATURE_SAE
/**
* csr_sae_callback - Update SAE info to CSR roam session
* @mac_ctx: MAC context
* @msg_ptr: pointer to SAE message
*
* API to update SAE info to roam csr session
*
* Return: QDF_STATUS
*/
static VOS_STATUS csr_sae_callback(tpAniSirGlobal mac_ctx, tSirSmeRsp *msg_ptr)
{
tCsrRoamInfo roam_info;
uint32_t session_id;
struct sir_sae_info *sae_info;
sae_info = (struct sir_sae_info *) msg_ptr;
if (!sae_info) {
smsLog(mac_ctx, LOGE, "SAE info is NULL");
return VOS_STATUS_E_FAILURE;
}
smsLog(mac_ctx, LOG1, FL("vdev_id %d "MAC_ADDRESS_STR""),
sae_info->vdev_id,
MAC_ADDR_ARRAY(sae_info->peer_mac_addr.bytes));
session_id = sae_info->vdev_id;
if (session_id == CSR_SESSION_ID_INVALID)
return VOS_STATUS_E_FAILURE;
roam_info.sae_info = sae_info;
csrRoamCallCallback(mac_ctx, session_id, &roam_info, 0,
eCSR_ROAM_SAE_COMPUTE, eCSR_ROAM_RESULT_NONE);
return VOS_STATUS_SUCCESS;
}
#else
static inline VOS_STATUS csr_sae_callback(tpAniSirGlobal mac_ctx,
tSirSmeRsp *msg_ptr)
{
return VOS_STATUS_SUCCESS;
}
#endif
#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
int diagAuthTypeFromCSRType(eCsrAuthType authType)
{
int n = AUTH_OPEN;
switch(authType)
{
case eCSR_AUTH_TYPE_SHARED_KEY:
n = AUTH_SHARED;
break;
case eCSR_AUTH_TYPE_WPA:
n = AUTH_WPA_EAP;
break;
case eCSR_AUTH_TYPE_WPA_PSK:
n = AUTH_WPA_PSK;
break;
case eCSR_AUTH_TYPE_RSN:
#ifdef WLAN_FEATURE_11W
case eCSR_AUTH_TYPE_RSN_8021X_SHA256:
#endif
n = AUTH_WPA2_EAP;
break;
case eCSR_AUTH_TYPE_RSN_PSK:
#ifdef WLAN_FEATURE_11W
case eCSR_AUTH_TYPE_RSN_PSK_SHA256:
#endif
n = AUTH_WPA2_PSK;
break;
#ifdef FEATURE_WLAN_WAPI
case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE:
n = AUTH_WAPI_CERT;
break;
case eCSR_AUTH_TYPE_WAPI_WAI_PSK:
n = AUTH_WAPI_PSK;
break;
#endif /* FEATURE_WLAN_WAPI */
default:
break;
}
return (n);
}
int diagEncTypeFromCSRType(eCsrEncryptionType encType)
{
int n = ENC_MODE_OPEN;
switch(encType)
{
case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
case eCSR_ENCRYPT_TYPE_WEP40:
n = ENC_MODE_WEP40;
break;
case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
case eCSR_ENCRYPT_TYPE_WEP104:
n = ENC_MODE_WEP104;
break;
case eCSR_ENCRYPT_TYPE_TKIP:
n = ENC_MODE_TKIP;
break;
case eCSR_ENCRYPT_TYPE_AES:
n = ENC_MODE_AES;
break;
#ifdef FEATURE_WLAN_WAPI
case eCSR_ENCRYPT_TYPE_WPI:
n = ENC_MODE_SMS4;
break;
#endif /* FEATURE_WLAN_WAPI */
default:
break;
}
return (n);
}
#endif //#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
static const tANI_U8 csrStartIbssChannels50[ CSR_NUM_IBSS_START_CHANNELS_50 ] = { 36, 40, 44, 48};
static const tANI_U8 csrStartIbssChannels24[ CSR_NUM_IBSS_START_CHANNELS_24 ] = { 1, 6, 11 };
static void initConfigParam(tpAniSirGlobal pMac);
static tANI_BOOLEAN csrRoamProcessResults( tpAniSirGlobal pMac, tSmeCmd *pCommand,
eCsrRoamCompleteResult Result, void *Context );
static eHalStatus csrRoamStartIbss( tpAniSirGlobal pMac, tANI_U32 sessionId,
tCsrRoamProfile *pProfile,
tANI_BOOLEAN *pfSameIbss );
static void csrRoamUpdateConnectedProfileFromNewBss( tpAniSirGlobal pMac, tANI_U32 sessionId, tSirSmeNewBssInfo *pNewBss );
static void csrRoamPrepareBssParams(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfile *pProfile,
tSirBssDescription *pBssDesc, tBssConfigParam *pBssConfig, tDot11fBeaconIEs *pIes);
static ePhyChanBondState csrGetCBModeFromIes(tpAniSirGlobal pMac, tANI_U8 primaryChn, tDot11fBeaconIEs *pIes);
eHalStatus csrInitGetChannels(tpAniSirGlobal pMac);
static void csrRoamingStateConfigCnfProcessor( tpAniSirGlobal pMac, tANI_U32 result );
eHalStatus csrRoamOpen(tpAniSirGlobal pMac);
eHalStatus csrRoamClose(tpAniSirGlobal pMac);
void csrRoamMICErrorTimerHandler(void *pv);
void csrRoamTKIPCounterMeasureTimerHandler(void *pv);
tANI_BOOLEAN csrRoamIsSameProfileKeys(tpAniSirGlobal pMac, tCsrRoamConnectedProfile *pConnProfile, tCsrRoamProfile *pProfile2);
static eHalStatus csrRoamStartRoamingTimer(tpAniSirGlobal pMac, tANI_U32 sessionId, tANI_U32 interval);
static eHalStatus csrRoamStopRoamingTimer(tpAniSirGlobal pMac, tANI_U32 sessionId);
static void csrRoamRoamingTimerHandler(void *pv);
eHalStatus csrRoamStopWaitForKeyTimer(tpAniSirGlobal pMac);
static void csrRoamWaitForKeyTimeOutHandler(void *pv);
static eHalStatus CsrInit11dInfo(tpAniSirGlobal pMac, tCsr11dinfo *ps11dinfo);
static eHalStatus csrInitChannelPowerList( tpAniSirGlobal pMac, tCsr11dinfo *ps11dinfo);
eHalStatus csrSendMBSetContextReqMsg( tpAniSirGlobal pMac, tANI_U32 sessionId,
tSirMacAddr peerMacAddr, tANI_U8 numKeys, tAniEdType edType,
tANI_BOOLEAN fUnicast, tAniKeyDirection aniKeyDirection,
tANI_U8 keyId, tANI_U8 keyLength, tANI_U8 *pKey, tANI_U8 paeRole,
tANI_U8 *pKeyRsc );
static eHalStatus csrRoamIssueReassociate( tpAniSirGlobal pMac, tANI_U32 sessionId,
tSirBssDescription *pSirBssDesc, tDot11fBeaconIEs *pIes,
tCsrRoamProfile *pProfile );
void csrRoamStatisticsTimerHandler(void *pv);
void csrRoamStatsGlobalClassDTimerHandler(void *pv);
VOS_STATUS csrRoamVccTriggerRssiIndCallback(tHalHandle hHal,
v_U8_t rssiNotification,
void * context);
static void csrRoamLinkDown(tpAniSirGlobal pMac, tANI_U32 sessionId);
void csrRoamVccTrigger(tpAniSirGlobal pMac);
eHalStatus csrSendMBStatsReqMsg( tpAniSirGlobal pMac, tANI_U32 statsMask, tANI_U8 staId);
/*
pStaEntry is no longer invalid upon the return of this function.
*/
static void csrRoamRemoveStatListEntry(tpAniSirGlobal pMac, tListElem *pEntry);
static eCsrCfgDot11Mode csrRoamGetPhyModeBandForBss( tpAniSirGlobal pMac, tCsrRoamProfile *pProfile,tANI_U8 operationChn, eCsrBand *pBand );
static eHalStatus csrRoamGetQosInfoFromBss(tpAniSirGlobal pMac, tSirBssDescription *pBssDesc);
tCsrStatsClientReqInfo * csrRoamInsertEntryIntoList( tpAniSirGlobal pMac,
tDblLinkList *pStaList,
tCsrStatsClientReqInfo *pStaEntry);
void csrRoamStatsClientTimerHandler(void *pv);
tCsrPeStatsReqInfo * csrRoamCheckPeStatsReqList(tpAniSirGlobal pMac, tANI_U32 statsMask,
tANI_U32 periodicity, tANI_BOOLEAN *pFound, tANI_U8 staId);
void csrRoamReportStatistics(tpAniSirGlobal pMac, tANI_U32 statsMask,
tCsrStatsCallback callback, tANI_U8 staId, void *pContext);
void csrRoamSaveStatsFromTl(tpAniSirGlobal pMac, WLANTL_TRANSFER_STA_TYPE *pTlStats);
void csrRoamTlStatsTimerHandler(void *pv);
void csrRoamPeStatsTimerHandler(void *pv);
tListElem * csrRoamCheckClientReqList(tpAniSirGlobal pMac, tANI_U32 statsMask);
void csrRoamRemoveEntryFromPeStatsReqList(tpAniSirGlobal pMac, tCsrPeStatsReqInfo *pPeStaEntry);
tListElem * csrRoamFindInPeStatsReqList(tpAniSirGlobal pMac, tANI_U32 statsMask);
eHalStatus csrRoamDeregStatisticsReq(tpAniSirGlobal pMac);
static tANI_U32 csrFindIbssSession( tpAniSirGlobal pMac );
static eHalStatus csrRoamStartWds( tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfile *pProfile, tSirBssDescription *pBssDesc );
static void csrInitSession( tpAniSirGlobal pMac, tANI_U32 sessionId );
static eHalStatus csrRoamIssueSetKeyCommand( tpAniSirGlobal pMac, tANI_U32 sessionId,
tCsrRoamSetKey *pSetKey, tANI_U32 roamId );
//static eHalStatus csrRoamProcessStopBss( tpAniSirGlobal pMac, tSmeCmd *pCommand );
static eHalStatus csrRoamGetQosInfoFromBss(tpAniSirGlobal pMac, tSirBssDescription *pBssDesc);
void csrRoamReissueRoamCommand(tpAniSirGlobal pMac);
#ifdef FEATURE_WLAN_BTAMP_UT_RF
void csrRoamJoinRetryTimerHandler(void *pv);
#endif
void limInitOperatingClasses( tHalHandle hHal );
extern void SysProcessMmhMsg(tpAniSirGlobal pMac, tSirMsgQ* pMsg);
#ifdef WLAN_BTAMP_FEATURE
extern void btampEstablishLogLinkHdlr(void* pMsg);
#endif
static void csrSerDesUnpackDiassocRsp(tANI_U8 *pBuf, tSirSmeDisassocRsp *pRsp);
void csrReinitPreauthCmd(tpAniSirGlobal pMac, tSmeCmd *pCommand);
//Initialize global variables
static void csrRoamInitGlobals(tpAniSirGlobal pMac)
{
if(pMac)
{
vos_mem_zero(&csrRoamRoamSession, sizeof(csrRoamRoamSession));
pMac->roam.roamSession = csrRoamRoamSession;
}
return;
}
static void csrRoamDeInitGlobals(tpAniSirGlobal pMac)
{
if(pMac)
{
pMac->roam.roamSession = NULL;
}
return;
}
eHalStatus csrOpen(tpAniSirGlobal pMac)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
#ifndef CONFIG_ENABLE_LINUX_REG
static uNvTables nvTables;
VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
v_REGDOMAIN_t regId;
#endif
tANI_U32 i;
do
{
/* Initialize CSR Roam Globals */
csrRoamInitGlobals(pMac);
for( i = 0; i < CSR_ROAM_SESSION_MAX; i++ )
csrRoamStateChange( pMac, eCSR_ROAMING_STATE_STOP, i);
initConfigParam(pMac);
if(!HAL_STATUS_SUCCESS((status = csrScanOpen(pMac))))
break;
if(!HAL_STATUS_SUCCESS((status = csrRoamOpen(pMac))))
break;
pMac->roam.nextRoamId = 1; //Must not be 0
if(!HAL_STATUS_SUCCESS(csrLLOpen(pMac->hHdd, &pMac->roam.statsClientReqList)))
break;
if(!HAL_STATUS_SUCCESS(csrLLOpen(pMac->hHdd, &pMac->roam.peStatsReqList)))
break;
if(!HAL_STATUS_SUCCESS(csrLLOpen(pMac->hHdd, &pMac->roam.roamCmdPendingList)))
break;
#ifndef CONFIG_ENABLE_LINUX_REG
vosStatus = vos_nv_readDefaultCountryTable( &nvTables );
if ( VOS_IS_STATUS_SUCCESS(vosStatus) )
{
vos_mem_copy(pMac->scan.countryCodeDefault, nvTables.defaultCountryTable.countryCode,
WNI_CFG_COUNTRY_CODE_LEN);
status = eHAL_STATUS_SUCCESS;
}
else
{
smsLog( pMac, LOGE, FL(" fail to get NV_FIELD_IMAGE") );
//hardcoded for now
pMac->scan.countryCodeDefault[0] = 'U';
pMac->scan.countryCodeDefault[1] = 'S';
pMac->scan.countryCodeDefault[2] = 'I';
//status = eHAL_STATUS_SUCCESS;
}
smsLog( pMac, LOG1, FL(" country Code from nvRam %.2s"), pMac->scan.countryCodeDefault );
if (!('0' == pMac->scan.countryCodeDefault[0] &&
'0' == pMac->scan.countryCodeDefault[1]))
{
csrGetRegulatoryDomainForCountry(pMac, pMac->scan.countryCodeDefault,
&regId, COUNTRY_NV);
}
else
{
regId = REGDOMAIN_WORLD;
}
WDA_SetRegDomain(pMac, regId, eSIR_TRUE);
pMac->scan.domainIdDefault = regId;
pMac->scan.domainIdCurrent = pMac->scan.domainIdDefault;
vos_mem_copy(pMac->scan.countryCodeCurrent, pMac->scan.countryCodeDefault,
WNI_CFG_COUNTRY_CODE_LEN);
status = csrInitGetChannels( pMac );
#endif
}while(0);
return (status);
}
/* --------------------------------------------------------------------------
\fn csrInitChannels
\brief This function must be called to initialize CSR channel lists
\return eHalStatus
----------------------------------------------------------------------------*/
eHalStatus csrInitChannels(tpAniSirGlobal pMac)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
static uNvTables nvTables;
VOS_STATUS vosStatus = VOS_STATUS_SUCCESS;
v_REGDOMAIN_t regId = REGDOMAIN_WORLD;
vosStatus = vos_nv_readDefaultCountryTable( &nvTables );
if ( VOS_IS_STATUS_SUCCESS(vosStatus) )
{
vos_mem_copy(pMac->scan.countryCodeDefault,
nvTables.defaultCountryTable.countryCode,
WNI_CFG_COUNTRY_CODE_LEN);
}
else
{
smsLog( pMac, LOGE, FL(" fail to get NV_FIELD_IMAGE") );
//hardcoded for now
pMac->scan.countryCodeDefault[0] = 'U';
pMac->scan.countryCodeDefault[1] = 'S';
pMac->scan.countryCodeDefault[2] = 'I';
}
smsLog( pMac, LOG1, FL(" country Code from nvRam %.2s"), pMac->scan.countryCodeDefault );
WDA_SetRegDomain(pMac, regId, eSIR_TRUE);
pMac->scan.domainIdDefault = regId;
pMac->scan.domainIdCurrent = pMac->scan.domainIdDefault;
vos_mem_copy(pMac->scan.countryCodeCurrent, pMac->scan.countryCodeDefault,
WNI_CFG_COUNTRY_CODE_LEN);
vos_mem_copy(pMac->scan.countryCodeElected, pMac->scan.countryCodeDefault,
WNI_CFG_COUNTRY_CODE_LEN);
vos_mem_copy(pMac->scan.countryCode11d, pMac->scan.countryCodeDefault,
WNI_CFG_COUNTRY_CODE_LEN);
status = csrInitGetChannels( pMac );
csrClearVotesForCountryInfo(pMac);
return status;
}
#ifdef CONFIG_ENABLE_LINUX_REG
eHalStatus csrInitChannelsForCC(tpAniSirGlobal pMac, driver_load_type init)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
v_REGDOMAIN_t regId = REGDOMAIN_WORLD;
tANI_U8 cc[WNI_CFG_COUNTRY_CODE_LEN];
/* In case of driver load ; driver need to get channel
* list with default Countrycode.
* In case of SSR; driver need to get channel list
* with old country code. 0 is for init and
* 1 is for reinit
*/
switch (init)
{
case INIT:
vos_mem_copy(cc, pMac->scan.countryCodeDefault,
WNI_CFG_COUNTRY_CODE_LEN);
if (!('0' == cc[0] &&
'0' == cc[1]))
{
csrGetRegulatoryDomainForCountry(pMac, cc,
&regId, COUNTRY_NV);
}
else
{
return status;
}
pMac->scan.domainIdDefault = regId;
break;
case REINIT:
vos_getCurrentCountryCode(&cc[0]);
status = csrGetRegulatoryDomainForCountry(pMac,
cc, &regId, COUNTRY_QUERY);
break;
}
WDA_SetRegDomain(pMac, regId, eSIR_TRUE);
pMac->scan.domainIdCurrent = regId;
vos_mem_copy(pMac->scan.countryCodeCurrent, cc,
WNI_CFG_COUNTRY_CODE_LEN);
status = csrInitGetChannels( pMac );
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
FL("Current Country is %c%c "), pMac->scan.countryCodeCurrent[0],
pMac->scan.countryCodeCurrent[1]);
/* reset info based on new cc, and we are done */
csrResetCountryInformation(pMac, eANI_BOOLEAN_TRUE, eANI_BOOLEAN_TRUE);
csrScanFilterResults(pMac);
return status;
}
#endif
eHalStatus csrSetRegInfo(tHalHandle hHal, tANI_U8 *apCntryCode)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
v_REGDOMAIN_t regId;
v_U8_t cntryCodeLength;
if(NULL == apCntryCode)
{
smsLog( pMac, LOGE, FL(" Invalid country Code Pointer") );
return eHAL_STATUS_FAILURE;
}
smsLog( pMac, LOG1, FL(" country Code %.2s"), apCntryCode );
/* To get correct Regulatory domain from NV table
* 2 character Country code should be used
* 3rd charater is optional for indoor/outdoor setting */
cntryCodeLength = WNI_CFG_COUNTRY_CODE_LEN;
/*
cntryCodeLength = strlen(apCntryCode);
if (cntryCodeLength > WNI_CFG_COUNTRY_CODE_LEN)
{
smsLog( pMac, LOGW, FL(" Invalid Country Code Length") );
return eHAL_STATUS_FAILURE;
}
*/
status = csrGetRegulatoryDomainForCountry(pMac, apCntryCode, &regId,
COUNTRY_USER);
if (status != eHAL_STATUS_SUCCESS)
{
smsLog( pMac, LOGE, FL(" fail to get regId for country Code %.2s"), apCntryCode );
return status;
}
status = WDA_SetRegDomain(hHal, regId, eSIR_TRUE);
if (status != eHAL_STATUS_SUCCESS)
{
smsLog( pMac, LOGE, FL(" fail to get regId for country Code %.2s"), apCntryCode );
return status;
}
pMac->scan.domainIdDefault = regId;
pMac->scan.domainIdCurrent = pMac->scan.domainIdDefault;
/* Clear CC field */
vos_mem_set(pMac->scan.countryCodeDefault, WNI_CFG_COUNTRY_CODE_LEN, 0);
/* Copy 2 or 3 bytes country code */
vos_mem_copy(pMac->scan.countryCodeDefault, apCntryCode, cntryCodeLength);
/* If 2 bytes country code, 3rd byte must be filled with space */
if((WNI_CFG_COUNTRY_CODE_LEN - 1) == cntryCodeLength)
{
vos_mem_set(pMac->scan.countryCodeDefault + 2, 1, 0x20);
}
vos_mem_copy(pMac->scan.countryCodeCurrent, pMac->scan.countryCodeDefault,
WNI_CFG_COUNTRY_CODE_LEN);
status = csrInitGetChannels( pMac );
return status;
}
eHalStatus csrSetChannels(tHalHandle hHal, tCsrConfigParam *pParam )
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
tANI_U8 index = 0;
vos_mem_copy(pParam->Csr11dinfo.countryCode, pMac->scan.countryCodeCurrent,
WNI_CFG_COUNTRY_CODE_LEN);
for ( index = 0; index < pMac->scan.base20MHzChannels.numChannels ; index++)
{
pParam->Csr11dinfo.Channels.channelList[index] = pMac->scan.base20MHzChannels.channelList[ index ];
pParam->Csr11dinfo.ChnPower[index].firstChannel = pMac->scan.base20MHzChannels.channelList[ index ];
pParam->Csr11dinfo.ChnPower[index].numChannels = 1;
pParam->Csr11dinfo.ChnPower[index].maxtxPower = pMac->scan.defaultPowerTable[index].pwr;
}
pParam->Csr11dinfo.Channels.numChannels = pMac->scan.base20MHzChannels.numChannels;
return status;
}
eHalStatus csrClose(tpAniSirGlobal pMac)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
csrRoamClose(pMac);
csrScanClose(pMac);
csrLLClose(&pMac->roam.statsClientReqList);
csrLLClose(&pMac->roam.peStatsReqList);
csrLLClose(&pMac->roam.roamCmdPendingList);
/* DeInit Globals */
csrRoamDeInitGlobals(pMac);
return (status);
}
eHalStatus csrUpdateChannelList(tpAniSirGlobal pMac)
{
tSirUpdateChanList *pChanList;
tCsrScanStruct *pScan = &pMac->scan;
tANI_U32 numChan = 0;
tANI_U32 bufLen ;
tANI_U8 i, j;
tANI_U8 num_channel = 0;
tANI_U8 channel_state;
tANI_U8 cfgnumChannels = 0;
tANI_U8 *cfgChannelList = NULL;
eHalStatus status;
tSmeCmd *command;
limInitOperatingClasses((tHalHandle)pMac);
numChan = sizeof(pMac->roam.validChannelList);
if ( !HAL_STATUS_SUCCESS(csrGetCfgValidChannels(pMac,
(tANI_U8 *)pMac->roam.validChannelList, &numChan)))
{
smsLog( pMac, LOGE, "Failed to get Channel list from CFG");
return eHAL_STATUS_FAILED_ALLOC;
}
bufLen = sizeof(tSirUpdateChanList) +
(sizeof(tSirUpdateChanParam) * (numChan - 1));
pChanList = (tSirUpdateChanList *) vos_mem_malloc(bufLen);
if (!pChanList)
{
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"Failed to allocate memory for tSirUpdateChanList");
return eHAL_STATUS_FAILED_ALLOC;
}
vos_mem_zero(pChanList, bufLen);
smsLog(pMac, LOG1, FL("fEnableDFSChnlScan %d"),
pMac->scan.fEnableDFSChnlScan);
for (i = 0; i < numChan; i++)
{
channel_state =
vos_nv_getChannelEnabledState(pMac->roam.validChannelList[i]);
if((pMac->scan.fEnableDFSChnlScan == DFS_CHNL_SCAN_DISABLED)
&& (channel_state == NV_CHANNEL_DFS))
{
continue;
}
pChanList->chanParam[num_channel].chanId =
pMac->roam.validChannelList[i];
pChanList->chanParam[num_channel].pwr =
cfgGetRegulatoryMaxTransmitPower(pMac,
pScan->defaultPowerTable[i].chanId);
if (!pChanList->chanParam[num_channel].pwr)
{
smsLog(pMac, LOGE, FL("Power level is zero for channel %d "
"setting to default %d"),
pChanList->chanParam[num_channel].chanId,
TX_POWER_DEFAULT);
pChanList->chanParam[num_channel].pwr = TX_POWER_DEFAULT;
}
if (channel_state == NV_CHANNEL_DFS)
pChanList->chanParam[num_channel].dfsSet = VOS_TRUE;
else
pChanList->chanParam[num_channel].dfsSet = VOS_FALSE;
/* When DFS mode is 2, mark static channels as active */
if (pMac->scan.fEnableDFSChnlScan == DFS_CHNL_SCAN_ENABLED_ACTIVE)
{
cfgnumChannels =
pMac->roam.neighborRoamInfo.cfgParams.channelInfo.numOfChannels;
cfgChannelList =
pMac->roam.neighborRoamInfo.cfgParams.channelInfo.ChannelList;
if (cfgChannelList)
{
for(j=0; j< cfgnumChannels; j++)
{
if (CSR_IS_CHANNEL_DFS(cfgChannelList[j]) &&
(pMac->roam.validChannelList[i] == cfgChannelList[j]))
{
pChanList->chanParam[num_channel].dfsSet = VOS_FALSE;
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
"%s Marked DFS ch %d as active\n", __func__,
cfgChannelList[j]);
}
}
}
else
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
"%s cfgChannelList is NULL \n", __func__);
}
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
"%s Supported Channel: %d dfsSet %d pwr: %d \n", __func__,
pChanList->chanParam[num_channel].chanId,
pChanList->chanParam[num_channel].dfsSet,
pChanList->chanParam[num_channel].pwr);
num_channel++;
}
pChanList->regId = csrGetCurrentRegulatoryDomain(pMac);
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
"%s : regID : %d \n", __func__,
pChanList->regId);
pChanList->numChan = num_channel;
status = sme_AcquireGlobalLock(&pMac->sme);
if (HAL_STATUS_SUCCESS(status)) {
command = csrGetCommandBuffer(pMac);
if (command) {
command->command = eSmeCommandUpdateChannelList;
command->u.chan_list = pChanList;
status = csrQueueSmeCommand(pMac, command, eANI_BOOLEAN_TRUE);
if (!HAL_STATUS_SUCCESS(status)) {
smsLog(pMac, LOGE, FL("fail to send msg status = %d"), status);
csrReleaseCommand(pMac, command);
}
} else {
smsLog(pMac, LOGE, FL("can not obtain a common buffer"));
status = eHAL_STATUS_RESOURCES;
}
sme_ReleaseGlobalLock(&pMac->sme);
}
return status;
}
eHalStatus csrStart(tpAniSirGlobal pMac)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tANI_U32 i;
do
{
//save the global vos context
pMac->roam.gVosContext = vos_get_global_context(VOS_MODULE_ID_SME, pMac);
for( i = 0; i < CSR_ROAM_SESSION_MAX; i++ )
csrRoamStateChange( pMac, eCSR_ROAMING_STATE_IDLE, i );
status = csrRoamStart(pMac);
if(!HAL_STATUS_SUCCESS(status)) break;
pMac->scan.f11dInfoApplied = eANI_BOOLEAN_FALSE;
status = pmcRegisterPowerSaveCheck(pMac, csrCheckPSReady, pMac);
if(!HAL_STATUS_SUCCESS(status)) break;
pMac->roam.sPendingCommands = 0;
csrScanEnable(pMac);
#if defined WLAN_FEATURE_NEIGHBOR_ROAMING
status = csrNeighborRoamInit(pMac);
#endif /* WLAN_FEATURE_NEIGHBOR_ROAMING */
pMac->roam.tlStatsReqInfo.numClient = 0;
pMac->roam.tlStatsReqInfo.periodicity = 0;
pMac->roam.tlStatsReqInfo.timerRunning = FALSE;
//init the link quality indication also
pMac->roam.vccLinkQuality = eCSR_ROAM_LINK_QUAL_MIN_IND;
if(!HAL_STATUS_SUCCESS(status))
{
smsLog(pMac, LOGW, " csrStart: Couldn't Init HO control blk ");
break;
}
}while(0);
#if defined(ANI_LOGDUMP)
csrDumpInit(pMac);
#endif //#if defined(ANI_LOGDUMP)
return (status);
}
eHalStatus csrStop(tpAniSirGlobal pMac, tHalStopType stopType)
{
tANI_U32 sessionId;
tANI_U32 i;
for(sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; sessionId++)
{
csrRoamCloseSession(pMac, sessionId, TRUE, TRUE, NULL, NULL);
}
csrScanDisable(pMac);
pMac->scan.fCancelIdleScan = eANI_BOOLEAN_FALSE;
pMac->scan.fRestartIdleScan = eANI_BOOLEAN_FALSE;
csrLLPurge( &pMac->roam.roamCmdPendingList, eANI_BOOLEAN_TRUE );
#if defined WLAN_FEATURE_NEIGHBOR_ROAMING
csrNeighborRoamClose(pMac);
#endif
csrScanFlushResult(pMac); //Do we want to do this?
// deregister from PMC since we register during csrStart()
// (ignore status since there is nothing we can do if it fails)
(void) pmcDeregisterPowerSaveCheck(pMac, csrCheckPSReady);
//Reset the domain back to the deault
pMac->scan.domainIdCurrent = pMac->scan.domainIdDefault;
for( i = 0; i < CSR_ROAM_SESSION_MAX; i++ )
{
csrRoamStateChange( pMac, eCSR_ROAMING_STATE_STOP, i );
csrRoamSubstateChange(pMac, eCSR_ROAM_SUBSTATE_NONE, i);
}
#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
/* When HAL resets all the context information
* in HAL is lost, so we might need to send the
* scan offload request again when it comes
* out of reset for scan offload to be functional
*/
if (HAL_STOP_TYPE_SYS_RESET == stopType)
{
bRoamScanOffloadStarted = VOS_FALSE;
}
#endif
return (eHAL_STATUS_SUCCESS);
}
eHalStatus csrReady(tpAniSirGlobal pMac)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
csrScanGetSupportedChannels( pMac );
//WNI_CFG_VALID_CHANNEL_LIST should be set by this time
//use it to init the background scan list
csrInitBGScanChannelList(pMac);
//Store the AC weights in TL for later use
WLANTL_GetACWeights(pMac->roam.gVosContext, pMac->roam.ucACWeights);
status = csrInitChannelList( pMac );
if ( ! HAL_STATUS_SUCCESS( status ) )
{
smsLog( pMac, LOGE, "csrInitChannelList failed during csrReady with status=%d",
status );
}
return (status);
}
void csrSetDefaultDot11Mode( tpAniSirGlobal pMac )
{
v_U32_t wniDot11mode = 0;
wniDot11mode = csrTranslateToWNICfgDot11Mode(pMac,pMac->roam.configParam.uCfgDot11Mode);
ccmCfgSetInt(pMac, WNI_CFG_DOT11_MODE, wniDot11mode, NULL, eANI_BOOLEAN_FALSE);
}
void csrSetGlobalCfgs( tpAniSirGlobal pMac )
{
ccmCfgSetInt(pMac, WNI_CFG_FRAGMENTATION_THRESHOLD, csrGetFragThresh(pMac), NULL, eANI_BOOLEAN_FALSE);
ccmCfgSetInt(pMac, WNI_CFG_RTS_THRESHOLD, csrGetRTSThresh(pMac), NULL, eANI_BOOLEAN_FALSE);
ccmCfgSetInt(pMac, WNI_CFG_11D_ENABLED,
((pMac->roam.configParam.Is11hSupportEnabled) ? pMac->roam.configParam.Is11dSupportEnabled : pMac->roam.configParam.Is11dSupportEnabled),
NULL, eANI_BOOLEAN_FALSE);
ccmCfgSetInt(pMac, WNI_CFG_11H_ENABLED, pMac->roam.configParam.Is11hSupportEnabled, NULL, eANI_BOOLEAN_FALSE);
/* For now we will just use the 5GHz CB mode ini parameter to decide whether CB supported or not in Probes when there is no session
* Once session is established we will use the session related params stored in PE session for CB mode
*/
ccmCfgSetInt(pMac, WNI_CFG_CHANNEL_BONDING_MODE, !!(pMac->roam.configParam.channelBondingMode5GHz), NULL, eANI_BOOLEAN_FALSE);
ccmCfgSetInt(pMac, WNI_CFG_HEART_BEAT_THRESHOLD, pMac->roam.configParam.HeartbeatThresh24, NULL, eANI_BOOLEAN_FALSE);
//Update the operating mode to configured value during initialization,
//So that client can advertise full capabilities in Probe request frame.
csrSetDefaultDot11Mode( pMac );
}
eHalStatus csrRoamOpen(tpAniSirGlobal pMac)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tANI_U32 i;
tCsrRoamSession *pSession = NULL;
do
{
for( i = 0; i < CSR_ROAM_SESSION_MAX; i++ )
{
pSession = CSR_GET_SESSION( pMac, i );
pSession->roamingTimerInfo.pMac = pMac;
pSession->roamingTimerInfo.sessionId = CSR_SESSION_ID_INVALID;
}
pMac->roam.WaitForKeyTimerInfo.pMac = pMac;
pMac->roam.WaitForKeyTimerInfo.sessionId = CSR_SESSION_ID_INVALID;
status = vos_timer_init(&pMac->roam.hTimerWaitForKey, VOS_TIMER_TYPE_SW,
csrRoamWaitForKeyTimeOutHandler,
&pMac->roam.WaitForKeyTimerInfo);
if (!HAL_STATUS_SUCCESS(status))
{
smsLog(pMac, LOGE, FL("cannot allocate memory for WaitForKey time out timer"));
break;
}
status = vos_timer_init(&pMac->roam.tlStatsReqInfo.hTlStatsTimer,
VOS_TIMER_TYPE_SW, csrRoamTlStatsTimerHandler, pMac);
if (!HAL_STATUS_SUCCESS(status))
{
smsLog(pMac, LOGE, FL("cannot allocate memory for summary Statistics timer"));
return eHAL_STATUS_FAILURE;
}
vos_spin_lock_init(&pMac->roam.roam_state_lock);
}while (0);
return (status);
}
eHalStatus csrRoamClose(tpAniSirGlobal pMac)
{
tANI_U32 sessionId;
for(sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; sessionId++)
{
csrRoamCloseSession(pMac, sessionId, TRUE, TRUE, NULL, NULL);
}
vos_timer_stop(&pMac->roam.hTimerWaitForKey);
vos_timer_destroy(&pMac->roam.hTimerWaitForKey);
vos_timer_stop(&pMac->roam.tlStatsReqInfo.hTlStatsTimer);
vos_timer_destroy(&pMac->roam.tlStatsReqInfo.hTlStatsTimer);
vos_spin_lock_destroy(&pMac->roam.roam_state_lock);
return (eHAL_STATUS_SUCCESS);
}
eHalStatus csrRoamStart(tpAniSirGlobal pMac)
{
(void)pMac;
return (eHAL_STATUS_SUCCESS);
}
void csrRoamStop(tpAniSirGlobal pMac, tANI_U32 sessionId)
{
csrRoamStopRoamingTimer(pMac, sessionId);
/* deregister the clients requesting stats from PE/TL & also stop the corresponding timers*/
csrRoamDeregStatisticsReq(pMac);
}
eHalStatus csrRoamGetConnectState(tpAniSirGlobal pMac, tANI_U32 sessionId, eCsrConnectState *pState)
{
eHalStatus status = eHAL_STATUS_INVALID_PARAMETER;
if ( CSR_IS_SESSION_VALID(pMac, sessionId) && (NULL != pState) )
{
status = eHAL_STATUS_SUCCESS;
*pState = pMac->roam.roamSession[sessionId].connectState;
}
return (status);
}
eHalStatus csrRoamCopyConnectProfile(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamConnectedProfile *pProfile)
{
eHalStatus status = eHAL_STATUS_FAILURE;
tANI_U32 size = 0;
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return eHAL_STATUS_FAILURE;
}
if(pProfile)
{
if(pSession->pConnectBssDesc)
{
do
{
size = pSession->pConnectBssDesc->length + sizeof(pSession->pConnectBssDesc->length);
if(size)
{
pProfile->pBssDesc = vos_mem_malloc(size);
if ( NULL != pProfile->pBssDesc )
{
vos_mem_copy(pProfile->pBssDesc,
pSession->pConnectBssDesc, size);
status = eHAL_STATUS_SUCCESS;
}
else
break;
}
else
{
pProfile->pBssDesc = NULL;
}
pProfile->AuthType = pSession->connectedProfile.AuthType;
pProfile->EncryptionType = pSession->connectedProfile.EncryptionType;
pProfile->mcEncryptionType = pSession->connectedProfile.mcEncryptionType;
pProfile->BSSType = pSession->connectedProfile.BSSType;
pProfile->operationChannel = pSession->connectedProfile.operationChannel;
pProfile->CBMode = pSession->connectedProfile.CBMode;
vos_mem_copy(&pProfile->bssid, &pSession->connectedProfile.bssid,
sizeof(tCsrBssid));
vos_mem_copy(&pProfile->SSID, &pSession->connectedProfile.SSID,
sizeof(tSirMacSSid));
#ifdef WLAN_FEATURE_VOWIFI_11R
if (pSession->connectedProfile.MDID.mdiePresent)
{
pProfile->MDID.mdiePresent = 1;
pProfile->MDID.mobilityDomain = pSession->connectedProfile.MDID.mobilityDomain;
}
else
{
pProfile->MDID.mdiePresent = 0;
pProfile->MDID.mobilityDomain = 0;
}
#endif
#ifdef FEATURE_WLAN_ESE
pProfile->isESEAssoc = pSession->connectedProfile.isESEAssoc;
if (csrIsAuthTypeESE(pSession->connectedProfile.AuthType))
{
vos_mem_copy (pProfile->eseCckmInfo.krk,
pSession->connectedProfile.eseCckmInfo.krk,
CSR_KRK_KEY_LEN);
pProfile->eseCckmInfo.reassoc_req_num=
pSession->connectedProfile.eseCckmInfo.reassoc_req_num;
pProfile->eseCckmInfo.krk_plumbed =
pSession->connectedProfile.eseCckmInfo.krk_plumbed;
}
#endif
}while(0);
}
}
return (status);
}
eHalStatus csrRoamGetConnectProfile(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamConnectedProfile *pProfile)
{
eHalStatus status = eHAL_STATUS_FAILURE;
if((csrIsConnStateConnected(pMac, sessionId)) ||
(csrIsConnStateIbss(pMac, sessionId)))
{
if(pProfile)
{
status = csrRoamCopyConnectProfile(pMac, sessionId, pProfile);
}
}
return (status);
}
eHalStatus csrRoamFreeConnectProfile(tpAniSirGlobal pMac, tCsrRoamConnectedProfile *pProfile)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
if (pProfile->pBssDesc)
{
vos_mem_free(pProfile->pBssDesc);
}
if (pProfile->pAddIEAssoc)
{
vos_mem_free(pProfile->pAddIEAssoc);
}
vos_mem_set(pProfile, sizeof(tCsrRoamConnectedProfile), 0);
pProfile->AuthType = eCSR_AUTH_TYPE_UNKNOWN;
return (status);
}
eHalStatus csrRoamFreeConnectedInfo( tpAniSirGlobal pMac, tCsrRoamConnectedInfo *pConnectedInfo )
{
eHalStatus status = eHAL_STATUS_SUCCESS;
if( pConnectedInfo->pbFrames )
{
vos_mem_free(pConnectedInfo->pbFrames);
pConnectedInfo->pbFrames = NULL;
}
pConnectedInfo->nBeaconLength = 0;
pConnectedInfo->nAssocReqLength = 0;
pConnectedInfo->nAssocRspLength = 0;
pConnectedInfo->staId = 0;
#ifdef WLAN_FEATURE_VOWIFI_11R
pConnectedInfo->nRICRspLength = 0;
#endif
#ifdef FEATURE_WLAN_ESE
pConnectedInfo->nTspecIeLength = 0;
#endif
return ( status );
}
void csrReleaseCommandPreauth(tpAniSirGlobal pMac, tSmeCmd *pCommand)
{
csrReinitPreauthCmd(pMac, pCommand);
csrReleaseCommand( pMac, pCommand );
}
void csrReleaseCommandRoam(tpAniSirGlobal pMac, tSmeCmd *pCommand)
{
csrReinitRoamCmd(pMac, pCommand);
csrReleaseCommand( pMac, pCommand );
}
void csrReleaseCommandScan(tpAniSirGlobal pMac, tSmeCmd *pCommand)
{
csrReinitScanCmd(pMac, pCommand);
csrReleaseCommand( pMac, pCommand );
}
void csrReleaseCommandWmStatusChange(tpAniSirGlobal pMac, tSmeCmd *pCommand)
{
csrReinitWmStatusChangeCmd(pMac, pCommand);
csrReleaseCommand( pMac, pCommand );
}
void csrReinitSetKeyCmd(tpAniSirGlobal pMac, tSmeCmd *pCommand)
{
vos_mem_set(&pCommand->u.setKeyCmd, sizeof(tSetKeyCmd), 0);
}
void csrReinitRemoveKeyCmd(tpAniSirGlobal pMac, tSmeCmd *pCommand)
{
vos_mem_set(&pCommand->u.removeKeyCmd, sizeof(tRemoveKeyCmd), 0);
}
void csrReleaseCommandSetKey(tpAniSirGlobal pMac, tSmeCmd *pCommand)
{
csrReinitSetKeyCmd(pMac, pCommand);
csrReleaseCommand( pMac, pCommand );
}
void csrReleaseCommandRemoveKey(tpAniSirGlobal pMac, tSmeCmd *pCommand)
{
csrReinitRemoveKeyCmd(pMac, pCommand);
csrReleaseCommand( pMac, pCommand );
}
/**
* csr_is_disconnect_full_power_cmd() - Check if command is for
* disconnect or for fullpower
* @command: command to check
*
* Return: true if disconnect or full power command else false
*/
bool csr_is_disconnect_full_power_cmd(tSmeCmd *command)
{
switch (command->command) {
case eSmeCommandRoam:
if (CSR_IS_DISCONNECT_COMMAND(command))
return true;
break;
case eSmeCommandWmStatusChange:
case eSmeCommandExitImps:
case eSmeCommandExitBmps:
case eSmeCommandExitUapsd:
case eSmeCommandExitWowl:
return true;
default:
return false;
}
return false;
}
void csrAbortCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand, tANI_BOOLEAN fStopping )
{
if( eSmeCsrCommandMask & pCommand->command )
{
switch (pCommand->command)
{
case eSmeCommandScan:
// We need to inform the requester before dropping the scan command
smsLog( pMac, LOGW, "%s: Drop scan reason %d callback %pK",
__func__, pCommand->u.scanCmd.reason,
pCommand->u.scanCmd.callback);
if (NULL != pCommand->u.scanCmd.callback)
{
smsLog( pMac, LOGW, "%s callback scan requester", __func__);
csrScanCallCallback(pMac, pCommand, eCSR_SCAN_ABORT);
}
csrReleaseCommandScan( pMac, pCommand );
break;
case eSmeCommandRoam:
csrReleaseCommandRoam( pMac, pCommand );
break;
case eSmeCommandWmStatusChange:
csrReleaseCommandWmStatusChange( pMac, pCommand );
break;
case eSmeCommandSetKey:
csrReleaseCommandSetKey( pMac, pCommand );
break;
case eSmeCommandRemoveKey:
csrReleaseCommandRemoveKey( pMac, pCommand );
break;
default:
smsLog( pMac, LOGW, " CSR abort standard command %d", pCommand->command );
csrReleaseCommand( pMac, pCommand );
break;
}
}
}
void csrRoamSubstateChange( tpAniSirGlobal pMac, eCsrRoamSubState NewSubstate, tANI_U32 sessionId)
{
smsLog(pMac, LOG1, FL("CSR RoamSubstate: [ %s <== %s ]"),
macTraceGetcsrRoamSubState(NewSubstate),
macTraceGetcsrRoamSubState(pMac->roam.curSubState[sessionId]));
if(pMac->roam.curSubState[sessionId] == NewSubstate)
{
return;
}
vos_spin_lock_acquire(&pMac->roam.roam_state_lock);
pMac->roam.curSubState[sessionId] = NewSubstate;
vos_spin_lock_release(&pMac->roam.roam_state_lock);
}
eCsrRoamState csrRoamStateChange( tpAniSirGlobal pMac, eCsrRoamState NewRoamState, tANI_U8 sessionId)
{
eCsrRoamState PreviousState;
smsLog(pMac, LOG1, FL("CSR RoamState[%hu]: [ %s <== %s ]"), sessionId,
macTraceGetcsrRoamState(NewRoamState),
macTraceGetcsrRoamState(pMac->roam.curState[sessionId]));
PreviousState = pMac->roam.curState[sessionId];
if ( NewRoamState != pMac->roam.curState[sessionId] )
{
// Whenever we transition OUT of the Roaming state, clear the Roaming substate...
if ( CSR_IS_ROAM_JOINING(pMac, sessionId) )
{
csrRoamSubstateChange( pMac, eCSR_ROAM_SUBSTATE_NONE, sessionId );
}
pMac->roam.curState[sessionId] = NewRoamState;
}
return( PreviousState );
}
void csrAssignRssiForCategory(tpAniSirGlobal pMac, tANI_S8 bestApRssi, tANI_U8 catOffset)
{
int i;
if(catOffset)
{
pMac->roam.configParam.bCatRssiOffset = catOffset;
for(i = 0; i < CSR_NUM_RSSI_CAT; i++)
{
pMac->roam.configParam.RSSICat[CSR_NUM_RSSI_CAT - i - 1] = (int)bestApRssi - pMac->roam.configParam.nSelect5GHzMargin - (int)(i * catOffset);
}
}
}
static void initConfigParam(tpAniSirGlobal pMac)
{
int i;
pMac->roam.configParam.agingCount = CSR_AGING_COUNT;
pMac->roam.configParam.channelBondingMode24GHz =
WNI_CFG_CHANNEL_BONDING_MODE_DISABLE;
pMac->roam.configParam.channelBondingMode5GHz =
WNI_CFG_CHANNEL_BONDING_MODE_ENABLE;
pMac->roam.configParam.phyMode = eCSR_DOT11_MODE_TAURUS;
pMac->roam.configParam.eBand = eCSR_BAND_ALL;
pMac->roam.configParam.uCfgDot11Mode = eCSR_CFG_DOT11_MODE_TAURUS;
pMac->roam.configParam.FragmentationThreshold = eCSR_DOT11_FRAG_THRESH_DEFAULT;
pMac->roam.configParam.HeartbeatThresh24 = 40;
pMac->roam.configParam.HeartbeatThresh50 = 40;
pMac->roam.configParam.Is11dSupportEnabled = eANI_BOOLEAN_FALSE;
pMac->roam.configParam.Is11dSupportEnabledOriginal = eANI_BOOLEAN_FALSE;
pMac->roam.configParam.Is11eSupportEnabled = eANI_BOOLEAN_TRUE;
pMac->roam.configParam.Is11hSupportEnabled = eANI_BOOLEAN_TRUE;
pMac->roam.configParam.RTSThreshold = 2346;
pMac->roam.configParam.shortSlotTime = eANI_BOOLEAN_TRUE;
pMac->roam.configParam.WMMSupportMode = eCsrRoamWmmAuto;
pMac->roam.configParam.ProprietaryRatesEnabled = eANI_BOOLEAN_TRUE;
pMac->roam.configParam.TxRate = eCSR_TX_RATE_AUTO;
pMac->roam.configParam.impsSleepTime = CSR_IDLE_SCAN_NO_PS_INTERVAL;
pMac->roam.configParam.scanAgeTimeNCNPS = CSR_SCAN_AGING_TIME_NOT_CONNECT_NO_PS;
pMac->roam.configParam.scanAgeTimeNCPS = CSR_SCAN_AGING_TIME_NOT_CONNECT_W_PS;
pMac->roam.configParam.scanAgeTimeCNPS = CSR_SCAN_AGING_TIME_CONNECT_NO_PS;
pMac->roam.configParam.scanAgeTimeCPS = CSR_SCAN_AGING_TIME_CONNECT_W_PS;
for(i = 0; i < CSR_NUM_RSSI_CAT; i++)
{
pMac->roam.configParam.BssPreferValue[i] = i;
}
csrAssignRssiForCategory(pMac, CSR_BEST_RSSI_VALUE, CSR_DEFAULT_RSSI_DB_GAP);
pMac->roam.configParam.nRoamingTime = CSR_DEFAULT_ROAMING_TIME;
pMac->roam.configParam.fEnforce11dChannels = eANI_BOOLEAN_FALSE;
pMac->roam.configParam.fSupplicantCountryCodeHasPriority = eANI_BOOLEAN_FALSE;
pMac->roam.configParam.fEnforceCountryCodeMatch = eANI_BOOLEAN_FALSE;
pMac->roam.configParam.fEnforceDefaultDomain = eANI_BOOLEAN_FALSE;
pMac->roam.configParam.fEnforceCountryCode = eANI_BOOLEAN_FALSE;
pMac->roam.configParam.nActiveMaxChnTime = CSR_ACTIVE_MAX_CHANNEL_TIME;
pMac->roam.configParam.nActiveMinChnTime = CSR_ACTIVE_MIN_CHANNEL_TIME;
pMac->roam.configParam.nPassiveMaxChnTime = CSR_PASSIVE_MAX_CHANNEL_TIME;
pMac->roam.configParam.nPassiveMinChnTime = CSR_PASSIVE_MIN_CHANNEL_TIME;
pMac->roam.configParam.max_chntime_btc_esco =
CSR_ACTIVE_MAX_CHANNEL_TIME_ESCO_BTC;
pMac->roam.configParam.min_chntime_btc_esco =
CSR_ACTIVE_MIN_CHANNEL_TIME_ESCO_BTC;
pMac->roam.configParam.min_chntime_btc_sco =
CSR_ACTIVE_MIN_CHANNEL_TIME_SCO_BTC;
pMac->roam.configParam.max_chntime_btc_sco=
CSR_ACTIVE_MAX_CHANNEL_TIME_SCO_BTC;
pMac->roam.configParam.disableAggWithBtc = eANI_BOOLEAN_TRUE;
#ifdef WLAN_AP_STA_CONCURRENCY
pMac->roam.configParam.nActiveMaxChnTimeConc = CSR_ACTIVE_MAX_CHANNEL_TIME_CONC;
pMac->roam.configParam.nActiveMinChnTimeConc = CSR_ACTIVE_MIN_CHANNEL_TIME_CONC;
pMac->roam.configParam.nPassiveMaxChnTimeConc = CSR_PASSIVE_MAX_CHANNEL_TIME_CONC;
pMac->roam.configParam.nPassiveMinChnTimeConc = CSR_PASSIVE_MIN_CHANNEL_TIME_CONC;
pMac->roam.configParam.nRestTimeConc = CSR_REST_TIME_CONC;
pMac->roam.configParam.nNumStaChanCombinedConc = CSR_NUM_STA_CHAN_COMBINED_CONC;
pMac->roam.configParam.nNumP2PChanCombinedConc = CSR_NUM_P2P_CHAN_COMBINED_CONC;
#endif
pMac->roam.configParam.IsIdleScanEnabled = TRUE; //enable the idle scan by default
pMac->roam.configParam.nTxPowerCap = CSR_MAX_TX_POWER;
pMac->roam.configParam.statsReqPeriodicity = CSR_MIN_GLOBAL_STAT_QUERY_PERIOD;
pMac->roam.configParam.statsReqPeriodicityInPS = CSR_MIN_GLOBAL_STAT_QUERY_PERIOD_IN_BMPS;
#ifdef WLAN_FEATURE_VOWIFI_11R
pMac->roam.configParam.csr11rConfig.IsFTResourceReqSupported = 0;
#endif
#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
pMac->roam.configParam.neighborRoamConfig.nMaxNeighborRetries = 3;
pMac->roam.configParam.neighborRoamConfig.nNeighborLookupRssiThreshold = 120;
pMac->roam.configParam.neighborRoamConfig.nNeighborReassocRssiThreshold = 125;
pMac->roam.configParam.neighborRoamConfig.nNeighborScanMinChanTime = 20;
pMac->roam.configParam.neighborRoamConfig.nNeighborScanMaxChanTime = 40;
pMac->roam.configParam.neighborRoamConfig.nNeighborScanTimerPeriod = 200;
pMac->roam.configParam.neighborRoamConfig.neighborScanChanList.numChannels = 3;
pMac->roam.configParam.neighborRoamConfig.neighborScanChanList.channelList[0] = 1;
pMac->roam.configParam.neighborRoamConfig.neighborScanChanList.channelList[1] = 6;
pMac->roam.configParam.neighborRoamConfig.neighborScanChanList.channelList[2] = 11;
pMac->roam.configParam.neighborRoamConfig.nNeighborResultsRefreshPeriod = 20000; //20 seconds
pMac->roam.configParam.neighborRoamConfig.nEmptyScanRefreshPeriod = 0;
pMac->roam.configParam.neighborRoamConfig.nNeighborInitialForcedRoamTo5GhEnable = 0;
pMac->roam.configParam.neighborRoamConfig.nWeakZoneRssiThresholdForRoam = 0;
#endif
#ifdef WLAN_FEATURE_11AC
pMac->roam.configParam.nVhtChannelWidth = WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ + 1;
#endif
pMac->roam.configParam.addTSWhenACMIsOff = 0;
pMac->roam.configParam.fScanTwice = eANI_BOOLEAN_FALSE;
pMac->roam.configParam.agg_btc_sco_enabled = eANI_BOOLEAN_FALSE;
pMac->roam.configParam.num_ba_buff_btc_sco = DEFAULT_NUM_BUFF_BTC_SCO;
pMac->roam.configParam.num_ba_buff = WNI_CFG_NUM_BUFF_ADVERT_STADEF;
//Remove this code once SLM_Sessionization is supported
//BMPS_WORKAROUND_NOT_NEEDED
pMac->roam.configParam.doBMPSWorkaround = 0;
}
eCsrBand csrGetCurrentBand(tHalHandle hHal)
{
tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
return pMac->roam.configParam.bandCapability;
}
#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
/*
This function flushes the roam scan cache
*/
eHalStatus csrFlushRoamScanRoamChannelList(tpAniSirGlobal pMac)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo;
/* Free up the memory first (if required) */
if (NULL != pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList)
{
vos_mem_free(pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList);
pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList = NULL;
pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.numOfChannels = 0;
}
return status;
}
#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
/*
This function flushes the roam scan cache
*/
eHalStatus csrFlushCfgBgScanRoamChannelList(tpAniSirGlobal pMac)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo;
/* Free up the memory first (if required) */
if (NULL != pNeighborRoamInfo->cfgParams.channelInfo.ChannelList)
{
vos_mem_free(pNeighborRoamInfo->cfgParams.channelInfo.ChannelList);
pNeighborRoamInfo->cfgParams.channelInfo.ChannelList = NULL;
pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels = 0;
}
return status;
}
/*
This function flushes the roam scan cache and creates fresh cache
based on the input channel list
*/
eHalStatus csrCreateBgScanRoamChannelList(tpAniSirGlobal pMac,
const tANI_U8 *pChannelList,
const tANI_U8 numChannels)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo;
pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels = numChannels;
pNeighborRoamInfo->cfgParams.channelInfo.ChannelList =
vos_mem_malloc(pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels);
if (NULL == pNeighborRoamInfo->cfgParams.channelInfo.ChannelList)
{
smsLog(pMac, LOGE, FL("Memory Allocation for CFG Channel List failed"));
pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels = 0;
return eHAL_STATUS_RESOURCES;
}
/* Update the roam global structure */
vos_mem_copy(pNeighborRoamInfo->cfgParams.channelInfo.ChannelList,
pChannelList,
pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels);
return status;
}
/* This function modifies the bgscan channel list set via config ini or
runtime, whenever the band changes.
if the band is auto, then no operation is performed on the channel list
if the band is 2.4G, then make sure channel list contains only 2.4G valid channels
if the band is 5G, then make sure channel list contains only 5G valid channels
*/
eHalStatus csrUpdateBgScanConfigIniChannelList(tpAniSirGlobal pMac,
eCsrBand eBand)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo;
tANI_U8 outNumChannels = 0;
tANI_U8 inNumChannels = 0;
tANI_U8 *inPtr = NULL;
tANI_U8 i = 0;
tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
if (NULL == pNeighborRoamInfo->cfgParams.channelInfo.ChannelList)
{
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
"No update required for channel list "
"either cfg.ini channel list is not set up or "
"auto band (Band %d)", eBand);
return status;
}
inNumChannels = pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels;
inPtr = pNeighborRoamInfo->cfgParams.channelInfo.ChannelList;
if (eCSR_BAND_24 == eBand)
{
for (i = 0; i < inNumChannels; i++)
{
if (CSR_IS_CHANNEL_24GHZ(inPtr[i]) && csrRoamIsChannelValid(pMac, inPtr[i]))
{
ChannelList[outNumChannels++] = inPtr[i];
}
}
csrFlushCfgBgScanRoamChannelList(pMac);
csrCreateBgScanRoamChannelList(pMac, ChannelList, outNumChannels);
}
else if (eCSR_BAND_5G == eBand)
{
for (i = 0; i < inNumChannels; i++)
{
/* Add 5G Non-DFS channel */
if (CSR_IS_CHANNEL_5GHZ(inPtr[i]) &&
csrRoamIsChannelValid(pMac, inPtr[i]) &&
!CSR_IS_CHANNEL_DFS(inPtr[i]))
{
ChannelList[outNumChannels++] = inPtr[i];
}
}
csrFlushCfgBgScanRoamChannelList(pMac);
csrCreateBgScanRoamChannelList(pMac, ChannelList, outNumChannels);
}
else if (eCSR_BAND_ALL == eBand)
{
for (i = 0; i < inNumChannels; i++)
{
if (csrRoamIsChannelValid(pMac, inPtr[i]) &&
!CSR_IS_CHANNEL_DFS(inPtr[i]))
{
ChannelList[outNumChannels++] = inPtr[i];
}
}
csrFlushCfgBgScanRoamChannelList(pMac);
csrCreateBgScanRoamChannelList(pMac, ChannelList, outNumChannels);
}
else
{
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_WARN,
"Invalid band, No operation carried out (Band %d)", eBand);
status = eHAL_STATUS_INVALID_PARAMETER;
}
return status;
}
#endif
#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
/* This function modifies the roam scan channel list as per AP neighbor
report; AP neighbor report may be empty or may include only other AP
channels; in any case, we merge the channel list with the learned occupied
channels list.
if the band is 2.4G, then make sure channel list contains only 2.4G valid channels
if the band is 5G, then make sure channel list contains only 5G valid channels
*/
eHalStatus csrCreateRoamScanChannelList(tpAniSirGlobal pMac,
tANI_U8 *pChannelList,
tANI_U8 numChannels,
const eCsrBand eBand)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo;
tANI_U8 outNumChannels = 0;
tANI_U8 inNumChannels = numChannels;
tANI_U8 *inPtr = pChannelList;
tANI_U8 i = 0;
tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
tANI_U8 tmpChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
tANI_U8 mergedOutputNumOfChannels = 0;
tpCsrChannelInfo currChannelListInfo = &pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo;
/* Create a Union of occupied channel list learnt by the DUT along with the Neighbor
* report Channels. This increases the chances of the DUT to get a candidate AP while
* roaming even if the Neighbor Report is not able to provide sufficient information. */
if (pMac->scan.occupiedChannels.numChannels)
{
csrNeighborRoamMergeChannelLists(pMac,
&pMac->scan.occupiedChannels.channelList[0],
pMac->scan.occupiedChannels.numChannels,
inPtr,
inNumChannels,
&mergedOutputNumOfChannels);
inNumChannels = mergedOutputNumOfChannels;
}
if (eCSR_BAND_24 == eBand)
{
for (i = 0; i < inNumChannels; i++)
{
if (CSR_IS_CHANNEL_24GHZ(inPtr[i]) && csrRoamIsChannelValid(pMac, inPtr[i]))
{
ChannelList[outNumChannels++] = inPtr[i];
}
}
}
else if (eCSR_BAND_5G == eBand)
{
for (i = 0; i < inNumChannels; i++)
{
/* Add 5G Non-DFS channel */
if (CSR_IS_CHANNEL_5GHZ(inPtr[i]) &&
csrRoamIsChannelValid(pMac, inPtr[i]) &&
!CSR_IS_CHANNEL_DFS(inPtr[i]))
{
ChannelList[outNumChannels++] = inPtr[i];
}
}
}
else if (eCSR_BAND_ALL == eBand)
{
for (i = 0; i < inNumChannels; i++)
{
if (csrRoamIsChannelValid(pMac, inPtr[i]) &&
!CSR_IS_CHANNEL_DFS(inPtr[i]))
{
ChannelList[outNumChannels++] = inPtr[i];
}
}
}
else
{
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_WARN,
"Invalid band, No operation carried out (Band %d)", eBand);
return eHAL_STATUS_INVALID_PARAMETER;
}
/* if roaming within band is enabled, then select only the
in band channels .
This is required only if the band capability is set to ALL,
E.g., if band capability is only 2.4G then all the channels in the
list are already filtered for 2.4G channels, hence ignore this check*/
if ((eCSR_BAND_ALL == eBand) && CSR_IS_ROAM_INTRA_BAND_ENABLED(pMac))
{
csrNeighborRoamChannelsFilterByBand(
pMac,
ChannelList,
outNumChannels,
tmpChannelList,
&outNumChannels,
GetRFBand(pMac->roam.neighborRoamInfo.currAPoperationChannel));
vos_mem_copy(ChannelList,
tmpChannelList, outNumChannels);
}
/* Prepare final roam scan channel list */
if(outNumChannels)
{
/* Clear the channel list first */
if (NULL != currChannelListInfo->ChannelList)
{
vos_mem_free(currChannelListInfo->ChannelList);
currChannelListInfo->ChannelList = NULL;
currChannelListInfo->numOfChannels = 0;
}
currChannelListInfo->ChannelList = vos_mem_malloc(outNumChannels * sizeof(tANI_U8));
if (NULL == currChannelListInfo->ChannelList)
{
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,
"Failed to allocate memory for roam scan channel list");
currChannelListInfo->numOfChannels = 0;
return VOS_STATUS_E_RESOURCES;
}
vos_mem_copy(currChannelListInfo->ChannelList,
ChannelList, outNumChannels);
}
return status;
}
#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
eHalStatus csrSetBand(tHalHandle hHal, eCsrBand eBand)
{
tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
eHalStatus status = eHAL_STATUS_SUCCESS;
if (CSR_IS_PHY_MODE_A_ONLY(pMac) &&
(eBand == eCSR_BAND_24))
{
/* DOT11 mode configured to 11a only and received
request to change the band to 2.4 GHz */
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
"failed to set band cfg80211 = %u, band = %u",
pMac->roam.configParam.uCfgDot11Mode, eBand);
return eHAL_STATUS_INVALID_PARAMETER;
}
if ((CSR_IS_PHY_MODE_B_ONLY(pMac) ||
CSR_IS_PHY_MODE_G_ONLY(pMac)) &&
(eBand == eCSR_BAND_5G))
{
/* DOT11 mode configured to 11b/11g only and received
request to change the band to 5 GHz */
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
"failed to set band dot11mode = %u, band = %u",
pMac->roam.configParam.uCfgDot11Mode, eBand);
return eHAL_STATUS_INVALID_PARAMETER;
}
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
"Band changed to %u (0 - ALL, 1 - 2.4 GHZ, 2 - 5GHZ)", eBand);
pMac->roam.configParam.eBand = eBand;
pMac->roam.configParam.bandCapability = eBand;
csrScanGetSupportedChannels( pMac );
#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
if (!csrRoamIsRoamOffloadScanEnabled(pMac))
csrUpdateBgScanConfigIniChannelList( pMac, eBand );
#endif
status = csrInitGetChannels( pMac );
if (eHAL_STATUS_SUCCESS == status)
csrInitChannelList( hHal );
return status;
}
/* The funcns csrConvertCBIniValueToPhyCBState and csrConvertPhyCBStateToIniValue have been
* introduced to convert the ini value to the ENUM used in csr and MAC for CB state
* Ideally we should have kept the ini value and enum value same and representing the same
* cb values as in 11n standard i.e.
* Set to 1 (SCA) if the secondary channel is above the primary channel
* Set to 3 (SCB) if the secondary channel is below the primary channel
* Set to 0 (SCN) if no secondary channel is present
* However, since our driver is already distributed we will keep the ini definition as it is which is:
* 0 - secondary none
* 1 - secondary LOW
* 2 - secondary HIGH
* and convert to enum value used within the driver in csrChangeDefaultConfigParam using this funcn
* The enum values are as follows:
* PHY_SINGLE_CHANNEL_CENTERED = 0
* PHY_DOUBLE_CHANNEL_LOW_PRIMARY = 1
* PHY_DOUBLE_CHANNEL_HIGH_PRIMARY = 3
*/
ePhyChanBondState csrConvertCBIniValueToPhyCBState(v_U32_t cbIniValue)
{
ePhyChanBondState phyCbState;
switch (cbIniValue) {
// secondary none
case eCSR_INI_SINGLE_CHANNEL_CENTERED:
phyCbState = PHY_SINGLE_CHANNEL_CENTERED;
break;
// secondary LOW
case eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY:
phyCbState = PHY_DOUBLE_CHANNEL_HIGH_PRIMARY;
break;
// secondary HIGH
case eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY:
phyCbState = PHY_DOUBLE_CHANNEL_LOW_PRIMARY;
break;
#ifdef WLAN_FEATURE_11AC
case eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_CENTERED:
phyCbState = PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_CENTERED;
break;
case eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_CENTERED_40MHZ_CENTERED:
phyCbState = PHY_QUADRUPLE_CHANNEL_20MHZ_CENTERED_40MHZ_CENTERED;
break;
case eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_CENTERED:
phyCbState = PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_CENTERED;
break;
case eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW:
phyCbState = PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW;
break;
case eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW:
phyCbState = PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW;
break;
case eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH:
phyCbState = PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH;
break;
case eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH:
phyCbState = PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH;
break;
#endif
default:
// If an invalid value is passed, disable CHANNEL BONDING
phyCbState = PHY_SINGLE_CHANNEL_CENTERED;
break;
}
return phyCbState;
}
v_U32_t csrConvertPhyCBStateToIniValue(ePhyChanBondState phyCbState)
{
v_U32_t cbIniValue;
switch (phyCbState) {
// secondary none
case PHY_SINGLE_CHANNEL_CENTERED:
cbIniValue = eCSR_INI_SINGLE_CHANNEL_CENTERED;
break;
// secondary LOW
case PHY_DOUBLE_CHANNEL_HIGH_PRIMARY:
cbIniValue = eCSR_INI_DOUBLE_CHANNEL_HIGH_PRIMARY;
break;
// secondary HIGH
case PHY_DOUBLE_CHANNEL_LOW_PRIMARY:
cbIniValue = eCSR_INI_DOUBLE_CHANNEL_LOW_PRIMARY;
break;
#ifdef WLAN_FEATURE_11AC
case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_CENTERED:
cbIniValue = eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_CENTERED;
break;
case PHY_QUADRUPLE_CHANNEL_20MHZ_CENTERED_40MHZ_CENTERED:
cbIniValue = eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_CENTERED_40MHZ_CENTERED;
break;
case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_CENTERED:
cbIniValue = eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_CENTERED;
break;
case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW:
cbIniValue = eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW;
break;
case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW:
cbIniValue = eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW;
break;
case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH:
cbIniValue = eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH;
break;
case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH:
cbIniValue = eCSR_INI_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH;
break;
#endif
default:
// return some invalid value
cbIniValue = eCSR_INI_CHANNEL_BONDING_STATE_MAX;
break;
}
return cbIniValue;
}
eHalStatus csrChangeDefaultConfigParam(tpAniSirGlobal pMac, tCsrConfigParam *pParam)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tANI_U8 i;
if(pParam)
{
pMac->roam.configParam.WMMSupportMode = pParam->WMMSupportMode;
pMac->roam.configParam.Is11eSupportEnabled = pParam->Is11eSupportEnabled;
pMac->roam.configParam.FragmentationThreshold = pParam->FragmentationThreshold;
pMac->roam.configParam.Is11dSupportEnabled = pParam->Is11dSupportEnabled;
pMac->roam.configParam.Is11dSupportEnabledOriginal = pParam->Is11dSupportEnabled;
pMac->roam.configParam.Is11hSupportEnabled = pParam->Is11hSupportEnabled;
pMac->roam.configParam.fenableMCCMode = pParam->fEnableMCCMode;
pMac->roam.configParam.fAllowMCCGODiffBI = pParam->fAllowMCCGODiffBI;
/* channelBondingMode5GHz plays a dual role right now
* INFRA STA will use this non zero value as CB enabled and SOFTAP will use this non-zero value to determine the secondary channel offset
* This is how channelBondingMode5GHz works now and this is kept intact to avoid any cfg.ini change
*/
if (pParam->channelBondingMode24GHz > MAX_CB_VALUE_IN_INI)
{
smsLog( pMac, LOGW, "Invalid CB value from ini in 2.4GHz band %d, CB DISABLED", pParam->channelBondingMode24GHz);
}
pMac->roam.configParam.channelBondingMode24GHz = csrConvertCBIniValueToPhyCBState(pParam->channelBondingMode24GHz);
if (pParam->channelBondingMode5GHz > MAX_CB_VALUE_IN_INI)
{
smsLog( pMac, LOGW, "Invalid CB value from ini in 5GHz band %d, CB DISABLED", pParam->channelBondingMode5GHz);
}
#ifdef WLAN_FEATURE_AP_HT40_24G
pMac->roam.configParam.channelBondingAPMode24GHz = csrConvertCBIniValueToPhyCBState(pParam->channelBondingAPMode24GHz);
#endif
pMac->roam.configParam.channelBondingMode5GHz = csrConvertCBIniValueToPhyCBState(pParam->channelBondingMode5GHz);
pMac->roam.configParam.RTSThreshold = pParam->RTSThreshold;
pMac->roam.configParam.phyMode = pParam->phyMode;
pMac->roam.configParam.shortSlotTime = pParam->shortSlotTime;
pMac->roam.configParam.HeartbeatThresh24 = pParam->HeartbeatThresh24;
pMac->roam.configParam.HeartbeatThresh50 = pParam->HeartbeatThresh50;
pMac->roam.configParam.ProprietaryRatesEnabled = pParam->ProprietaryRatesEnabled;
pMac->roam.configParam.TxRate = pParam->TxRate;
pMac->roam.configParam.AdHocChannel24 = pParam->AdHocChannel24;
pMac->roam.configParam.AdHocChannel5G = pParam->AdHocChannel5G;
pMac->roam.configParam.bandCapability = pParam->bandCapability;
pMac->roam.configParam.cbChoice = pParam->cbChoice;
pMac->roam.configParam.bgScanInterval = pParam->bgScanInterval;
pMac->roam.configParam.disableAggWithBtc = pParam->disableAggWithBtc;
//if HDD passed down non zero values then only update,
//otherwise keep using the defaults
if (pParam->nInitialDwellTime)
{
pMac->roam.configParam.nInitialDwellTime =
pParam->nInitialDwellTime;
}
if (pParam->nActiveMaxChnTime)
{
pMac->roam.configParam.nActiveMaxChnTime = pParam->nActiveMaxChnTime;
cfgSetInt(pMac, WNI_CFG_ACTIVE_MAXIMUM_CHANNEL_TIME,
pParam->nActiveMaxChnTime);
}
if (pParam->nActiveMinChnTime)
{
pMac->roam.configParam.nActiveMinChnTime = pParam->nActiveMinChnTime;
cfgSetInt(pMac, WNI_CFG_ACTIVE_MINIMUM_CHANNEL_TIME,
pParam->nActiveMinChnTime);
}
if (pParam->nPassiveMaxChnTime)
{
pMac->roam.configParam.nPassiveMaxChnTime = pParam->nPassiveMaxChnTime;
cfgSetInt(pMac, WNI_CFG_PASSIVE_MAXIMUM_CHANNEL_TIME,
pParam->nPassiveMaxChnTime);
}
if (pParam->nPassiveMinChnTime)
{
pMac->roam.configParam.nPassiveMinChnTime = pParam->nPassiveMinChnTime;
cfgSetInt(pMac, WNI_CFG_PASSIVE_MINIMUM_CHANNEL_TIME,
pParam->nPassiveMinChnTime);
}
if (pParam->nOBSSScanWidthTriggerInterval)
{
pMac->roam.configParam.nOBSSScanWidthTriggerInterval =
pParam->nOBSSScanWidthTriggerInterval;
cfgSetInt(pMac, WNI_CFG_OBSS_HT40_SCAN_WIDTH_TRIGGER_INTERVAL,
pParam->nOBSSScanWidthTriggerInterval);
}
if (pParam->max_chntime_btc_esco)
{
pMac->roam.configParam.max_chntime_btc_esco =
pParam->max_chntime_btc_esco;
}
if (pParam->min_chntime_btc_esco)
{
pMac->roam.configParam.min_chntime_btc_esco =
pParam->min_chntime_btc_esco;
}
if (pParam->min_chntime_btc_sco)
pMac->roam.configParam.min_chntime_btc_sco =
pParam->min_chntime_btc_sco;
if (pParam->max_chntime_btc_sco)
pMac->roam.configParam.max_chntime_btc_sco =
pParam->max_chntime_btc_sco;
#ifdef WLAN_AP_STA_CONCURRENCY
if (pParam->nActiveMaxChnTimeConc)
{
pMac->roam.configParam.nActiveMaxChnTimeConc = pParam->nActiveMaxChnTimeConc;
}
if (pParam->nActiveMinChnTimeConc)
{
pMac->roam.configParam.nActiveMinChnTimeConc = pParam->nActiveMinChnTimeConc;
}
if (pParam->nPassiveMaxChnTimeConc)
{
pMac->roam.configParam.nPassiveMaxChnTimeConc = pParam->nPassiveMaxChnTimeConc;
}
if (pParam->nPassiveMinChnTimeConc)
{
pMac->roam.configParam.nPassiveMinChnTimeConc = pParam->nPassiveMinChnTimeConc;
}
if (pParam->nRestTimeConc)
{
pMac->roam.configParam.nRestTimeConc = pParam->nRestTimeConc;
}
if (pParam->nNumStaChanCombinedConc)
{
pMac->roam.configParam.nNumStaChanCombinedConc = pParam->nNumStaChanCombinedConc;
}
if (pParam->nNumP2PChanCombinedConc)
{
pMac->roam.configParam.nNumP2PChanCombinedConc = pParam->nNumP2PChanCombinedConc;
}
#endif
//if upper layer wants to disable idle scan altogether set it to 0
if (pParam->impsSleepTime)
{
//Change the unit from second to microsecond
tANI_U32 impsSleepTime = pParam->impsSleepTime * PAL_TIMER_TO_SEC_UNIT;
if(CSR_IDLE_SCAN_NO_PS_INTERVAL_MIN <= impsSleepTime)
{
pMac->roam.configParam.impsSleepTime = impsSleepTime;
}
else
{
pMac->roam.configParam.impsSleepTime = CSR_IDLE_SCAN_NO_PS_INTERVAL;
}
}
else
{
pMac->roam.configParam.impsSleepTime = 0;
}
pMac->roam.configParam.eBand = pParam->eBand;
pMac->roam.configParam.uCfgDot11Mode = csrGetCfgDot11ModeFromCsrPhyMode(NULL, pMac->roam.configParam.phyMode,
pMac->roam.configParam.ProprietaryRatesEnabled);
//if HDD passed down non zero values for age params, then only update,
//otherwise keep using the defaults
if (pParam->nScanResultAgeCount)
{
pMac->roam.configParam.agingCount = pParam->nScanResultAgeCount;
}
if(pParam->scanAgeTimeNCNPS)
{
pMac->roam.configParam.scanAgeTimeNCNPS = pParam->scanAgeTimeNCNPS;
}
if(pParam->scanAgeTimeNCPS)
{
pMac->roam.configParam.scanAgeTimeNCPS = pParam->scanAgeTimeNCPS;
}
if(pParam->scanAgeTimeCNPS)
{
pMac->roam.configParam.scanAgeTimeCNPS = pParam->scanAgeTimeCNPS;
}
if(pParam->scanAgeTimeCPS)
{
pMac->roam.configParam.scanAgeTimeCPS = pParam->scanAgeTimeCPS;
}
if (pParam->initialScanSkipDFSCh)
{
pMac->roam.configParam.initialScanSkipDFSCh =
pParam->initialScanSkipDFSCh;
}
csrAssignRssiForCategory(pMac, CSR_BEST_RSSI_VALUE, pParam->bCatRssiOffset);
pMac->roam.configParam.nRoamingTime = pParam->nRoamingTime;
pMac->roam.configParam.fEnforce11dChannels = pParam->fEnforce11dChannels;
pMac->roam.configParam.fSupplicantCountryCodeHasPriority = pParam->fSupplicantCountryCodeHasPriority;
pMac->roam.configParam.fEnforceCountryCodeMatch = pParam->fEnforceCountryCodeMatch;
pMac->roam.configParam.fEnforceDefaultDomain = pParam->fEnforceDefaultDomain;
pMac->roam.configParam.vccRssiThreshold = pParam->vccRssiThreshold;
pMac->roam.configParam.vccUlMacLossThreshold = pParam->vccUlMacLossThreshold;
pMac->roam.configParam.IsIdleScanEnabled = pParam->IsIdleScanEnabled;
pMac->roam.configParam.statsReqPeriodicity = pParam->statsReqPeriodicity;
pMac->roam.configParam.statsReqPeriodicityInPS = pParam->statsReqPeriodicityInPS;
//Assign this before calling CsrInit11dInfo
pMac->roam.configParam.nTxPowerCap = pParam->nTxPowerCap;
if( csrIs11dSupported( pMac ) )
{
status = CsrInit11dInfo(pMac, &pParam->Csr11dinfo);
}
else
{
pMac->scan.curScanType = eSIR_ACTIVE_SCAN;
}
/* Initialize the power + channel information if 11h is enabled.
If 11d is enabled this information has already been initialized */
if( csrIs11hSupported( pMac ) && !csrIs11dSupported( pMac ) )
{
csrInitChannelPowerList(pMac, &pParam->Csr11dinfo);
}
#ifdef WLAN_FEATURE_VOWIFI_11R
vos_mem_copy(&pMac->roam.configParam.csr11rConfig,
&pParam->csr11rConfig, sizeof(tCsr11rConfigParams));
smsLog( pMac, LOG1, "IsFTResourceReqSupp = %d", pMac->roam.configParam.csr11rConfig.IsFTResourceReqSupported);
#endif
#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
pMac->roam.configParam.isFastTransitionEnabled = pParam->isFastTransitionEnabled;
pMac->roam.configParam.RoamRssiDiff = pParam->RoamRssiDiff;
pMac->roam.configParam.nImmediateRoamRssiDiff = pParam->nImmediateRoamRssiDiff;
smsLog( pMac, LOG1, "nImmediateRoamRssiDiff = %d",
pMac->roam.configParam.nImmediateRoamRssiDiff );
pMac->roam.configParam.nRoamPrefer5GHz = pParam->nRoamPrefer5GHz;
pMac->roam.configParam.nRoamIntraBand = pParam->nRoamIntraBand;
pMac->roam.configParam.isWESModeEnabled = pParam->isWESModeEnabled;
pMac->roam.configParam.nProbes = pParam->nProbes;
pMac->roam.configParam.nRoamScanHomeAwayTime = pParam->nRoamScanHomeAwayTime;
#endif
#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
pMac->roam.configParam.isRoamOffloadScanEnabled =
pParam->isRoamOffloadScanEnabled;
pMac->roam.configParam.bFastRoamInConIniFeatureEnabled =
pParam->bFastRoamInConIniFeatureEnabled;
pMac->roam.configParam.isPERRoamEnabled =
pParam->isPERRoamEnabled;
pMac->roam.configParam.rateUpThreshold = pParam->rateUpThreshold;
pMac->roam.configParam.rateDownThreshold = pParam->rateDownThreshold;
pMac->roam.configParam.waitPeriodForNextPERScan =
pParam->waitPeriodForNextPERScan;
pMac->roam.configParam.PERtimerThreshold = pParam->PERtimerThreshold;
pMac->roam.configParam.isPERRoamCCAEnabled =
pParam->isPERRoamCCAEnabled;
pMac->roam.configParam.PERRoamFullScanThreshold =
pParam->PERRoamFullScanThreshold;
pMac->roam.configParam.PERroamTriggerPercent =
pParam->PERroamTriggerPercent;
pMac->roam.configParam.PERMinRssiThresholdForRoam =
pParam->PERMinRssiThresholdForRoam;
pMac->PERroamTimeout = pParam->waitPeriodForNextPERScan;
#endif
#ifdef WLAN_FEATURE_LFR_MBB
pMac->roam.configParam.enable_lfr_mbb = pParam->enable_lfr_mbb;
#endif
#ifdef FEATURE_WLAN_LFR
pMac->roam.configParam.isFastRoamIniFeatureEnabled = pParam->isFastRoamIniFeatureEnabled;
pMac->roam.configParam.MAWCEnabled = pParam->MAWCEnabled;
#endif
#ifdef FEATURE_WLAN_ESE
pMac->roam.configParam.isEseIniFeatureEnabled = pParam->isEseIniFeatureEnabled;
#endif
#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
vos_mem_copy(&pMac->roam.configParam.neighborRoamConfig,
&pParam->neighborRoamConfig, sizeof(tCsrNeighborRoamConfigParams));
smsLog( pMac, LOG1, "nNeighborScanTimerPerioid = %d", pMac->roam.configParam.neighborRoamConfig.nNeighborScanTimerPeriod);
smsLog( pMac, LOG1, "nNeighborReassocRssiThreshold = %d", pMac->roam.configParam.neighborRoamConfig.nNeighborReassocRssiThreshold);
smsLog( pMac, LOG1, "nNeighborLookupRssiThreshold = %d", pMac->roam.configParam.neighborRoamConfig.nNeighborLookupRssiThreshold);
smsLog( pMac, LOG1, "nNeighborScanMinChanTime = %d", pMac->roam.configParam.neighborRoamConfig.nNeighborScanMinChanTime);
smsLog( pMac, LOG1, "nNeighborScanMaxChanTime = %d", pMac->roam.configParam.neighborRoamConfig.nNeighborScanMaxChanTime);
smsLog( pMac, LOG1, "nMaxNeighborRetries = %d", pMac->roam.configParam.neighborRoamConfig.nMaxNeighborRetries);
smsLog( pMac, LOG1, "nNeighborResultsRefreshPeriod = %d", pMac->roam.configParam.neighborRoamConfig.nNeighborResultsRefreshPeriod);
smsLog( pMac, LOG1, "nEmptyScanRefreshPeriod = %d", pMac->roam.configParam.neighborRoamConfig.nEmptyScanRefreshPeriod);
smsLog( pMac, LOG1, "nNeighborInitialForcedRoamTo5GhEnable = %d", pMac->roam.configParam.neighborRoamConfig.nNeighborInitialForcedRoamTo5GhEnable);
smsLog( pMac, LOG1, "nWeakZoneRssiThresholdForRoam = %d", pMac->roam.configParam.neighborRoamConfig.nWeakZoneRssiThresholdForRoam);
{
int i;
smsLog( pMac, LOG1, FL("Num of Channels in CFG Channel List: %d"), pMac->roam.configParam.neighborRoamConfig.neighborScanChanList.numChannels);
for( i=0; i< pMac->roam.configParam.neighborRoamConfig.neighborScanChanList.numChannels; i++)
{
smsLog( pMac, LOG1, "%d ", pMac->roam.configParam.neighborRoamConfig.neighborScanChanList.channelList[i] );
}
}
#endif
pMac->roam.configParam.addTSWhenACMIsOff = pParam->addTSWhenACMIsOff;
pMac->scan.fValidateList = pParam->fValidateList;
pMac->scan.fEnableBypass11d = pParam->fEnableBypass11d;
pMac->scan.fEnableDFSChnlScan = pParam->fEnableDFSChnlScan;
pMac->scan.disable_scan_during_sco = pParam->disable_scan_during_sco;
pMac->scan.scanResultCfgAgingTime = pParam->scanCfgAgingTime;
pMac->roam.configParam.fScanTwice = pParam->fScanTwice;
pMac->scan.fFirstScanOnly2GChnl = pParam->fFirstScanOnly2GChnl;
pMac->scan.scanBandPreference = pParam->scanBandPreference;
/* This parameter is not available in cfg and not passed from upper layers. Instead it is initialized here
* This paramtere is used in concurrency to determine if there are concurrent active sessions.
* Is used as a temporary fix to disconnect all active sessions when BMPS enabled so the active session if Infra STA
* will automatically connect back and resume BMPS since resume BMPS is not working when moving from concurrent to
* single session
*/
//Remove this code once SLM_Sessionization is supported
//BMPS_WORKAROUND_NOT_NEEDED
pMac->roam.configParam.doBMPSWorkaround = 0;
#ifdef WLAN_FEATURE_11AC
pMac->roam.configParam.nVhtChannelWidth = pParam->nVhtChannelWidth;
pMac->roam.configParam.txBFEnable= pParam->enableTxBF;
pMac->roam.configParam.txBFCsnValue = pParam->txBFCsnValue;
pMac->roam.configParam.enableVhtFor24GHz = pParam->enableVhtFor24GHz;
/* Consider Mu-beamformee only if SU-beamformee is enabled */
if ( pParam->enableTxBF )
pMac->roam.configParam.txMuBformee= pParam->enableMuBformee;
else
pMac->roam.configParam.txMuBformee= 0;
#endif
pMac->roam.configParam.txLdpcEnable = pParam->enableTxLdpc;
pMac->roam.configParam.isAmsduSupportInAMPDU = pParam->isAmsduSupportInAMPDU;
pMac->roam.configParam.nSelect5GHzMargin = pParam->nSelect5GHzMargin;
pMac->roam.configParam.ignorePeerErpInfo = pParam->ignorePeerErpInfo;
pMac->roam.configParam.ignorePeerHTopMode = pParam->ignorePeerHTopMode;
pMac->roam.configParam.disableP2PMacSpoofing =
pParam->disableP2PMacSpoofing;
pMac->roam.configParam.enableFatalEvent =
pParam->enableFatalEvent;
pMac->roam.configParam.isCoalesingInIBSSAllowed =
pParam->isCoalesingInIBSSAllowed;
pMac->roam.configParam.allowDFSChannelRoam = pParam->allowDFSChannelRoam;
pMac->roam.configParam.sendDeauthBeforeCon = pParam->sendDeauthBeforeCon;
#ifdef WLAN_FEATURE_AP_HT40_24G
pMac->roam.configParam.apHT40_24GEnabled = pParam->apHT40_24GEnabled;
#endif
pMac->roam.configParam.roamDelayStatsEnabled = pParam->roamDelayStatsEnabled;
pMac->roam.configParam.max_chan_for_dwell_time_cfg =
pParam->max_chan_for_dwell_time_cfg;
pMac->roam.configParam.enable_edca_params = pParam->enable_edca_params;
pMac->roam.configParam.edca_vo_cwmin = pParam->edca_vo_cwmin;
pMac->roam.configParam.edca_vi_cwmin = pParam->edca_vi_cwmin;
pMac->roam.configParam.edca_bk_cwmin = pParam->edca_bk_cwmin;
pMac->roam.configParam.edca_be_cwmin = pParam->edca_be_cwmin;
pMac->roam.configParam.edca_vo_cwmax = pParam->edca_vo_cwmax;
pMac->roam.configParam.edca_vi_cwmax = pParam->edca_vi_cwmax;
pMac->roam.configParam.edca_bk_cwmax = pParam->edca_bk_cwmax;
pMac->roam.configParam.edca_be_cwmax = pParam->edca_be_cwmax;
pMac->roam.configParam.edca_vo_aifs = pParam->edca_vo_aifs;
pMac->roam.configParam.edca_vi_aifs = pParam->edca_vi_aifs;
pMac->roam.configParam.edca_bk_aifs = pParam->edca_bk_aifs;
pMac->roam.configParam.edca_be_aifs = pParam->edca_be_aifs;
pMac->sta_sap_scc_on_dfs_chan = pParam->sta_sap_scc_on_dfs_chan;
pMac->force_scc_with_ecsa = pParam->force_scc_with_ecsa;
for (i = 0; i < 3; i++) {
pMac->roam.configParam.agg_btc_sco_oui[i] =
pParam->agg_btc_sco_oui[i];
}
pMac->roam.configParam.num_ba_buff_btc_sco =
pParam->num_ba_buff_btc_sco;
pMac->roam.configParam.num_ba_buff = pParam->num_ba_buff;
}
return status;
}
eHalStatus csrGetConfigParam(tpAniSirGlobal pMac, tCsrConfigParam *pParam)
{
eHalStatus status = eHAL_STATUS_INVALID_PARAMETER;
tANI_U8 i;
if(pParam)
{
pParam->WMMSupportMode = pMac->roam.configParam.WMMSupportMode;
pParam->Is11eSupportEnabled = pMac->roam.configParam.Is11eSupportEnabled;
pParam->FragmentationThreshold = pMac->roam.configParam.FragmentationThreshold;
pParam->Is11dSupportEnabled = pMac->roam.configParam.Is11dSupportEnabled;
pParam->Is11dSupportEnabledOriginal = pMac->roam.configParam.Is11dSupportEnabledOriginal;
pParam->Is11hSupportEnabled = pMac->roam.configParam.Is11hSupportEnabled;
pParam->channelBondingMode24GHz = csrConvertPhyCBStateToIniValue(pMac->roam.configParam.channelBondingMode24GHz);
#ifdef WLAN_FEATURE_AP_HT40_24G
pParam->channelBondingAPMode24GHz = csrConvertPhyCBStateToIniValue(pMac->roam.configParam.channelBondingAPMode24GHz);
#endif
pParam->channelBondingMode5GHz = csrConvertPhyCBStateToIniValue(pMac->roam.configParam.channelBondingMode5GHz);
pParam->RTSThreshold = pMac->roam.configParam.RTSThreshold;
pParam->phyMode = pMac->roam.configParam.phyMode;
pParam->shortSlotTime = pMac->roam.configParam.shortSlotTime;
pParam->HeartbeatThresh24 = pMac->roam.configParam.HeartbeatThresh24;
pParam->HeartbeatThresh50 = pMac->roam.configParam.HeartbeatThresh50;
pParam->ProprietaryRatesEnabled = pMac->roam.configParam.ProprietaryRatesEnabled;
pParam->TxRate = pMac->roam.configParam.TxRate;
pParam->AdHocChannel24 = pMac->roam.configParam.AdHocChannel24;
pParam->AdHocChannel5G = pMac->roam.configParam.AdHocChannel5G;
pParam->bandCapability = pMac->roam.configParam.bandCapability;
pParam->cbChoice = pMac->roam.configParam.cbChoice;
pParam->bgScanInterval = pMac->roam.configParam.bgScanInterval;
pParam->nActiveMaxChnTime = pMac->roam.configParam.nActiveMaxChnTime;
pParam->nActiveMinChnTime = pMac->roam.configParam.nActiveMinChnTime;
pParam->nPassiveMaxChnTime = pMac->roam.configParam.nPassiveMaxChnTime;
pParam->nPassiveMinChnTime = pMac->roam.configParam.nPassiveMinChnTime;
pParam->max_chntime_btc_esco =
pMac->roam.configParam.max_chntime_btc_esco;
pParam->min_chntime_btc_esco =
pMac->roam.configParam.min_chntime_btc_esco;
pParam->min_chntime_btc_sco =
pMac->roam.configParam.min_chntime_btc_sco;
pParam->max_chntime_btc_sco =
pMac->roam.configParam.max_chntime_btc_sco;
pParam->disableAggWithBtc = pMac->roam.configParam.disableAggWithBtc;
#ifdef WLAN_AP_STA_CONCURRENCY
pParam->nActiveMaxChnTimeConc = pMac->roam.configParam.nActiveMaxChnTimeConc;
pParam->nActiveMinChnTimeConc = pMac->roam.configParam.nActiveMinChnTimeConc;
pParam->nPassiveMaxChnTimeConc = pMac->roam.configParam.nPassiveMaxChnTimeConc;
pParam->nPassiveMinChnTimeConc = pMac->roam.configParam.nPassiveMinChnTimeConc;
pParam->nRestTimeConc = pMac->roam.configParam.nRestTimeConc;
pParam->nNumStaChanCombinedConc = pMac->roam.configParam.nNumStaChanCombinedConc;
pParam->nNumP2PChanCombinedConc = pMac->roam.configParam.nNumP2PChanCombinedConc;
#endif
//Change the unit from microsecond to second
pParam->impsSleepTime = pMac->roam.configParam.impsSleepTime / PAL_TIMER_TO_SEC_UNIT;
pParam->eBand = pMac->roam.configParam.eBand;
pParam->nScanResultAgeCount = pMac->roam.configParam.agingCount;
pParam->scanAgeTimeNCNPS = pMac->roam.configParam.scanAgeTimeNCNPS;
pParam->scanAgeTimeNCPS = pMac->roam.configParam.scanAgeTimeNCPS;
pParam->scanAgeTimeCNPS = pMac->roam.configParam.scanAgeTimeCNPS;
pParam->scanAgeTimeCPS = pMac->roam.configParam.scanAgeTimeCPS;
pParam->bCatRssiOffset = pMac->roam.configParam.bCatRssiOffset;
pParam->nRoamingTime = pMac->roam.configParam.nRoamingTime;
pParam->fEnforce11dChannels = pMac->roam.configParam.fEnforce11dChannels;
pParam->fSupplicantCountryCodeHasPriority = pMac->roam.configParam.fSupplicantCountryCodeHasPriority;
pParam->fEnforceCountryCodeMatch = pMac->roam.configParam.fEnforceCountryCodeMatch;
pParam->fEnforceDefaultDomain = pMac->roam.configParam.fEnforceDefaultDomain;
pParam->vccRssiThreshold = pMac->roam.configParam.vccRssiThreshold;
pParam->vccUlMacLossThreshold = pMac->roam.configParam.vccUlMacLossThreshold;
pParam->IsIdleScanEnabled = pMac->roam.configParam.IsIdleScanEnabled;
pParam->nTxPowerCap = pMac->roam.configParam.nTxPowerCap;
pParam->statsReqPeriodicity = pMac->roam.configParam.statsReqPeriodicity;
pParam->statsReqPeriodicityInPS = pMac->roam.configParam.statsReqPeriodicityInPS;
pParam->addTSWhenACMIsOff = pMac->roam.configParam.addTSWhenACMIsOff;
pParam->fValidateList = pMac->roam.configParam.fValidateList;
pParam->fEnableBypass11d = pMac->scan.fEnableBypass11d;
pParam->fEnableDFSChnlScan = pMac->scan.fEnableDFSChnlScan;
pParam->disable_scan_during_sco = pMac->scan.disable_scan_during_sco;
pParam->fScanTwice = pMac->roam.configParam.fScanTwice;
pParam->fFirstScanOnly2GChnl = pMac->scan.fFirstScanOnly2GChnl;
pParam->fEnableMCCMode = pMac->roam.configParam.fenableMCCMode;
pParam->fAllowMCCGODiffBI = pMac->roam.configParam.fAllowMCCGODiffBI;
pParam->scanCfgAgingTime = pMac->scan.scanResultCfgAgingTime;
pParam->scanBandPreference = pMac->scan.scanBandPreference;
#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
vos_mem_copy(&pParam->neighborRoamConfig,
&pMac->roam.configParam.neighborRoamConfig,
sizeof(tCsrNeighborRoamConfigParams));
#endif
#ifdef WLAN_FEATURE_11AC
pParam->nVhtChannelWidth = pMac->roam.configParam.nVhtChannelWidth;
pParam->enableTxBF = pMac->roam.configParam.txBFEnable;
pParam->txBFCsnValue = pMac->roam.configParam.txBFCsnValue;
pParam->enableVhtFor24GHz = pMac->roam.configParam.enableVhtFor24GHz;
/* Consider Mu-beamformee only if SU-beamformee is enabled */
if ( pParam->enableTxBF )
pParam->enableMuBformee = pMac->roam.configParam.txMuBformee;
else
pParam->enableMuBformee = 0;
#endif
#ifdef WLAN_FEATURE_VOWIFI_11R
vos_mem_copy(&pMac->roam.configParam.csr11rConfig,
&pParam->csr11rConfig, sizeof(tCsr11rConfigParams));
#endif
#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
pParam->isFastTransitionEnabled = pMac->roam.configParam.isFastTransitionEnabled;
pParam->RoamRssiDiff = pMac->roam.configParam.RoamRssiDiff;
pParam->nImmediateRoamRssiDiff = pMac->roam.configParam.nImmediateRoamRssiDiff;
pParam->nRoamPrefer5GHz = pMac->roam.configParam.nRoamPrefer5GHz;
pParam->nRoamIntraBand = pMac->roam.configParam.nRoamIntraBand;
pParam->isWESModeEnabled = pMac->roam.configParam.isWESModeEnabled;
pParam->nProbes = pMac->roam.configParam.nProbes;
pParam->nRoamScanHomeAwayTime = pMac->roam.configParam.nRoamScanHomeAwayTime;
#endif
#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
pParam->isRoamOffloadScanEnabled = pMac->roam.configParam.isRoamOffloadScanEnabled;
pParam->bFastRoamInConIniFeatureEnabled = pMac->roam.configParam.bFastRoamInConIniFeatureEnabled;
pParam->isPERRoamEnabled =
pMac->roam.configParam.isPERRoamEnabled;
pParam->rateUpThreshold = pMac->roam.configParam.rateUpThreshold;
pParam->rateDownThreshold = pMac->roam.configParam.rateDownThreshold;
pParam->waitPeriodForNextPERScan =
pMac->roam.configParam.waitPeriodForNextPERScan;
pParam->PERtimerThreshold = pMac->roam.configParam.PERtimerThreshold;
pParam->isPERRoamCCAEnabled =
pMac->roam.configParam.isPERRoamCCAEnabled;
pParam->PERRoamFullScanThreshold =
pMac->roam.configParam.PERRoamFullScanThreshold;
pParam->PERroamTriggerPercent =
pMac->roam.configParam.PERroamTriggerPercent;
pParam->PERMinRssiThresholdForRoam =
pMac->roam.configParam.PERMinRssiThresholdForRoam;
#endif
#ifdef WLAN_FEATURE_LFR_MBB
pParam->enable_lfr_mbb = pMac->roam.configParam.enable_lfr_mbb;
#endif
#ifdef FEATURE_WLAN_LFR
pParam->isFastRoamIniFeatureEnabled = pMac->roam.configParam.isFastRoamIniFeatureEnabled;
#endif
#ifdef FEATURE_WLAN_ESE
pParam->isEseIniFeatureEnabled = pMac->roam.configParam.isEseIniFeatureEnabled;
#endif
#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
vos_mem_copy(&pParam->neighborRoamConfig,
&pMac->roam.configParam.neighborRoamConfig,
sizeof(tCsrNeighborRoamConfigParams));
{
int i;
smsLog( pMac, LOG1, FL("Num of Channels in CFG Channel List: %d"), pMac->roam.configParam.neighborRoamConfig.neighborScanChanList.numChannels);
for( i=0; i< pMac->roam.configParam.neighborRoamConfig.neighborScanChanList.numChannels; i++)
{
smsLog( pMac, LOG1, "%d ", pMac->roam.configParam.neighborRoamConfig.neighborScanChanList.channelList[i] );
}
}
#endif
pParam->enableTxLdpc = pMac->roam.configParam.txLdpcEnable;
pParam->isAmsduSupportInAMPDU = pMac->roam.configParam.isAmsduSupportInAMPDU;
pParam->nSelect5GHzMargin = pMac->roam.configParam.nSelect5GHzMargin;
pParam->ignorePeerErpInfo = pMac->roam.configParam.ignorePeerErpInfo;
pParam->ignorePeerHTopMode = pMac->roam.configParam.ignorePeerHTopMode;
pParam->disableP2PMacSpoofing =
pMac->roam.configParam.disableP2PMacSpoofing;
pParam->enableFatalEvent = pMac->roam.configParam.enableFatalEvent;
pParam->isCoalesingInIBSSAllowed =
pMac->roam.configParam.isCoalesingInIBSSAllowed;
pParam->allowDFSChannelRoam =
pMac->roam.configParam.allowDFSChannelRoam;
pParam->sendDeauthBeforeCon = pMac->roam.configParam.sendDeauthBeforeCon;
csrSetChannels(pMac, pParam);
#ifdef WLAN_FEATURE_AP_HT40_24G
pParam->apHT40_24GEnabled = pMac->roam.configParam.apHT40_24GEnabled;
#endif
pParam->max_chan_for_dwell_time_cfg =
pMac->roam.configParam.max_chan_for_dwell_time_cfg;
pParam->enable_edca_params = pMac->roam.configParam.enable_edca_params;
pParam->edca_vo_cwmin = pMac->roam.configParam.edca_vo_cwmin;
pParam->edca_vi_cwmin = pMac->roam.configParam.edca_vi_cwmin;
pParam->edca_bk_cwmin = pMac->roam.configParam.edca_bk_cwmin;
pParam->edca_be_cwmin = pMac->roam.configParam.edca_be_cwmin;
pParam->edca_vo_cwmax = pMac->roam.configParam.edca_vo_cwmax;
pParam->edca_vi_cwmax = pMac->roam.configParam.edca_vi_cwmax;
pParam->edca_bk_cwmax = pMac->roam.configParam.edca_bk_cwmax;
pParam->edca_be_cwmax = pMac->roam.configParam.edca_be_cwmax;
pParam->edca_vo_aifs = pMac->roam.configParam.edca_vo_aifs;
pParam->edca_vi_aifs = pMac->roam.configParam.edca_vi_aifs;
pParam->edca_bk_aifs = pMac->roam.configParam.edca_bk_aifs;
pParam->edca_be_aifs = pMac->roam.configParam.edca_be_aifs;
pParam->sta_sap_scc_on_dfs_chan = pMac->sta_sap_scc_on_dfs_chan;
pParam->force_scc_with_ecsa = pMac->force_scc_with_ecsa;
for (i = 0; i < 3; i++) {
pParam->agg_btc_sco_oui[i] =
pMac->roam.configParam.agg_btc_sco_oui[i];
}
pParam->num_ba_buff_btc_sco =
pMac->roam.configParam.num_ba_buff_btc_sco;
pParam->num_ba_buff = pMac->roam.configParam.num_ba_buff;
status = eHAL_STATUS_SUCCESS;
}
return (status);
}
eHalStatus csrSetPhyMode(tHalHandle hHal, tANI_U32 phyMode, eCsrBand eBand, tANI_BOOLEAN *pfRestartNeeded)
{
eHalStatus status = eHAL_STATUS_INVALID_PARAMETER;
tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
tANI_BOOLEAN fRestartNeeded = eANI_BOOLEAN_FALSE;
eCsrPhyMode newPhyMode = eCSR_DOT11_MODE_AUTO;
do
{
if(eCSR_BAND_24 == eBand)
{
if(CSR_IS_RADIO_A_ONLY(pMac)) break;
if((eCSR_DOT11_MODE_11a & phyMode) || (eCSR_DOT11_MODE_11a_ONLY & phyMode)) break;
}
if(eCSR_BAND_5G == eBand)
{
if(CSR_IS_RADIO_BG_ONLY(pMac)) break;
if((eCSR_DOT11_MODE_11b & phyMode) || (eCSR_DOT11_MODE_11b_ONLY & phyMode) ||
(eCSR_DOT11_MODE_11g & phyMode) || (eCSR_DOT11_MODE_11g_ONLY & phyMode)
)
{
break;
}
}
if((0 == phyMode) || (eCSR_DOT11_MODE_TAURUS & phyMode))
{
newPhyMode = eCSR_DOT11_MODE_TAURUS;
}
else if(eCSR_DOT11_MODE_AUTO & phyMode)
{
newPhyMode = eCSR_DOT11_MODE_AUTO;
}
else
{
//Check for dual band and higher capability first
if(eCSR_DOT11_MODE_11n_ONLY & phyMode)
{
if(eCSR_DOT11_MODE_11n_ONLY != phyMode) break;
newPhyMode = eCSR_DOT11_MODE_11n_ONLY;
}
else if(eCSR_DOT11_MODE_11a_ONLY & phyMode)
{
if(eCSR_DOT11_MODE_11a_ONLY != phyMode) break;
if(eCSR_BAND_24 == eBand) break;
newPhyMode = eCSR_DOT11_MODE_11a_ONLY;
eBand = eCSR_BAND_5G;
}
else if(eCSR_DOT11_MODE_11g_ONLY & phyMode)
{
if(eCSR_DOT11_MODE_11g_ONLY != phyMode) break;
if(eCSR_BAND_5G == eBand) break;
newPhyMode = eCSR_DOT11_MODE_11g_ONLY;
eBand = eCSR_BAND_24;
}
else if(eCSR_DOT11_MODE_11b_ONLY & phyMode)
{
if(eCSR_DOT11_MODE_11b_ONLY != phyMode) break;
if(eCSR_BAND_5G == eBand) break;
newPhyMode = eCSR_DOT11_MODE_11b_ONLY;
eBand = eCSR_BAND_24;
}
else if(eCSR_DOT11_MODE_11n & phyMode)
{
newPhyMode = eCSR_DOT11_MODE_11n;
}
else if(eCSR_DOT11_MODE_abg & phyMode)
{
newPhyMode = eCSR_DOT11_MODE_abg;
}
else if(eCSR_DOT11_MODE_11a & phyMode)
{
if((eCSR_DOT11_MODE_11g & phyMode) || (eCSR_DOT11_MODE_11b & phyMode))
{
if(eCSR_BAND_ALL == eBand)
{
newPhyMode = eCSR_DOT11_MODE_abg;
}
else
{
//bad setting
break;
}
}
else
{
newPhyMode = eCSR_DOT11_MODE_11a;
eBand = eCSR_BAND_5G;
}
}
else if(eCSR_DOT11_MODE_11g & phyMode)
{
newPhyMode = eCSR_DOT11_MODE_11g;
eBand = eCSR_BAND_24;
}
else if(eCSR_DOT11_MODE_11b & phyMode)
{
newPhyMode = eCSR_DOT11_MODE_11b;
eBand = eCSR_BAND_24;
}
else
{
//We will never be here
smsLog( pMac, LOGE, FL(" cannot recognize the phy mode 0x%08X"), phyMode );
newPhyMode = eCSR_DOT11_MODE_AUTO;
}
}
//Done validating
status = eHAL_STATUS_SUCCESS;
//Now we need to check whether a restart is needed.
if(eBand != pMac->roam.configParam.eBand)
{
fRestartNeeded = eANI_BOOLEAN_TRUE;
break;
}
if(newPhyMode != pMac->roam.configParam.phyMode)
{
fRestartNeeded = eANI_BOOLEAN_TRUE;
break;
}
}while(0);
if(HAL_STATUS_SUCCESS(status))
{
pMac->roam.configParam.eBand = eBand;
pMac->roam.configParam.phyMode = newPhyMode;
if(pfRestartNeeded)
{
*pfRestartNeeded = fRestartNeeded;
}
}
return (status);
}
void csrPruneChannelListForMode( tpAniSirGlobal pMac, tCsrChannel *pChannelList )
{
tANI_U8 Index;
tANI_U8 cChannels;
// for dual band NICs, don't need to trim the channel list....
if ( !CSR_IS_OPEARTING_DUAL_BAND( pMac ) )
{
// 2.4 GHz band operation requires the channel list to be trimmed to
// the 2.4 GHz channels only...
if ( CSR_IS_24_BAND_ONLY( pMac ) )
{
for( Index = 0, cChannels = 0; Index < pChannelList->numChannels;
Index++ )
{
if ( CSR_IS_CHANNEL_24GHZ(pChannelList->channelList[ Index ]) )
{
pChannelList->channelList[ cChannels ] = pChannelList->channelList[ Index ];
cChannels++;
}
}
// Cleanup the rest of channels. Note we only need to clean up the channels if we had
// to trim the list. Calling palZeroMemory() with a 0 size is going to throw asserts on
// the debug builds so let's be a bit smarter about that. Zero out the reset of the channels
// only if we need to.
//
// The amount of memory to clear is the number of channesl that we trimmed
// (pChannelList->numChannels - cChannels) times the size of a channel in the structure.
if ( pChannelList->numChannels > cChannels )
{
vos_mem_set(&pChannelList->channelList[ cChannels ],
sizeof( pChannelList->channelList[ 0 ] ) *
( pChannelList->numChannels - cChannels ), 0);
}
pChannelList->numChannels = cChannels;
}
else if ( CSR_IS_5G_BAND_ONLY( pMac ) )
{
for ( Index = 0, cChannels = 0; Index < pChannelList->numChannels; Index++ )
{
if ( CSR_IS_CHANNEL_5GHZ(pChannelList->channelList[ Index ]) )
{
pChannelList->channelList[ cChannels ] = pChannelList->channelList[ Index ];
cChannels++;
}
}
// Cleanup the rest of channels. Note we only need to clean up the channels if we had
// to trim the list. Calling palZeroMemory() with a 0 size is going to throw asserts on
// the debug builds so let's be a bit smarter about that. Zero out the reset of the channels
// only if we need to.
//
// The amount of memory to clear is the number of channesl that we trimmed
// (pChannelList->numChannels - cChannels) times the size of a channel in the structure.
if ( pChannelList->numChannels > cChannels )
{
vos_mem_set(&pChannelList->channelList[ cChannels ],
sizeof( pChannelList->channelList[ 0 ] ) *
( pChannelList->numChannels - cChannels ), 0);
}
pChannelList->numChannels = cChannels;
}
}
}
#define INFRA_AP_DEFAULT_CHANNEL 6
eHalStatus csrIsValidChannel(tpAniSirGlobal pMac, tANI_U8 chnNum)
{
tANI_U8 index= 0;
eHalStatus status = eHAL_STATUS_FAILURE;
for (index=0; index < pMac->scan.base20MHzChannels.numChannels ;index++)
{
if(pMac->scan.base20MHzChannels.channelList[ index ] == chnNum){
status = eHAL_STATUS_SUCCESS;
break;
}
}
return status;
}
eHalStatus csrInitGetChannels(tpAniSirGlobal pMac)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tANI_U8 num20MHzChannelsFound = 0;
VOS_STATUS vosStatus;
tANI_U8 Index = 0;
tANI_U8 num40MHzChannelsFound = 0;
//TODO: this interface changed to include the 40MHz channel list
// this needs to be tied into the adapter structure somehow and referenced appropriately for CB operation
// Read the scan channel list (including the power limit) from EEPROM
vosStatus = vos_nv_getChannelListWithPower( pMac->scan.defaultPowerTable, &num20MHzChannelsFound,
pMac->scan.defaultPowerTable40MHz, &num40MHzChannelsFound);
if ( (VOS_STATUS_SUCCESS != vosStatus) || (num20MHzChannelsFound == 0) )
{
smsLog( pMac, LOGE, FL("failed to get channels "));
status = eHAL_STATUS_FAILURE;
}
else
{
if ( num20MHzChannelsFound > WNI_CFG_VALID_CHANNEL_LIST_LEN )
{
num20MHzChannelsFound = WNI_CFG_VALID_CHANNEL_LIST_LEN;
}
pMac->scan.numChannelsDefault = num20MHzChannelsFound;
// Move the channel list to the global data
// structure -- this will be used as the scan list
for ( Index = 0; Index < num20MHzChannelsFound; Index++)
{
pMac->scan.base20MHzChannels.channelList[ Index ] = pMac->scan.defaultPowerTable[ Index ].chanId;
}
pMac->scan.base20MHzChannels.numChannels = num20MHzChannelsFound;
if(num40MHzChannelsFound > WNI_CFG_VALID_CHANNEL_LIST_LEN)
{
num40MHzChannelsFound = WNI_CFG_VALID_CHANNEL_LIST_LEN;
}
for ( Index = 0; Index < num40MHzChannelsFound; Index++)
{
pMac->scan.base40MHzChannels.channelList[ Index ] = pMac->scan.defaultPowerTable40MHz[ Index ].chanId;
}
pMac->scan.base40MHzChannels.numChannels = num40MHzChannelsFound;
}
return (status);
}
eHalStatus csrInitChannelList( tHalHandle hHal )
{
tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
eHalStatus status = eHAL_STATUS_SUCCESS;
csrPruneChannelListForMode(pMac, &pMac->scan.baseChannels);
csrPruneChannelListForMode(pMac, &pMac->scan.base20MHzChannels);
csrSaveChannelPowerForBand(pMac, eANI_BOOLEAN_FALSE);
csrSaveChannelPowerForBand(pMac, eANI_BOOLEAN_TRUE);
// Apply the base channel list, power info, and set the Country code...
csrApplyChannelPowerCountryInfo( pMac, &pMac->scan.base20MHzChannels, pMac->scan.countryCodeCurrent, eANI_BOOLEAN_TRUE );
limInitOperatingClasses(hHal);
return (status);
}
eHalStatus csrChangeConfigParams(tpAniSirGlobal pMac,
tCsrUpdateConfigParam *pUpdateConfigParam)
{
eHalStatus status = eHAL_STATUS_FAILURE;
tCsr11dinfo *ps11dinfo = NULL;
ps11dinfo = &pUpdateConfigParam->Csr11dinfo;
status = CsrInit11dInfo(pMac, ps11dinfo);
return status;
}
static eHalStatus CsrInit11dInfo(tpAniSirGlobal pMac, tCsr11dinfo *ps11dinfo)
{
eHalStatus status = eHAL_STATUS_FAILURE;
tANI_U8 index;
tANI_U32 count=0;
tSirMacChanInfo *pChanInfo;
tSirMacChanInfo *pChanInfoStart;
tANI_BOOLEAN applyConfig = TRUE;
pMac->scan.currentCountryRSSI = -128;
if(!ps11dinfo)
{
return (status);
}
if ( ps11dinfo->Channels.numChannels && ( WNI_CFG_VALID_CHANNEL_LIST_LEN >= ps11dinfo->Channels.numChannels ) )
{
pMac->scan.base20MHzChannels.numChannels = ps11dinfo->Channels.numChannels;
vos_mem_copy(pMac->scan.base20MHzChannels.channelList,
ps11dinfo->Channels.channelList,
ps11dinfo->Channels.numChannels);
}
else
{
//No change
return (eHAL_STATUS_SUCCESS);
}
//legacy maintenance
vos_mem_copy(pMac->scan.countryCodeDefault, ps11dinfo->countryCode,
WNI_CFG_COUNTRY_CODE_LEN);
//Tush: at csropen get this initialized with default, during csr reset if this
// already set with some value no need initilaize with default again
if(0 == pMac->scan.countryCodeCurrent[0])
{
vos_mem_copy(pMac->scan.countryCodeCurrent, ps11dinfo->countryCode,
WNI_CFG_COUNTRY_CODE_LEN);
}
// need to add the max power channel list
pChanInfo = vos_mem_malloc(sizeof(tSirMacChanInfo) * WNI_CFG_VALID_CHANNEL_LIST_LEN);
if (pChanInfo != NULL)
{
vos_mem_set(pChanInfo,
sizeof(tSirMacChanInfo) * WNI_CFG_VALID_CHANNEL_LIST_LEN ,
0);
pChanInfoStart = pChanInfo;
for(index = 0; index < ps11dinfo->Channels.numChannels; index++)
{
pChanInfo->firstChanNum = ps11dinfo->ChnPower[index].firstChannel;
pChanInfo->numChannels = ps11dinfo->ChnPower[index].numChannels;
pChanInfo->maxTxPower = CSR_ROAM_MIN( ps11dinfo->ChnPower[index].maxtxPower, pMac->roam.configParam.nTxPowerCap );
pChanInfo++;
count++;
}
if(count)
{
csrSaveToChannelPower2G_5G( pMac, count * sizeof(tSirMacChanInfo), pChanInfoStart );
}
vos_mem_free(pChanInfoStart);
}
//Only apply them to CFG when not in STOP state. Otherwise they will be applied later
if( HAL_STATUS_SUCCESS(status) )
{
for( index = 0; index < CSR_ROAM_SESSION_MAX; index++ )
{
if((CSR_IS_SESSION_VALID(pMac, index)) && CSR_IS_ROAM_STOP(pMac, index))
{
applyConfig = FALSE;
}
}
if(TRUE == applyConfig)
{
// Apply the base channel list, power info, and set the Country code...
csrApplyChannelPowerCountryInfo( pMac, &pMac->scan.base20MHzChannels, pMac->scan.countryCodeCurrent, eANI_BOOLEAN_TRUE );
}
}
return (status);
}
/* Initialize the Channel + Power List in the local cache and in the CFG */
eHalStatus csrInitChannelPowerList( tpAniSirGlobal pMac, tCsr11dinfo *ps11dinfo)
{
tANI_U8 index;
tANI_U32 count=0;
tSirMacChanInfo *pChanInfo;
tSirMacChanInfo *pChanInfoStart;
if(!ps11dinfo || !pMac)
{
return eHAL_STATUS_FAILURE;
}
pChanInfo = vos_mem_malloc(sizeof(tSirMacChanInfo) * WNI_CFG_VALID_CHANNEL_LIST_LEN);
if (pChanInfo != NULL)
{
vos_mem_set(pChanInfo,
sizeof(tSirMacChanInfo) * WNI_CFG_VALID_CHANNEL_LIST_LEN,
0);
pChanInfoStart = pChanInfo;
for(index = 0; index < ps11dinfo->Channels.numChannels; index++)
{
pChanInfo->firstChanNum = ps11dinfo->ChnPower[index].firstChannel;
pChanInfo->numChannels = ps11dinfo->ChnPower[index].numChannels;
pChanInfo->maxTxPower = CSR_ROAM_MIN( ps11dinfo->ChnPower[index].maxtxPower, pMac->roam.configParam.nTxPowerCap );
pChanInfo++;
count++;
}
if(count)
{
csrSaveToChannelPower2G_5G( pMac, count * sizeof(tSirMacChanInfo), pChanInfoStart );
}
vos_mem_free(pChanInfoStart);
}
return eHAL_STATUS_SUCCESS;
}
/**
* csr_roam_remove_duplicate_cmd_from_list()- Remove duplicate roam cmd from
* list
*
* @pMac: pointer to global mac
* @sessionId: session id for the cmd
* @pList: pending list from which cmd needs to be removed
* @pCommand: cmd to be removed, can be NULL
* @eRoamReason: cmd with reason to be removed
*
* Remove duplicate command from the pending list.
*
* Return: void
*/
void csr_roam_remove_duplicate_cmd_from_list(tpAniSirGlobal pMac,
tANI_U32 sessionId, tDblLinkList *pList,
tSmeCmd *pCommand, eCsrRoamReason eRoamReason)
{
tListElem *pEntry, *pNextEntry;
tSmeCmd *pDupCommand;
tDblLinkList localList;
vos_mem_zero(&localList, sizeof(tDblLinkList));
if (!HAL_STATUS_SUCCESS(csrLLOpen(pMac->hHdd, &localList)))
{
smsLog(pMac, LOGE, FL("failed to open list"));
return;
}
csrLLLock(pList);
pEntry = csrLLPeekHead(pList, LL_ACCESS_NOLOCK);
while (pEntry)
{
pNextEntry = csrLLNext(pList, pEntry, LL_ACCESS_NOLOCK);
pDupCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
/*
* If pCommand is not NULL remove the similar duplicate cmd for same
* reason as pCommand. If pCommand is NULL then check if eRoamReason is
* eCsrForcedDisassoc (disconnect) and remove all roam command for the
* sessionId, else if eRoamReason is eCsrHddIssued (connect) remove all
* connect (non disconenct) commands.
*/
if ((pCommand && (pCommand->sessionId == pDupCommand->sessionId) &&
((pCommand->command == pDupCommand->command) &&
/*
* This peermac check is requried for Softap/GO scenarios
* For STA scenario below OR check will suffice as pCommand
* will always be NULL for STA scenarios
*/
(vos_mem_compare(pDupCommand->u.roamCmd.peerMac,
pCommand->u.roamCmd.peerMac, sizeof(v_MACADDR_t))) &&
((pCommand->u.roamCmd.roamReason ==
pDupCommand->u.roamCmd.roamReason) ||
(eCsrForcedDisassoc == pCommand->u.roamCmd.roamReason) ||
(eCsrHddIssued == pCommand->u.roamCmd.roamReason)))) ||
/* OR if pCommand is NULL */
((sessionId == pDupCommand->sessionId) &&
(eSmeCommandRoam == pDupCommand->command) &&
((eCsrForcedDisassoc == eRoamReason) ||
(eCsrHddIssued == eRoamReason &&
!CSR_IS_DISCONNECT_COMMAND(pDupCommand)))))
{
smsLog(pMac, LOGW, FL("RoamReason = %d"),
pDupCommand->u.roamCmd.roamReason);
/* Remove the 'stale' roam command from the pending list */
if (csrLLRemoveEntry(pList, pEntry, LL_ACCESS_NOLOCK))
csrLLInsertTail(&localList, pEntry, LL_ACCESS_NOLOCK);
}
pEntry = pNextEntry;
}
csrLLUnlock(pList);
while ((pEntry = csrLLRemoveHead(&localList, LL_ACCESS_NOLOCK)))
{
pDupCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link );
/* Tell caller that the command is cancelled */
csrRoamCallCallback(pMac, pDupCommand->sessionId, NULL,
pDupCommand->u.roamCmd.roamId,
eCSR_ROAM_CANCELLED, eCSR_ROAM_RESULT_NONE);
csrReleaseCommandRoam(pMac, pDupCommand);
}
csrLLClose(&localList);
}
/**
* csrRoamRemoveDuplicateCommand()- Remove duplicate roam cmd
* from pending lists.
*
* @pMac: pointer to global mac
* @sessionId: session id for the cmd
* @pCommand: cmd to be removed, can be null
* @eRoamReason: cmd with reason to be removed
*
* Remove duplicate command from the sme and roam pending list.
*
* Return: void
*/
void csrRoamRemoveDuplicateCommand(tpAniSirGlobal pMac,
tANI_U32 sessionId, tSmeCmd *pCommand,
eCsrRoamReason eRoamReason)
{
/* Always lock active list before locking pending lists */
csrLLLock(&pMac->sme.smeCmdActiveList);
csr_roam_remove_duplicate_cmd_from_list(pMac,
sessionId, &pMac->sme.smeCmdPendingList,
pCommand, eRoamReason);
csr_roam_remove_duplicate_cmd_from_list(pMac,
sessionId, &pMac->roam.roamCmdPendingList,
pCommand, eRoamReason);
csrLLUnlock(&pMac->sme.smeCmdActiveList);
}
eHalStatus csrRoamCallCallback(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamInfo *pRoamInfo,
tANI_U32 roamId, eRoamCmdStatus u1, eCsrRoamResult u2)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
WLAN_VOS_DIAG_EVENT_DEF(connectionStatus, vos_event_wlan_status_payload_type);
#endif
tCsrRoamSession *pSession = NULL;
if( CSR_IS_SESSION_VALID( pMac, sessionId) )
{
pSession = CSR_GET_SESSION( pMac, sessionId );
}
else
{
smsLog(pMac, LOGE, "Session ID:%d is not valid", sessionId);
VOS_ASSERT(0);
return eHAL_STATUS_FAILURE;
}
if (eANI_BOOLEAN_FALSE == pSession->sessionActive)
{
smsLog(pMac, LOG1, "%s Session is not Active", __func__);
return eHAL_STATUS_FAILURE;
}
smsLog(pMac, LOG4, "Recieved RoamCmdStatus %d with Roam Result %d", u1, u2);
if(eCSR_ROAM_ASSOCIATION_COMPLETION == u1 && pRoamInfo)
{
smsLog(pMac, LOGW, " Assoc complete result = %d statusCode = %d reasonCode = %d", u2, pRoamInfo->statusCode, pRoamInfo->reasonCode);
}
if ((u1 == eCSR_ROAM_FT_REASSOC_FAILED) && (pSession->bRefAssocStartCnt)) {
/*
* Decrement bRefAssocStartCnt for FT reassoc failure.
* Reason: For FT reassoc failures, we first call
* csrRoamCallCallback before notifying a failed roam
* completion through csrRoamComplete. The latter in
* turn calls csrRoamProcessResults which tries to
* once again call csrRoamCallCallback if bRefAssocStartCnt
* is non-zero. Since this is redundant for FT reassoc
* failure, decrement bRefAssocStartCnt.
*/
pSession->bRefAssocStartCnt--;
} else if (u1 == eCSR_ROAM_ECSA_CHAN_CHANGE_RSP && u2 ==
eCSR_ROAM_RESULT_NONE)
pSession->connectedProfile.operationChannel =
pRoamInfo->ap_chan_change_rsp->new_channel;
if (eCSR_ROAM_RESULT_LOSTLINK == u2 ||
eCSR_ROAM_LOSTLINK_DETECTED == u1)
smsLog(pMac, LOG1, "eCSR_ROAM_RESULT_LOSTLINK ");
if(NULL != pSession->callback)
{
if( pRoamInfo )
{
pRoamInfo->sessionId = (tANI_U8)sessionId;
}
/* avoid holding the global lock when making the roaming callback, original change came
from a raised CR (CR304874). Since this callback is in HDD a potential deadlock
is possible on other OS ports where the callback may need to take locks to protect
HDD state
UPDATE : revert this change but keep the comments here. Need to revisit as there are callbacks
that may actually depend on the lock being held */
// TODO: revisit: sme_ReleaseGlobalLock( &pMac->sme );
status = pSession->callback(pSession->pContext, pRoamInfo, roamId, u1, u2);
// TODO: revisit: sme_AcquireGlobalLock( &pMac->sme );
}
//EVENT_WLAN_STATUS_V2: eCSR_ROAM_ASSOCIATION_COMPLETION,
// eCSR_ROAM_LOSTLINK, eCSR_ROAM_DISASSOCIATED,
#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
vos_mem_set(&connectionStatus,
sizeof(vos_event_wlan_status_payload_type), 0);
if((eCSR_ROAM_ASSOCIATION_COMPLETION == u1) && (eCSR_ROAM_RESULT_ASSOCIATED == u2) && pRoamInfo)
{
connectionStatus.eventId = eCSR_WLAN_STATUS_CONNECT;
connectionStatus.bssType = pRoamInfo->u.pConnectedProfile->BSSType;
if(NULL != pRoamInfo->pBssDesc)
{
connectionStatus.rssi = pRoamInfo->pBssDesc->rssi * (-1);
connectionStatus.channel = pRoamInfo->pBssDesc->channelId;
}
connectionStatus.qosCapability = pRoamInfo->u.pConnectedProfile->qosConnection;
connectionStatus.authType = (v_U8_t)diagAuthTypeFromCSRType(pRoamInfo->u.pConnectedProfile->AuthType);
connectionStatus.encryptionType = (v_U8_t)diagEncTypeFromCSRType(pRoamInfo->u.pConnectedProfile->EncryptionType);
vos_mem_copy(connectionStatus.ssid,
pRoamInfo->u.pConnectedProfile->SSID.ssId,
pRoamInfo->u.pConnectedProfile->SSID.length);
connectionStatus.reason = eCSR_REASON_UNSPECIFIED;
WLAN_VOS_DIAG_EVENT_REPORT(&connectionStatus, EVENT_WLAN_STATUS_V2);
}
if((eCSR_ROAM_MIC_ERROR_IND == u1) || (eCSR_ROAM_RESULT_MIC_FAILURE == u2))
{
connectionStatus.eventId = eCSR_WLAN_STATUS_DISCONNECT;
connectionStatus.reason = eCSR_REASON_MIC_ERROR;
WLAN_VOS_DIAG_EVENT_REPORT(&connectionStatus, EVENT_WLAN_STATUS_V2);
}
if(eCSR_ROAM_RESULT_FORCED == u2)
{
connectionStatus.eventId = eCSR_WLAN_STATUS_DISCONNECT;
connectionStatus.reason = eCSR_REASON_USER_REQUESTED;
WLAN_VOS_DIAG_EVENT_REPORT(&connectionStatus, EVENT_WLAN_STATUS_V2);
}
if(eCSR_ROAM_RESULT_DISASSOC_IND == u2)
{
connectionStatus.eventId = eCSR_WLAN_STATUS_DISCONNECT;
connectionStatus.reason = eCSR_REASON_DISASSOC;
WLAN_VOS_DIAG_EVENT_REPORT(&connectionStatus, EVENT_WLAN_STATUS_V2);
}
if(eCSR_ROAM_RESULT_DEAUTH_IND == u2)
{
connectionStatus.eventId = eCSR_WLAN_STATUS_DISCONNECT;
connectionStatus.reason = eCSR_REASON_DEAUTH;
WLAN_VOS_DIAG_EVENT_REPORT(&connectionStatus, EVENT_WLAN_STATUS_V2);
}
#endif //FEATURE_WLAN_DIAG_SUPPORT_CSR
return (status);
}
// Returns whether handoff is currently in progress or not
tANI_BOOLEAN csrRoamIsHandoffInProgress(tpAniSirGlobal pMac)
{
#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
return csrNeighborRoamIsHandoffInProgress(pMac);
#else
return eANI_BOOLEAN_FALSE;
#endif
}
eHalStatus csrRoamIssueDisassociate( tpAniSirGlobal pMac, tANI_U32 sessionId,
eCsrRoamSubState NewSubstate, tANI_BOOLEAN fMICFailure )
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tCsrBssid bssId = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
tANI_U16 reasonCode;
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return eHAL_STATUS_FAILURE;
}
//Restore AC weight in case we change it
if ( csrIsConnStateConnectedInfra( pMac, sessionId ) )
{
smsLog(pMac, LOG1, FL(" restore AC weights (%d-%d-%d-%d)"), pMac->roam.ucACWeights[0], pMac->roam.ucACWeights[1],
pMac->roam.ucACWeights[2], pMac->roam.ucACWeights[3]);
WLANTL_SetACWeights(pMac->roam.gVosContext, pMac->roam.ucACWeights);
}
if ( fMICFailure )
{
reasonCode = eSIR_MAC_MIC_FAILURE_REASON;
}
else if (NewSubstate == eCSR_ROAM_SUBSTATE_DISASSOC_HANDOFF)
{
reasonCode = eSIR_MAC_DISASSOC_DUE_TO_FTHANDOFF_REASON;
}
else
{
reasonCode = eSIR_MAC_UNSPEC_FAILURE_REASON;
}
#ifdef WLAN_FEATURE_VOWIFI_11R
if ( (csrRoamIsHandoffInProgress(pMac)) &&
(NewSubstate != eCSR_ROAM_SUBSTATE_DISASSOC_HANDOFF))
{
tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo;
vos_mem_copy(&bssId,
pNeighborRoamInfo->csrNeighborRoamProfile.BSSIDs.bssid,
sizeof(tSirMacAddr));
}
else
#endif
if(pSession->pConnectBssDesc)
{
vos_mem_copy(&bssId, pSession->pConnectBssDesc->bssId, sizeof(tCsrBssid));
}
smsLog(pMac, LOG2, FL("CSR Attempting to Disassociate Bssid="MAC_ADDRESS_STR
" subState = %s reason=%d"),
MAC_ADDR_ARRAY(bssId), macTraceGetcsrRoamSubState(NewSubstate),
reasonCode);
csrRoamSubstateChange( pMac, NewSubstate, sessionId);
status = csrSendMBDisassocReqMsg( pMac, sessionId, bssId, reasonCode );
if(HAL_STATUS_SUCCESS(status))
{
csrRoamLinkDown(pMac, sessionId);
#ifndef WLAN_MDM_CODE_REDUCTION_OPT
//no need to tell QoS that we are disassociating, it will be taken care off in assoc req for HO
if(eCSR_ROAM_SUBSTATE_DISASSOC_HANDOFF != NewSubstate)
{
//notify QoS module that disassoc happening
sme_QosCsrEventInd(pMac, (v_U8_t)sessionId, SME_QOS_CSR_DISCONNECT_REQ, NULL);
}
#endif
}
else
{
smsLog(pMac, LOGW, FL("csrSendMBDisassocReqMsg failed with status %d"), status);
}
return (status);
}
/* ---------------------------------------------------------------------------
\fn csrRoamIssueDisassociateStaCmd
\brief csr function that HDD calls to disassociate a associated station
\param sessionId - session Id for Soft AP
\param pPeerMacAddr - MAC of associated station to delete
\param reason - reason code, be one of the tSirMacReasonCodes
\return eHalStatus
---------------------------------------------------------------------------*/
eHalStatus csrRoamIssueDisassociateStaCmd( tpAniSirGlobal pMac,
tANI_U32 sessionId,
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0))
const tANI_U8 *pPeerMacAddr,
#else
tANI_U8 *pPeerMacAddr,
#endif
tANI_U32 reason)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tSmeCmd *pCommand;
do
{
pCommand = csrGetCommandBuffer( pMac );
if ( !pCommand )
{
smsLog( pMac, LOGE, FL(" fail to get command buffer") );
status = eHAL_STATUS_RESOURCES;
break;
}
pCommand->command = eSmeCommandRoam;
pCommand->sessionId = (tANI_U8)sessionId;
pCommand->u.roamCmd.roamReason = eCsrForcedDisassocSta;
vos_mem_copy(pCommand->u.roamCmd.peerMac, pPeerMacAddr, 6);
pCommand->u.roamCmd.reason = (tSirMacReasonCodes)reason;
status = csrQueueSmeCommand(pMac, pCommand, eANI_BOOLEAN_FALSE);
if( !HAL_STATUS_SUCCESS( status ) )
{
smsLog( pMac, LOGE, FL(" fail to send message status = %d"), status );
csrReleaseCommandRoam( pMac, pCommand );
}
}while(0);
return status;
}
/* ---------------------------------------------------------------------------
\fn csrRoamIssueDeauthSta
\brief csr function that HDD calls to delete a associated station
\param sessionId - session Id for Soft AP
\param pDelStaParams- Pointer to parameters of the station to deauthenticate
\return eHalStatus
---------------------------------------------------------------------------*/
eHalStatus csrRoamIssueDeauthStaCmd( tpAniSirGlobal pMac,
tANI_U32 sessionId,
struct tagCsrDelStaParams *pDelStaParams)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tSmeCmd *pCommand;
do
{
pCommand = csrGetCommandBuffer( pMac );
if ( !pCommand )
{
smsLog( pMac, LOGE, FL(" fail to get command buffer") );
status = eHAL_STATUS_RESOURCES;
break;
}
pCommand->command = eSmeCommandRoam;
pCommand->sessionId = (tANI_U8)sessionId;
pCommand->u.roamCmd.roamReason = eCsrForcedDeauthSta;
vos_mem_copy(pCommand->u.roamCmd.peerMac, pDelStaParams->peerMacAddr,
sizeof(tSirMacAddr));
pCommand->u.roamCmd.reason =
(tSirMacReasonCodes)pDelStaParams->reason_code;
status = csrQueueSmeCommand(pMac, pCommand, eANI_BOOLEAN_FALSE);
if( !HAL_STATUS_SUCCESS( status ) )
{
smsLog( pMac, LOGE, FL(" fail to send message status = %d"), status );
csrReleaseCommandRoam( pMac, pCommand );
}
}while(0);
return status;
}
eHalStatus
csrRoamIssueTkipCounterMeasures( tpAniSirGlobal pMac, tANI_U32 sessionId,
tANI_BOOLEAN bEnable )
{
eHalStatus status = eHAL_STATUS_FAILURE;
tCsrBssid bssId = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
if (!pSession)
{
smsLog( pMac, LOGE, "csrRoamIssueTkipCounterMeasures:CSR Session not found");
return (status);
}
if (pSession->pConnectBssDesc)
{
vos_mem_copy(&bssId, pSession->pConnectBssDesc->bssId, sizeof(tCsrBssid));
}
else
{
smsLog( pMac, LOGE, "csrRoamIssueTkipCounterMeasures:Connected BSS Description in CSR Session not found");
return (status);
}
smsLog( pMac, LOG2, "CSR issuing tkip counter measures for Bssid = "MAC_ADDRESS_STR", Enable = %d",
MAC_ADDR_ARRAY(bssId), bEnable);
status = csrSendMBTkipCounterMeasuresReqMsg( pMac, sessionId, bEnable, bssId );
return (status);
}
eHalStatus
csrRoamGetAssociatedStas( tpAniSirGlobal pMac, tANI_U32 sessionId,
VOS_MODULE_ID modId, void *pUsrContext,
void *pfnSapEventCallback, v_U8_t *pAssocStasBuf )
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tCsrBssid bssId = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
if (!pSession)
{
smsLog( pMac, LOGE, "csrRoamGetAssociatedStas:CSR Session not found");
return (status);
}
if(pSession->pConnectBssDesc)
{
vos_mem_copy(&bssId, pSession->pConnectBssDesc->bssId, sizeof(tCsrBssid));
}
else
{
smsLog( pMac, LOGE, "csrRoamGetAssociatedStas:Connected BSS Description in CSR Session not found");
return (status);
}
smsLog( pMac, LOG2, "CSR getting associated stations for Bssid = "MAC_ADDRESS_STR,
MAC_ADDR_ARRAY(bssId));
status = csrSendMBGetAssociatedStasReqMsg( pMac, sessionId, modId, bssId, pUsrContext, pfnSapEventCallback, pAssocStasBuf );
return (status);
}
eHalStatus
csrRoamGetWpsSessionOverlap( tpAniSirGlobal pMac, tANI_U32 sessionId,
void *pUsrContext, void *pfnSapEventCallback, v_MACADDR_t pRemoveMac )
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tCsrBssid bssId = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
if (!pSession)
{
smsLog( pMac, LOGE, "csrRoamGetWpsSessionOverlap:CSR Session not found");
return (status);
}
if(pSession->pConnectBssDesc)
{
vos_mem_copy(&bssId, pSession->pConnectBssDesc->bssId, sizeof(tCsrBssid));
}
else
{
smsLog( pMac, LOGE, "csrRoamGetWpsSessionOverlap:Connected BSS Description in CSR Session not found");
return (status);
}
smsLog( pMac, LOG2, "CSR getting WPS Session Overlap for Bssid = "MAC_ADDRESS_STR,
MAC_ADDR_ARRAY(bssId));
status = csrSendMBGetWPSPBCSessions( pMac, sessionId, bssId, pUsrContext, pfnSapEventCallback, pRemoveMac);
return (status);
}
eHalStatus csrRoamIssueDeauth( tpAniSirGlobal pMac, tANI_U32 sessionId, eCsrRoamSubState NewSubstate )
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tCsrBssid bssId = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
if (!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return eHAL_STATUS_FAILURE;
}
if(pSession->pConnectBssDesc)
{
vos_mem_copy(&bssId, pSession->pConnectBssDesc->bssId, sizeof(tCsrBssid));
}
smsLog( pMac, LOG2, "CSR Attempting to Deauth Bssid= "MAC_ADDRESS_STR,
MAC_ADDR_ARRAY(bssId));
csrRoamSubstateChange( pMac, NewSubstate, sessionId);
status = csrSendMBDeauthReqMsg( pMac, sessionId, bssId, eSIR_MAC_DEAUTH_LEAVING_BSS_REASON );
if(HAL_STATUS_SUCCESS(status))
{
csrRoamLinkDown(pMac, sessionId);
}
else
{
smsLog(pMac, LOGE, FL("csrSendMBDeauthReqMsg failed with status %d Session ID: %d"
MAC_ADDRESS_STR ), status, sessionId, MAC_ADDR_ARRAY(bssId));
}
return (status);
}
eHalStatus csrRoamSaveConnectedBssDesc( tpAniSirGlobal pMac, tANI_U32 sessionId, tSirBssDescription *pBssDesc )
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
tANI_U32 size;
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return eHAL_STATUS_FAILURE;
}
// If no BSS description was found in this connection (happens with start IBSS), then
// nix the BSS description that we keep around for the connected BSS) and get out...
if(NULL == pBssDesc)
{
csrFreeConnectBssDesc(pMac, sessionId);
}
else
{
size = pBssDesc->length + sizeof( pBssDesc->length );
if(NULL != pSession->pConnectBssDesc)
{
if(((pSession->pConnectBssDesc->length) + sizeof(pSession->pConnectBssDesc->length)) < size)
{
//not enough room for the new BSS, pMac->roam.pConnectBssDesc is freed inside
csrFreeConnectBssDesc(pMac, sessionId);
}
}
if(NULL == pSession->pConnectBssDesc)
{
pSession->pConnectBssDesc = vos_mem_malloc(size);
}
if (NULL == pSession->pConnectBssDesc)
status = eHAL_STATUS_FAILURE;
else
vos_mem_copy(pSession->pConnectBssDesc, pBssDesc, size);
}
return (status);
}
eHalStatus csrRoamPrepareBssConfig(tpAniSirGlobal pMac, tCsrRoamProfile *pProfile,
tSirBssDescription *pBssDesc, tBssConfigParam *pBssConfig,
tDot11fBeaconIEs *pIes)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
eCsrCfgDot11Mode cfgDot11Mode;
VOS_ASSERT( pIes != NULL );
if (pIes == NULL)
return eHAL_STATUS_FAILURE;
do
{
vos_mem_copy(&pBssConfig->BssCap, &pBssDesc->capabilityInfo,
sizeof(tSirMacCapabilityInfo));
//get qos
pBssConfig->qosType = csrGetQoSFromBssDesc(pMac, pBssDesc, pIes);
//get SSID
if(pIes->SSID.present)
{
vos_mem_copy(&pBssConfig->SSID.ssId, pIes->SSID.ssid, pIes->SSID.num_ssid);
pBssConfig->SSID.length = pIes->SSID.num_ssid;
}
else
pBssConfig->SSID.length = 0;
if(csrIsNULLSSID(pBssConfig->SSID.ssId, pBssConfig->SSID.length))
{
smsLog(pMac, LOGW, " BSS desc SSID is a wildcard");
//Return failed if profile doesn't have an SSID either.
if(pProfile->SSIDs.numOfSSIDs == 0)
{
smsLog(pMac, LOGW, " Both BSS desc and profile doesn't have SSID");
status = eHAL_STATUS_FAILURE;
break;
}
}
if(CSR_IS_CHANNEL_5GHZ(pBssDesc->channelId))
{
pBssConfig->eBand = eCSR_BAND_5G;
}
else
{
pBssConfig->eBand = eCSR_BAND_24;
}
//phymode
if(csrIsPhyModeMatch( pMac, pProfile->phyMode, pBssDesc, pProfile, &cfgDot11Mode, pIes ))
{
pBssConfig->uCfgDot11Mode = cfgDot11Mode;
}
else
{
smsLog(pMac, LOGW, " Can not find match phy mode");
//force it
if(eCSR_BAND_24 == pBssConfig->eBand)
{
pBssConfig->uCfgDot11Mode = eCSR_CFG_DOT11_MODE_11G;
}
else
{
pBssConfig->uCfgDot11Mode = eCSR_CFG_DOT11_MODE_11A;
}
}
smsLog(pMac, LOG1, FL("phyMode %d uCfgDot11Mode %d"),
pProfile->phyMode, pBssConfig->uCfgDot11Mode);
//Qos
if ((pBssConfig->uCfgDot11Mode != eCSR_CFG_DOT11_MODE_11N) &&
(pMac->roam.configParam.WMMSupportMode == eCsrRoamWmmNoQos))
{
//Joining BSS is not 11n capable and WMM is disabled on client.
//Disable QoS and WMM
pBssConfig->qosType = eCSR_MEDIUM_ACCESS_DCF;
}
if (((pBssConfig->uCfgDot11Mode == eCSR_CFG_DOT11_MODE_11N) ||
(pBssConfig->uCfgDot11Mode == eCSR_CFG_DOT11_MODE_11AC)) &&
((pBssConfig->qosType != eCSR_MEDIUM_ACCESS_WMM_eDCF_DSCP) ||
(pBssConfig->qosType != eCSR_MEDIUM_ACCESS_11e_HCF) ||
(pBssConfig->qosType != eCSR_MEDIUM_ACCESS_11e_eDCF) ))
{
//Joining BSS is 11n capable and WMM is disabled on AP.
//Assume all HT AP's are QOS AP's and enable WMM
pBssConfig->qosType = eCSR_MEDIUM_ACCESS_WMM_eDCF_DSCP;
}
//auth type
switch( pProfile->negotiatedAuthType )
{
default:
case eCSR_AUTH_TYPE_WPA:
case eCSR_AUTH_TYPE_WPA_PSK:
case eCSR_AUTH_TYPE_WPA_NONE:
case eCSR_AUTH_TYPE_OPEN_SYSTEM:
pBssConfig->authType = eSIR_OPEN_SYSTEM;
break;
case eCSR_AUTH_TYPE_SHARED_KEY:
pBssConfig->authType = eSIR_SHARED_KEY;
break;
case eCSR_AUTH_TYPE_AUTOSWITCH:
pBssConfig->authType = eSIR_AUTO_SWITCH;
break;
case eCSR_AUTH_TYPE_SAE:
pBssConfig->authType = eSIR_AUTH_TYPE_SAE;
break;
}
//short slot time
if( eCSR_CFG_DOT11_MODE_11B != cfgDot11Mode )
{
pBssConfig->uShortSlotTime = pMac->roam.configParam.shortSlotTime;
}
else
{
pBssConfig->uShortSlotTime = 0;
}
if(pBssConfig->BssCap.ibss)
{
//We don't support 11h on IBSS
pBssConfig->f11hSupport = eANI_BOOLEAN_FALSE;
}
else
{
pBssConfig->f11hSupport = pMac->roam.configParam.Is11hSupportEnabled;
}
//power constraint
pBssConfig->uPowerLimit = csrGet11hPowerConstraint(pMac, &pIes->PowerConstraints);
//heartbeat
if ( CSR_IS_11A_BSS( pBssDesc ) )
{
pBssConfig->uHeartBeatThresh = pMac->roam.configParam.HeartbeatThresh50;
}
else
{
pBssConfig->uHeartBeatThresh = pMac->roam.configParam.HeartbeatThresh24;
}
/*
* Join timeout, if we find a BeaconInterval in the BssDescription,
* then set the Join Timeout to be 3 BeaconInterval.
*/
if (pBssDesc->beaconInterval)
{
//Make sure it is bigger than the minimal
pBssConfig->uJoinTimeOut =
CSR_ROAM_MAX(3 * pBssDesc->beaconInterval,
CSR_JOIN_FAILURE_TIMEOUT_MIN);
}
else
{
pBssConfig->uJoinTimeOut = CSR_JOIN_FAILURE_TIMEOUT_DEFAULT;
}
//validate CB
pBssConfig->cbMode = csrGetCBModeFromIes(pMac, pBssDesc->channelId, pIes);
if (CSR_IS_CHANNEL_24GHZ(pBssDesc->channelId) &&
pProfile->force_24ghz_in_ht20) {
pBssConfig->cbMode = PHY_SINGLE_CHANNEL_CENTERED;
smsLog(pMac, LOG1,
FL("force_24ghz_in_ht20 is set so set cbmode to 0"));
}
smsLog(pMac, LOG1, FL("Bss Cb is %d, join timeout is %d, HB thresh is %d,"),
pBssConfig->cbMode, pBssConfig->uJoinTimeOut, pBssConfig->uHeartBeatThresh);
}while(0);
return (status);
}
static eHalStatus csrRoamPrepareBssConfigFromProfile(tpAniSirGlobal pMac, tCsrRoamProfile *pProfile,
tBssConfigParam *pBssConfig, tSirBssDescription *pBssDesc)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tANI_U8 operationChannel = 0;
tANI_U8 qAPisEnabled = FALSE;
//SSID
pBssConfig->SSID.length = 0;
if(pProfile->SSIDs.numOfSSIDs)
{
//only use the first one
vos_mem_copy(&pBssConfig->SSID, &pProfile->SSIDs.SSIDList[0].SSID,
sizeof(tSirMacSSid));
}
else
{
//SSID must present
return eHAL_STATUS_FAILURE;
}
//Settomg up the capabilities
if( csrIsBssTypeIBSS(pProfile->BSSType) )
{
pBssConfig->BssCap.ibss = 1;
}
else
{
pBssConfig->BssCap.ess = 1;
}
if( eCSR_ENCRYPT_TYPE_NONE != pProfile->EncryptionType.encryptionType[0] )
{
pBssConfig->BssCap.privacy = 1;
}
pBssConfig->eBand = pMac->roam.configParam.eBand;
//phymode
if(pProfile->ChannelInfo.ChannelList)
{
operationChannel = pProfile->ChannelInfo.ChannelList[0];
}
pBssConfig->uCfgDot11Mode = csrRoamGetPhyModeBandForBss(pMac, pProfile, operationChannel,
&pBssConfig->eBand);
//QOS
//Is this correct to always set to this //***
if ( pBssConfig->BssCap.ess == 1 )
{
/*For Softap case enable WMM*/
if(CSR_IS_INFRA_AP(pProfile) && (eCsrRoamWmmNoQos != pMac->roam.configParam.WMMSupportMode )){
qAPisEnabled = TRUE;
}
else
if (csrRoamGetQosInfoFromBss(pMac, pBssDesc) == eHAL_STATUS_SUCCESS) {
qAPisEnabled = TRUE;
} else {
qAPisEnabled = FALSE;
}
} else {
qAPisEnabled = TRUE;
}
if (( eCsrRoamWmmNoQos != pMac->roam.configParam.WMMSupportMode && qAPisEnabled) ||
(( eCSR_CFG_DOT11_MODE_11N == pBssConfig->uCfgDot11Mode && qAPisEnabled) ||
( eCSR_CFG_DOT11_MODE_TAURUS == pBssConfig->uCfgDot11Mode ) ) //For 11n, need QoS
)
{
pBssConfig->qosType = eCSR_MEDIUM_ACCESS_WMM_eDCF_DSCP;
} else {
pBssConfig->qosType = eCSR_MEDIUM_ACCESS_DCF;
}
//auth type
switch( pProfile->AuthType.authType[0] ) //Take the preferred Auth type.
{
default:
case eCSR_AUTH_TYPE_WPA:
case eCSR_AUTH_TYPE_WPA_PSK:
case eCSR_AUTH_TYPE_WPA_NONE:
case eCSR_AUTH_TYPE_OPEN_SYSTEM:
pBssConfig->authType = eSIR_OPEN_SYSTEM;
break;
case eCSR_AUTH_TYPE_SHARED_KEY:
pBssConfig->authType = eSIR_SHARED_KEY;
break;
case eCSR_AUTH_TYPE_AUTOSWITCH:
pBssConfig->authType = eSIR_AUTO_SWITCH;
break;
case eCSR_AUTH_TYPE_SAE:
pBssConfig->authType = eSIR_AUTH_TYPE_SAE;
break;
}
//short slot time
if( WNI_CFG_PHY_MODE_11B != pBssConfig->uCfgDot11Mode )
{
pBssConfig->uShortSlotTime = pMac->roam.configParam.shortSlotTime;
}
else
{
pBssConfig->uShortSlotTime = 0;
}
//power constraint. We don't support 11h on IBSS
pBssConfig->f11hSupport = eANI_BOOLEAN_FALSE;
pBssConfig->uPowerLimit = 0;
//heartbeat
if ( eCSR_BAND_5G == pBssConfig->eBand )
{
pBssConfig->uHeartBeatThresh = pMac->roam.configParam.HeartbeatThresh50;
}
else
{
pBssConfig->uHeartBeatThresh = pMac->roam.configParam.HeartbeatThresh24;
}
//Join timeout
pBssConfig->uJoinTimeOut = CSR_JOIN_FAILURE_TIMEOUT_DEFAULT;
return (status);
}
static eHalStatus csrRoamGetQosInfoFromBss(tpAniSirGlobal pMac, tSirBssDescription *pBssDesc)
{
eHalStatus status = eHAL_STATUS_FAILURE;
tDot11fBeaconIEs *pIes = NULL;
do
{
if(!HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, pBssDesc, &pIes)))
{
//err msg
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
"csrRoamGetQosInfoFromBss() failed");
break;
}
//check if the AP is QAP & it supports APSD
if( CSR_IS_QOS_BSS(pIes) )
{
status = eHAL_STATUS_SUCCESS;
}
} while (0);
if (NULL != pIes)
{
vos_mem_free(pIes);
}
return status;
}
void csrSetCfgPrivacy( tpAniSirGlobal pMac, tCsrRoamProfile *pProfile, tANI_BOOLEAN fPrivacy )
{
// !! Note: the only difference between this function and the csrSetCfgPrivacyFromProfile() is the
// setting of the privacy CFG based on the advertised privacy setting from the AP for WPA associations.
// See !!Note: below in this function...
tANI_U32 PrivacyEnabled = 0;
tANI_U32 RsnEnabled = 0;
tANI_U32 WepDefaultKeyId = 0;
tANI_U32 WepKeyLength = WNI_CFG_WEP_KEY_LENGTH_5; /* default 40 bits */
tANI_U32 Key0Length = 0;
tANI_U32 Key1Length = 0;
tANI_U32 Key2Length = 0;
tANI_U32 Key3Length = 0;
// Reserve for the biggest key
tANI_U8 Key0[ WNI_CFG_WEP_DEFAULT_KEY_1_LEN ];
tANI_U8 Key1[ WNI_CFG_WEP_DEFAULT_KEY_2_LEN ];
tANI_U8 Key2[ WNI_CFG_WEP_DEFAULT_KEY_3_LEN ];
tANI_U8 Key3[ WNI_CFG_WEP_DEFAULT_KEY_4_LEN ];
switch ( pProfile->negotiatedUCEncryptionType )
{
case eCSR_ENCRYPT_TYPE_NONE:
// for NO encryption, turn off Privacy and Rsn.
PrivacyEnabled = 0;
RsnEnabled = 0;
// WEP key length and Wep Default Key ID don't matter in this case....
// clear out the WEP keys that may be hanging around.
Key0Length = 0;
Key1Length = 0;
Key2Length = 0;
Key3Length = 0;
break;
case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY:
case eCSR_ENCRYPT_TYPE_WEP40:
// Privacy is ON. NO RSN for Wep40 static key.
PrivacyEnabled = 1;
RsnEnabled = 0;
// Set the Wep default key ID.
WepDefaultKeyId = pProfile->Keys.defaultIndex;
// Wep key size if 5 bytes (40 bits).
WepKeyLength = WNI_CFG_WEP_KEY_LENGTH_5;
// set encryption keys in the CFG database or clear those that are not present in this profile.
if ( pProfile->Keys.KeyLength[0] )
{
vos_mem_copy(Key0, pProfile->Keys.KeyMaterial[0],
WNI_CFG_WEP_KEY_LENGTH_5);
Key0Length = WNI_CFG_WEP_KEY_LENGTH_5;
}
else
{
Key0Length = 0;
}
if ( pProfile->Keys.KeyLength[1] )
{
vos_mem_copy(Key1, pProfile->Keys.KeyMaterial[1],
WNI_CFG_WEP_KEY_LENGTH_5);
Key1Length = WNI_CFG_WEP_KEY_LENGTH_5;
}
else
{
Key1Length = 0;
}
if ( pProfile->Keys.KeyLength[2] )
{
vos_mem_copy(Key2, pProfile->Keys.KeyMaterial[2],
WNI_CFG_WEP_KEY_LENGTH_5);
Key2Length = WNI_CFG_WEP_KEY_LENGTH_5;
}
else
{
Key2Length = 0;
}
if ( pProfile->Keys.KeyLength[3] )
{
vos_mem_copy(Key3, pProfile->Keys.KeyMaterial[3],
WNI_CFG_WEP_KEY_LENGTH_5);
Key3Length = WNI_CFG_WEP_KEY_LENGTH_5;
}
else
{
Key3Length = 0;
}
break;
case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY:
case eCSR_ENCRYPT_TYPE_WEP104:
// Privacy is ON. NO RSN for Wep40 static key.
PrivacyEnabled = 1;
RsnEnabled = 0;
// Set the Wep default key ID.
WepDefaultKeyId = pProfile->Keys.defaultIndex;
// Wep key size if 13 bytes (104 bits).
WepKeyLength = WNI_CFG_WEP_KEY_LENGTH_13;
// set encryption keys in the CFG database or clear those that are not present in this profile.
if ( pProfile->Keys.KeyLength[0] )
{
vos_mem_copy(Key0, pProfile->Keys.KeyMaterial[ 0 ],
WNI_CFG_WEP_KEY_LENGTH_13);
Key0Length = WNI_CFG_WEP_KEY_LENGTH_13;
}
else
{
Key0Length = 0;
}
if ( pProfile->Keys.KeyLength[1] )
{
vos_mem_copy(Key1, pProfile->Keys.KeyMaterial[ 1 ],
WNI_CFG_WEP_KEY_LENGTH_13);
Key1Length = WNI_CFG_WEP_KEY_LENGTH_13;
}
else
{
Key1Length = 0;
}
if ( pProfile->Keys.KeyLength[2] )
{
vos_mem_copy(Key2, pProfile->Keys.KeyMaterial[ 2 ],
WNI_CFG_WEP_KEY_LENGTH_13);
Key2Length = WNI_CFG_WEP_KEY_LENGTH_13;
}
else
{
Key2Length = 0;
}
if ( pProfile->Keys.KeyLength[3] )
{
vos_mem_copy(Key3, pProfile->Keys.KeyMaterial[ 3 ],
WNI_CFG_WEP_KEY_LENGTH_13);
Key3Length = WNI_CFG_WEP_KEY_LENGTH_13;
}
else
{
Key3Length = 0;
}
break;
case eCSR_ENCRYPT_TYPE_TKIP:
case eCSR_ENCRYPT_TYPE_AES:
#ifdef FEATURE_WLAN_WAPI
case eCSR_ENCRYPT_TYPE_WPI:
#endif /* FEATURE_WLAN_WAPI */
// !! Note: this is the only difference between this function and the csrSetCfgPrivacyFromProfile()
// (setting of the privacy CFG based on the advertised privacy setting from the AP for WPA/WAPI associations ).
PrivacyEnabled = (0 != fPrivacy);
// turn on RSN enabled for WPA associations
RsnEnabled = 1;
// WEP key length and Wep Default Key ID don't matter in this case....
// clear out the static WEP keys that may be hanging around.
Key0Length = 0;
Key1Length = 0;
Key2Length = 0;
Key3Length = 0;
break;
default:
PrivacyEnabled = 0;
RsnEnabled = 0;
break;
}
ccmCfgSetInt(pMac, WNI_CFG_PRIVACY_ENABLED, PrivacyEnabled, NULL, eANI_BOOLEAN_FALSE);
ccmCfgSetInt(pMac, WNI_CFG_RSN_ENABLED, RsnEnabled, NULL, eANI_BOOLEAN_FALSE);
ccmCfgSetStr(pMac, WNI_CFG_WEP_DEFAULT_KEY_1, Key0, Key0Length, NULL, eANI_BOOLEAN_FALSE);
ccmCfgSetStr(pMac, WNI_CFG_WEP_DEFAULT_KEY_2, Key1, Key1Length, NULL, eANI_BOOLEAN_FALSE);
ccmCfgSetStr(pMac, WNI_CFG_WEP_DEFAULT_KEY_3, Key2, Key2Length, NULL, eANI_BOOLEAN_FALSE);
ccmCfgSetStr(pMac, WNI_CFG_WEP_DEFAULT_KEY_4, Key3, Key3Length, NULL, eANI_BOOLEAN_FALSE);
ccmCfgSetInt(pMac, WNI_CFG_WEP_KEY_LENGTH, WepKeyLength, NULL, eANI_BOOLEAN_FALSE);
ccmCfgSetInt(pMac, WNI_CFG_WEP_DEFAULT_KEYID, WepDefaultKeyId, NULL, eANI_BOOLEAN_FALSE);
}
static void csrSetCfgSsid( tpAniSirGlobal pMac, tSirMacSSid *pSSID )
{
tANI_U32 len = 0;
if(pSSID->length <= WNI_CFG_SSID_LEN)
{
len = pSSID->length;
}
ccmCfgSetStr(pMac, WNI_CFG_SSID, (tANI_U8 *)pSSID->ssId, len, NULL, eANI_BOOLEAN_FALSE);
}
eHalStatus csrSetQosToCfg( tpAniSirGlobal pMac, tANI_U32 sessionId, eCsrMediaAccessType qosType )
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tANI_U32 QoSEnabled;
tANI_U32 WmeEnabled;
// set the CFG enable/disable variables based on the qosType being configured...
switch( qosType )
{
case eCSR_MEDIUM_ACCESS_WMM_eDCF_802dot1p:
QoSEnabled = FALSE;
WmeEnabled = TRUE;
break;
case eCSR_MEDIUM_ACCESS_WMM_eDCF_DSCP:
QoSEnabled = FALSE;
WmeEnabled = TRUE;
break;
case eCSR_MEDIUM_ACCESS_WMM_eDCF_NoClassify:
QoSEnabled = FALSE;
WmeEnabled = TRUE;
break;
case eCSR_MEDIUM_ACCESS_11e_eDCF:
QoSEnabled = TRUE;
WmeEnabled = FALSE;
break;
case eCSR_MEDIUM_ACCESS_11e_HCF:
QoSEnabled = TRUE;
WmeEnabled = FALSE;
break;
default:
case eCSR_MEDIUM_ACCESS_DCF:
QoSEnabled = FALSE;
WmeEnabled = FALSE;
break;
}
//save the WMM setting for later use
pMac->roam.roamSession[sessionId].fWMMConnection = (tANI_BOOLEAN)WmeEnabled;
pMac->roam.roamSession[sessionId].fQOSConnection = (tANI_BOOLEAN)QoSEnabled;
return (status);
}
static eHalStatus csrGetRateSet( tpAniSirGlobal pMac, tCsrRoamProfile *pProfile, eCsrPhyMode phyMode, tSirBssDescription *pBssDesc,
tDot11fBeaconIEs *pIes, tSirMacRateSet *pOpRateSet, tSirMacRateSet *pExRateSet, tANI_U16 *pRateBitmap)
{
eHalStatus status = eHAL_STATUS_FAILURE;
int i;
eCsrCfgDot11Mode cfgDot11Mode;
tANI_U8 *pDstRate;
tANI_U16 rateBitmap = 0;
vos_mem_set(pOpRateSet, sizeof(tSirMacRateSet), 0);
vos_mem_set(pExRateSet, sizeof(tSirMacRateSet), 0);
VOS_ASSERT( pIes != NULL );
if( NULL != pIes )
{
csrIsPhyModeMatch( pMac, phyMode, pBssDesc, pProfile, &cfgDot11Mode, pIes );
// Originally, we thought that for 11a networks, the 11a rates are always
// in the Operational Rate set & for 11b and 11g networks, the 11b rates
// appear in the Operational Rate set. Consequently, in either case, we
// would blindly put the rates we support into our Operational Rate set
// (including the basic rates, which we have already verified are
// supported earlier in the roaming decision).
// However, it turns out that this is not always the case. Some AP's
// (e.g. D-Link DI-784) ram 11g rates into the Operational Rate set,
// too. Now, we're a little more careful:
pDstRate = pOpRateSet->rate;
if(pIes->SuppRates.present)
{
for ( i = 0; i < pIes->SuppRates.num_rates; i++ )
{
if ( csrRatesIsDot11RateSupported( pMac, pIes->SuppRates.rates[ i ] ) )
{
if ( !csrIsRateAlreadyPresent(pIes->SuppRates.rates[ i ], rateBitmap) )
{
csrAddRateBitmap(pIes->SuppRates.rates[ i ], &rateBitmap);
*pDstRate++ = pIes->SuppRates.rates[ i ];
pOpRateSet->numRates++;
}
}
}
}
/* If there are Extended Rates in the beacon, we will reflect those
* extended rates that we support in out Extended Operational Rate
* set*/
pDstRate = pExRateSet->rate;
if(pIes->ExtSuppRates.present)
{
for (i = 0; i < pIes->ExtSuppRates.num_rates; i++)
{
if (csrRatesIsDot11RateSupported(pMac,
pIes->ExtSuppRates.rates[ i ]))
{
if (!csrIsRateAlreadyPresent(pIes->ExtSuppRates.rates[i],
rateBitmap))
{
csrAddRateBitmap(pIes->ExtSuppRates.rates[i],
&rateBitmap);
*pDstRate++ = pIes->ExtSuppRates.rates[i];
pExRateSet->numRates++;
}
}
}
}
*pRateBitmap = rateBitmap;
}//Parsing BSSDesc
else
{
smsLog(pMac, LOGE, FL("failed to parse BssDesc"));
}
if (pOpRateSet->numRates > 0 || pExRateSet->numRates > 0) status = eHAL_STATUS_SUCCESS;
return status;
}
static void csrSetCfgRateSet( tpAniSirGlobal pMac, eCsrPhyMode phyMode, tCsrRoamProfile *pProfile,
tSirBssDescription *pBssDesc, tDot11fBeaconIEs *pIes)
{
int i;
tANI_U8 *pDstRate;
eCsrCfgDot11Mode cfgDot11Mode;
tANI_U8 OperationalRates[ CSR_DOT11_SUPPORTED_RATES_MAX ]; // leave enough room for the max number of rates
tANI_U32 OperationalRatesLength = 0;
tANI_U8 ExtendedOperationalRates[ CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX ]; // leave enough room for the max number of rates
tANI_U32 ExtendedOperationalRatesLength = 0;
tANI_U8 ProprietaryOperationalRates[ 4 ]; // leave enough room for the max number of proprietary rates
tANI_U32 ProprietaryOperationalRatesLength = 0;
tANI_U32 PropRatesEnable = 0;
tANI_U8 MCSRateIdxSet[ SIZE_OF_SUPPORTED_MCS_SET ];
tANI_U32 MCSRateLength = 0;
VOS_ASSERT( pIes != NULL );
if( NULL != pIes )
{
csrIsPhyModeMatch( pMac, phyMode, pBssDesc, pProfile, &cfgDot11Mode, pIes );
// Originally, we thought that for 11a networks, the 11a rates are always
// in the Operational Rate set & for 11b and 11g networks, the 11b rates
// appear in the Operational Rate set. Consequently, in either case, we
// would blindly put the rates we support into our Operational Rate set
// (including the basic rates, which we have already verified are
// supported earlier in the roaming decision).
// However, it turns out that this is not always the case. Some AP's
// (e.g. D-Link DI-784) ram 11g rates into the Operational Rate set,
// too. Now, we're a little more careful:
pDstRate = OperationalRates;
if(pIes->SuppRates.present)
{
for ( i = 0; i < pIes->SuppRates.num_rates; i++ )
{
if ( csrRatesIsDot11RateSupported( pMac, pIes->SuppRates.rates[ i ] ) &&
( OperationalRatesLength < CSR_DOT11_SUPPORTED_RATES_MAX ))
{
*pDstRate++ = pIes->SuppRates.rates[ i ];
OperationalRatesLength++;
}
}
}
if ( eCSR_CFG_DOT11_MODE_11G == cfgDot11Mode ||
eCSR_CFG_DOT11_MODE_11N == cfgDot11Mode ||
eCSR_CFG_DOT11_MODE_TAURUS == cfgDot11Mode ||
eCSR_CFG_DOT11_MODE_ABG == cfgDot11Mode )
{
// If there are Extended Rates in the beacon, we will reflect those
// extended rates that we support in out Extended Operational Rate
// set:
pDstRate = ExtendedOperationalRates;
if(pIes->ExtSuppRates.present)
{
for ( i = 0; i < pIes->ExtSuppRates.num_rates; i++ )
{
if ( csrRatesIsDot11RateSupported( pMac, pIes->ExtSuppRates.rates[ i ] ) &&
( ExtendedOperationalRatesLength < CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX ))
{
*pDstRate++ = pIes->ExtSuppRates.rates[ i ];
ExtendedOperationalRatesLength++;
}
}
}
}
// Enable proprietary MAC features if peer node is Airgo node and STA
// user wants to use them
if( pIes->Airgo.present && pMac->roam.configParam.ProprietaryRatesEnabled )
{
PropRatesEnable = 1;
}
else
{
PropRatesEnable = 0;
}
// For ANI network companions, we need to populate the proprietary rate
// set with any proprietary rates we found in the beacon, only if user
// allows them...
if ( PropRatesEnable && pIes->Airgo.PropSuppRates.present &&
( pIes->Airgo.PropSuppRates.num_rates > 0 ))
{
ProprietaryOperationalRatesLength = pIes->Airgo.PropSuppRates.num_rates;
if ( ProprietaryOperationalRatesLength > sizeof(ProprietaryOperationalRates) )
{
ProprietaryOperationalRatesLength = sizeof (ProprietaryOperationalRates);
}
vos_mem_copy(ProprietaryOperationalRates,
pIes->Airgo.PropSuppRates.rates,
ProprietaryOperationalRatesLength);
}
else {
// No proprietary modes...
ProprietaryOperationalRatesLength = 0;
}
/* Get MCS Rate */
pDstRate = MCSRateIdxSet;
if ( pIes->HTCaps.present )
{
for ( i = 0; i < VALID_MAX_MCS_INDEX; i++ )
{
if ( (unsigned int)pIes->HTCaps.supportedMCSSet[0] & (1 << i) )
{
MCSRateLength++;
*pDstRate++ = i;
}
}
}
// Set the operational rate set CFG variables...
ccmCfgSetStr(pMac, WNI_CFG_OPERATIONAL_RATE_SET, OperationalRates,
OperationalRatesLength, NULL, eANI_BOOLEAN_FALSE);
ccmCfgSetStr(pMac, WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET, ExtendedOperationalRates,
ExtendedOperationalRatesLength, NULL, eANI_BOOLEAN_FALSE);
ccmCfgSetStr(pMac, WNI_CFG_PROPRIETARY_OPERATIONAL_RATE_SET,
ProprietaryOperationalRates,
ProprietaryOperationalRatesLength, NULL, eANI_BOOLEAN_FALSE);
ccmCfgSetInt(pMac, WNI_CFG_PROPRIETARY_ANI_FEATURES_ENABLED, PropRatesEnable, NULL, eANI_BOOLEAN_FALSE);
ccmCfgSetStr(pMac, WNI_CFG_CURRENT_MCS_SET, MCSRateIdxSet,
MCSRateLength, NULL, eANI_BOOLEAN_FALSE);
}//Parsing BSSDesc
else
{
smsLog(pMac, LOGE, FL("failed to parse BssDesc"));
}
}
static void csrSetCfgRateSetFromProfile( tpAniSirGlobal pMac,
tCsrRoamProfile *pProfile )
{
tSirMacRateSetIE DefaultSupportedRates11a = { SIR_MAC_RATESET_EID,
{ 8,
{ SIR_MAC_RATE_6,
SIR_MAC_RATE_9,
SIR_MAC_RATE_12,
SIR_MAC_RATE_18,
SIR_MAC_RATE_24,
SIR_MAC_RATE_36,
SIR_MAC_RATE_48,
SIR_MAC_RATE_54 } } };
tSirMacRateSetIE DefaultSupportedRates11b = { SIR_MAC_RATESET_EID,
{ 4,
{ SIR_MAC_RATE_1,
SIR_MAC_RATE_2,
SIR_MAC_RATE_5_5,
SIR_MAC_RATE_11 } } };
tSirMacPropRateSet DefaultSupportedPropRates = { 3,
{ SIR_MAC_RATE_72,
SIR_MAC_RATE_96,
SIR_MAC_RATE_108 } };
eCsrCfgDot11Mode cfgDot11Mode;
eCsrBand eBand;
tANI_U8 OperationalRates[ CSR_DOT11_SUPPORTED_RATES_MAX ]; // leave enough room for the max number of rates
tANI_U32 OperationalRatesLength = 0;
tANI_U8 ExtendedOperationalRates[ CSR_DOT11_EXTENDED_SUPPORTED_RATES_MAX ]; // leave enough room for the max number of rates
tANI_U32 ExtendedOperationalRatesLength = 0;
tANI_U8 ProprietaryOperationalRates[ 4 ]; // leave enough room for the max number of proprietary rates
tANI_U32 ProprietaryOperationalRatesLength = 0;
tANI_U32 PropRatesEnable = 0;
tANI_U8 operationChannel = 0;
if(pProfile->ChannelInfo.ChannelList)
{
operationChannel = pProfile->ChannelInfo.ChannelList[0];
}
cfgDot11Mode = csrRoamGetPhyModeBandForBss( pMac, pProfile, operationChannel, &eBand );
// For 11a networks, the 11a rates go into the Operational Rate set. For 11b and 11g
// networks, the 11b rates appear in the Operational Rate set. In either case,
// we can blindly put the rates we support into our Operational Rate set
// (including the basic rates, which we have already verified are supported
// earlier in the roaming decision).
if ( eCSR_BAND_5G == eBand )
{
// 11a rates into the Operational Rate Set.
OperationalRatesLength = DefaultSupportedRates11a.supportedRateSet.numRates *
sizeof(*DefaultSupportedRates11a.supportedRateSet.rate);
vos_mem_copy(OperationalRates,
DefaultSupportedRates11a.supportedRateSet.rate,
OperationalRatesLength);
// Nothing in the Extended rate set.
ExtendedOperationalRatesLength = 0;
// populate proprietary rates if user allows them
if ( pMac->roam.configParam.ProprietaryRatesEnabled )
{
ProprietaryOperationalRatesLength = DefaultSupportedPropRates.numPropRates *
sizeof(*DefaultSupportedPropRates.propRate);
vos_mem_copy(ProprietaryOperationalRates,
DefaultSupportedPropRates.propRate,
ProprietaryOperationalRatesLength);
}
else
{
// No proprietary modes
ProprietaryOperationalRatesLength = 0;
}
}
else if ( eCSR_CFG_DOT11_MODE_11B == cfgDot11Mode )
{
// 11b rates into the Operational Rate Set.
OperationalRatesLength = DefaultSupportedRates11b.supportedRateSet.numRates *
sizeof(*DefaultSupportedRates11b.supportedRateSet.rate);
vos_mem_copy(OperationalRates,
DefaultSupportedRates11b.supportedRateSet.rate,
OperationalRatesLength);
// Nothing in the Extended rate set.
ExtendedOperationalRatesLength = 0;
// No proprietary modes
ProprietaryOperationalRatesLength = 0;
}
else
{
// 11G
// 11b rates into the Operational Rate Set.
OperationalRatesLength = DefaultSupportedRates11b.supportedRateSet.numRates *
sizeof(*DefaultSupportedRates11b.supportedRateSet.rate);
vos_mem_copy(OperationalRates,
DefaultSupportedRates11b.supportedRateSet.rate,
OperationalRatesLength);
// 11a rates go in the Extended rate set.
ExtendedOperationalRatesLength = DefaultSupportedRates11a.supportedRateSet.numRates *
sizeof(*DefaultSupportedRates11a.supportedRateSet.rate);
vos_mem_copy(ExtendedOperationalRates,
DefaultSupportedRates11a.supportedRateSet.rate,
ExtendedOperationalRatesLength);
// populate proprietary rates if user allows them
if ( pMac->roam.configParam.ProprietaryRatesEnabled )
{
ProprietaryOperationalRatesLength = DefaultSupportedPropRates.numPropRates *
sizeof(*DefaultSupportedPropRates.propRate);
vos_mem_copy(ProprietaryOperationalRates,
DefaultSupportedPropRates.propRate,
ProprietaryOperationalRatesLength);
}
else
{
// No proprietary modes
ProprietaryOperationalRatesLength = 0;
}
}
// set this to 1 if prop. rates need to be advertised in to the IBSS beacon and user wants to use them
if ( ProprietaryOperationalRatesLength && pMac->roam.configParam.ProprietaryRatesEnabled )
{
PropRatesEnable = 1;
}
else
{
PropRatesEnable = 0;
}
// Set the operational rate set CFG variables...
ccmCfgSetStr(pMac, WNI_CFG_OPERATIONAL_RATE_SET, OperationalRates,
OperationalRatesLength, NULL, eANI_BOOLEAN_FALSE);
ccmCfgSetStr(pMac, WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET, ExtendedOperationalRates,
ExtendedOperationalRatesLength, NULL, eANI_BOOLEAN_FALSE);
ccmCfgSetStr(pMac, WNI_CFG_PROPRIETARY_OPERATIONAL_RATE_SET,
ProprietaryOperationalRates,
ProprietaryOperationalRatesLength, NULL, eANI_BOOLEAN_FALSE);
ccmCfgSetInt(pMac, WNI_CFG_PROPRIETARY_ANI_FEATURES_ENABLED, PropRatesEnable, NULL, eANI_BOOLEAN_FALSE);
}
void csrRoamCcmCfgSetCallback(tHalHandle hHal, tANI_S32 result)
{
tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
tListElem *pEntry = csrLLPeekHead(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK);
tANI_U32 sessionId;
tSmeCmd *pCommand = NULL;
if(NULL == pEntry)
{
smsLog(pMac, LOGW, " CFG_CNF with active list empty");
return;
}
pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
sessionId = pCommand->sessionId;
smsLog(pMac, LOG1, FL("CCM CFG return value is %d, "
" current state : %d sub state : %d "),
result, pMac->roam.curState[sessionId],
pMac->roam.curSubState[sessionId]);
if(CSR_IS_ROAM_JOINING(pMac, sessionId) && CSR_IS_ROAM_SUBSTATE_CONFIG(pMac, sessionId))
{
csrRoamingStateConfigCnfProcessor(pMac, (tANI_U32)result);
}
}
//This function is very dump. It is here because PE still need WNI_CFG_PHY_MODE
tANI_U32 csrRoamGetPhyModeFromDot11Mode(eCsrCfgDot11Mode dot11Mode, eCsrBand band)
{
if(eCSR_CFG_DOT11_MODE_11B == dot11Mode)
{
return (WNI_CFG_PHY_MODE_11B);
}
else
{
if(eCSR_BAND_24 == band)
return (WNI_CFG_PHY_MODE_11G);
}
return (WNI_CFG_PHY_MODE_11A);
}
#ifdef WLAN_FEATURE_11AC
ePhyChanBondState csrGetHTCBStateFromVHTCBState(ePhyChanBondState aniCBMode)
{
switch ( aniCBMode )
{
case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW:
case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_CENTERED:
case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH:
return PHY_DOUBLE_CHANNEL_HIGH_PRIMARY;
case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW:
case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_CENTERED:
case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH:
return PHY_DOUBLE_CHANNEL_LOW_PRIMARY;
case PHY_QUADRUPLE_CHANNEL_20MHZ_CENTERED_40MHZ_CENTERED:
default :
return PHY_SINGLE_CHANNEL_CENTERED;
}
}
#endif
//pIes may be NULL
eHalStatus csrRoamSetBssConfigCfg(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfile *pProfile,
tSirBssDescription *pBssDesc, tBssConfigParam *pBssConfig,
tDot11fBeaconIEs *pIes, tANI_BOOLEAN resetCountry)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tANI_U32 cfgCb = WNI_CFG_CHANNEL_BONDING_MODE_DISABLE;
tANI_U8 channel = 0;
//Make sure we have the domain info for the BSS we try to connect to.
//Do we need to worry about sequence for OSs that are not Windows??
if (pBssDesc)
{
if (csrLearnCountryInformation(pMac, pBssDesc, pIes, eANI_BOOLEAN_TRUE))
{
//Make sure the 11d info from this BSSDesc can be applied
pMac->scan.fAmbiguous11dInfoFound = eANI_BOOLEAN_FALSE;
if (VOS_TRUE == resetCountry)
{
csrApplyCountryInformation(pMac, FALSE);
}
else
{
csrApplyCountryInformation(pMac, TRUE);
}
}
if ((csrIs11dSupported (pMac)) && pIes)
{
if (!pIes->Country.present)
{
csrResetCountryInformation(pMac, eANI_BOOLEAN_FALSE, eANI_BOOLEAN_FALSE );
}
else
{
//Let's also update the below to make sure we don't update CC while
//connected to an AP which is advertising some CC
vos_mem_copy(pMac->scan.currentCountryBssid,
pBssDesc->bssId, sizeof(tSirMacAddr));
}
}
}
//Qos
csrSetQosToCfg( pMac, sessionId, pBssConfig->qosType );
//SSID
csrSetCfgSsid(pMac, &pBssConfig->SSID );
//fragment threshold
//ccmCfgSetInt(pMac, WNI_CFG_FRAGMENTATION_THRESHOLD, csrGetFragThresh(pMac), NULL, eANI_BOOLEAN_FALSE);
//RTS threshold
//ccmCfgSetInt(pMac, WNI_CFG_RTS_THRESHOLD, csrGetRTSThresh(pMac), NULL, eANI_BOOLEAN_FALSE);
//ccmCfgSetInt(pMac, WNI_CFG_DOT11_MODE, csrTranslateToWNICfgDot11Mode(pMac, pBssConfig->uCfgDot11Mode), NULL, eANI_BOOLEAN_FALSE);
//Auth type
ccmCfgSetInt(pMac, WNI_CFG_AUTHENTICATION_TYPE, pBssConfig->authType, NULL, eANI_BOOLEAN_FALSE);
//encryption type
csrSetCfgPrivacy(pMac, pProfile, (tANI_BOOLEAN)pBssConfig->BssCap.privacy );
//short slot time
ccmCfgSetInt(pMac, WNI_CFG_11G_SHORT_SLOT_TIME_ENABLED, pBssConfig->uShortSlotTime, NULL, eANI_BOOLEAN_FALSE);
//11d
ccmCfgSetInt(pMac, WNI_CFG_11D_ENABLED,
((pBssConfig->f11hSupport) ? pBssConfig->f11hSupport : pProfile->ieee80211d),
NULL, eANI_BOOLEAN_FALSE);
/*//11h
ccmCfgSetInt(pMac, WNI_CFG_11H_ENABLED, pMac->roam.configParam.Is11hSupportEnabled, NULL, eANI_BOOLEAN_FALSE);
*/
ccmCfgSetInt(pMac, WNI_CFG_LOCAL_POWER_CONSTRAINT, pBssConfig->uPowerLimit, NULL, eANI_BOOLEAN_FALSE);
//CB
if(CSR_IS_INFRA_AP(pProfile) || CSR_IS_WDS_AP(pProfile) || CSR_IS_IBSS(pProfile))
{
channel = pProfile->operationChannel;
}
else
{
if(pBssDesc)
{
channel = pBssDesc->channelId;
}
}
if(0 != channel)
{
if(CSR_IS_CHANNEL_24GHZ(channel) &&
!pMac->roam.configParam.channelBondingMode24GHz &&
!WDA_getFwWlanFeatCaps(HT40_OBSS_SCAN))
{//On 2.4 Ghz, CB will be disabled if it is not configured through .ini
cfgCb = WNI_CFG_CHANNEL_BONDING_MODE_DISABLE;
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, "%s: "
" cbMode disabled cfgCb = %d channelBondingMode24GHz %d",
__func__, cfgCb, pMac->roam.configParam.channelBondingMode24GHz);
}
else
{
cfgCb = pBssConfig->cbMode;
}
}
#ifdef WLAN_FEATURE_11AC
// cbMode = 1 in cfg.ini is mapped to PHY_DOUBLE_CHANNEL_HIGH_PRIMARY = 3
// in function csrConvertCBIniValueToPhyCBState()
// So, max value for cbMode in 40MHz mode is 3 (MAC\src\include\sirParams.h)
if(cfgCb > PHY_DOUBLE_CHANNEL_HIGH_PRIMARY)
{
if(!WDA_getFwWlanFeatCaps(DOT11AC)) {
cfgCb = csrGetHTCBStateFromVHTCBState(cfgCb);
}
else
{
ccmCfgSetInt(pMac, WNI_CFG_VHT_CHANNEL_WIDTH, pMac->roam.configParam.nVhtChannelWidth, NULL, eANI_BOOLEAN_FALSE);
}
}
else
#endif
ccmCfgSetInt(pMac, WNI_CFG_CHANNEL_BONDING_MODE, cfgCb, NULL, eANI_BOOLEAN_FALSE);
//Rate
//Fixed Rate
if(pBssDesc)
{
csrSetCfgRateSet(pMac, (eCsrPhyMode)pProfile->phyMode, pProfile, pBssDesc, pIes);
}
else
{
csrSetCfgRateSetFromProfile(pMac, pProfile);
}
//Make this the last CFG to set. The callback will trigger a join_req
//Join time out
csrRoamSubstateChange( pMac, eCSR_ROAM_SUBSTATE_CONFIG, sessionId );
ccmCfgSetInt(pMac, WNI_CFG_JOIN_FAILURE_TIMEOUT, pBssConfig->uJoinTimeOut, (tCcmCfgSetCallback)csrRoamCcmCfgSetCallback, eANI_BOOLEAN_FALSE);
return (status);
}
eHalStatus csrRoamStopNetwork( tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfile *pProfile,
tSirBssDescription *pBssDesc, tDot11fBeaconIEs *pIes)
{
eHalStatus status;
tBssConfigParam *pBssConfig;
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return eHAL_STATUS_FAILURE;
}
pBssConfig = vos_mem_malloc(sizeof(tBssConfigParam));
if ( NULL == pBssConfig )
status = eHAL_STATUS_FAILURE;
else
{
vos_mem_set(pBssConfig, sizeof(tBssConfigParam), 0);
status = csrRoamPrepareBssConfig(pMac, pProfile, pBssDesc, pBssConfig, pIes);
if(HAL_STATUS_SUCCESS(status))
{
pSession->bssParams.uCfgDot11Mode = pBssConfig->uCfgDot11Mode;
/* This will allow to pass cbMode during join req */
pSession->bssParams.cbMode= pBssConfig->cbMode;
//For IBSS, we need to prepare some more information
if( csrIsBssTypeIBSS(pProfile->BSSType) || CSR_IS_WDS( pProfile )
|| CSR_IS_INFRA_AP(pProfile)
)
{
csrRoamPrepareBssParams(pMac, sessionId, pProfile, pBssDesc, pBssConfig, pIes);
}
// If we are in an IBSS, then stop the IBSS...
////Not worry about WDS connection for now
if ( csrIsConnStateIbss( pMac, sessionId ) )
{
status = csrRoamIssueStopBss( pMac, sessionId, eCSR_ROAM_SUBSTATE_DISCONNECT_CONTINUE_ROAMING );
}
else
{
// if we are in an Infrastructure association....
if ( csrIsConnStateInfra( pMac, sessionId ) )
{
// and the new Bss is an Ibss OR we are roaming from Infra to Infra
// across SSIDs (roaming to a new SSID)... //
//Not worry about WDS connection for now
if ( pBssDesc && ( ( csrIsIbssBssDesc( pBssDesc ) ) ||
!csrIsSsidEqual( pMac, pSession->pConnectBssDesc, pBssDesc, pIes ) ) )
{
// then we need to disassociate from the Infrastructure network...
status = csrRoamIssueDisassociate( pMac, sessionId,
eCSR_ROAM_SUBSTATE_DISCONNECT_CONTINUE_ROAMING, FALSE );
}
else
{
// In an Infrastucture and going to an Infrastructure network with the same SSID. This
// calls for a Reassociation sequence. So issue the CFG sets for this new AP.
if ( pBssDesc )
{
// Set parameters for this Bss.
status = csrRoamSetBssConfigCfg(pMac, sessionId, pProfile,
pBssDesc, pBssConfig,
pIes, eANI_BOOLEAN_FALSE);
}
}
}
else
{
// Neiher in IBSS nor in Infra. We can go ahead and set the CFG for tne new network...
// Nothing to stop.
if ( pBssDesc || CSR_IS_WDS_AP( pProfile )
|| CSR_IS_INFRA_AP(pProfile)
)
{
tANI_BOOLEAN is11rRoamingFlag = eANI_BOOLEAN_FALSE;
is11rRoamingFlag = csrRoamIs11rAssoc(pMac);
// Set parameters for this Bss.
status = csrRoamSetBssConfigCfg(pMac, sessionId, pProfile,
pBssDesc, pBssConfig,
pIes, is11rRoamingFlag);
}
}
}
}//Success getting BSS config info
vos_mem_free(pBssConfig);
}//Allocate memory
return (status);
}
eCsrJoinState csrRoamJoin( tpAniSirGlobal pMac, tANI_U32 sessionId,
tCsrScanResultInfo *pScanResult, tCsrRoamProfile *pProfile )
{
eCsrJoinState eRoamState = eCsrContinueRoaming;
eHalStatus status;
tSirBssDescription *pBssDesc = &pScanResult->BssDescriptor;
tDot11fBeaconIEs *pIesLocal = (tDot11fBeaconIEs *)( pScanResult->pvIes ); //This may be NULL
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return (eCsrStopRoaming);
}
if( CSR_IS_WDS_STA( pProfile ) )
{
status = csrRoamStartWds( pMac, sessionId, pProfile, pBssDesc );
if( !HAL_STATUS_SUCCESS( status ) )
{
eRoamState = eCsrStopRoaming;
}
}
else
{
if( !pIesLocal && (!HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, pBssDesc, &pIesLocal))) )
{
smsLog(pMac, LOGE, FL(" fail to parse IEs"));
return (eCsrStopRoaming);
}
if ( csrIsInfraBssDesc( pBssDesc ) )
{
// If we are connected in infrastructure mode and the Join Bss description is for the same BssID, then we are
// attempting to join the AP we are already connected with. In that case, see if the Bss or Sta capabilities
// have changed and handle the changes (without disturbing the current association).
if ( csrIsConnStateConnectedInfra(pMac, sessionId) &&
csrIsBssIdEqual( pMac, pBssDesc, pSession->pConnectBssDesc ) &&
csrIsSsidEqual( pMac, pSession->pConnectBssDesc, pBssDesc, pIesLocal )
)
{
// Check to see if the Auth type has changed in the Profile. If so, we don't want to Reassociate
// with Authenticating first. To force this, stop the current association (Disassociate) and
// then re 'Join' the AP, wihch will force an Authentication (with the new Auth type) followed by
// a new Association.
if(csrIsSameProfile(pMac, &pSession->connectedProfile, pProfile))
{
smsLog(pMac, LOGW, FL(" detect same profile"));
if(csrRoamIsSameProfileKeys(pMac, &pSession->connectedProfile, pProfile))
{
eRoamState = eCsrReassocToSelfNoCapChange;
}
else
{
tBssConfigParam bssConfig;
//The key changes
vos_mem_set(&bssConfig, sizeof(bssConfig), 0);
status = csrRoamPrepareBssConfig(pMac, pProfile, pBssDesc, &bssConfig, pIesLocal);
if(HAL_STATUS_SUCCESS(status))
{
pSession->bssParams.uCfgDot11Mode = bssConfig.uCfgDot11Mode;
pSession->bssParams.cbMode = bssConfig.cbMode;
//Reapply the config including Keys so reassoc is happening.
status = csrRoamSetBssConfigCfg(pMac, sessionId, pProfile,
pBssDesc, &bssConfig,
pIesLocal, eANI_BOOLEAN_FALSE);
if(!HAL_STATUS_SUCCESS(status))
{
eRoamState = eCsrStopRoaming;
}
}
else
{
eRoamState = eCsrStopRoaming;
}
}//same profile
}
else
{
if(!HAL_STATUS_SUCCESS(csrRoamIssueDisassociate( pMac, sessionId,
eCSR_ROAM_SUBSTATE_DISASSOC_REQ, FALSE )))
{
smsLog(pMac, LOGE, FL(" fail to issue disassociate with Session ID %d"),
sessionId);
eRoamState = eCsrStopRoaming;
}
}
}
else
{
// note: we used to pre-auth here with open authentication networks but that was not working so well.
// stop the existing network before attempting to join the new network...
if(!HAL_STATUS_SUCCESS(csrRoamStopNetwork(pMac, sessionId, pProfile, pBssDesc, pIesLocal)))
{
eRoamState = eCsrStopRoaming;
}
}
}//Infra
else
{
if(!HAL_STATUS_SUCCESS(csrRoamStopNetwork(pMac, sessionId, pProfile, pBssDesc, pIesLocal)))
{
eRoamState = eCsrStopRoaming;
}
}
if( pIesLocal && !pScanResult->pvIes )
{
vos_mem_free(pIesLocal);
}
}
return( eRoamState );
}
eHalStatus csrRoamShouldRoam(tpAniSirGlobal pMac, tANI_U32 sessionId,
tSirBssDescription *pBssDesc, tANI_U32 roamId)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tCsrRoamInfo roamInfo;
vos_mem_set(&roamInfo, sizeof(tCsrRoamInfo), 0);
roamInfo.pBssDesc = pBssDesc;
status = csrRoamCallCallback(pMac, sessionId, &roamInfo, roamId, eCSR_ROAM_SHOULD_ROAM, eCSR_ROAM_RESULT_NONE);
return (status);
}
//In case no matching BSS is found, use whatever default we can find
static void csrRoamAssignDefaultParam( tpAniSirGlobal pMac, tSmeCmd *pCommand )
{
//Need to get all negotiated types in place first
//auth type
switch( pCommand->u.roamCmd.roamProfile.AuthType.authType[0] ) //Take the preferred Auth type.
{
default:
case eCSR_AUTH_TYPE_WPA:
case eCSR_AUTH_TYPE_WPA_PSK:
case eCSR_AUTH_TYPE_WPA_NONE:
case eCSR_AUTH_TYPE_OPEN_SYSTEM:
pCommand->u.roamCmd.roamProfile.negotiatedAuthType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
break;
case eCSR_AUTH_TYPE_SHARED_KEY:
pCommand->u.roamCmd.roamProfile.negotiatedAuthType = eCSR_AUTH_TYPE_SHARED_KEY;
break;
case eCSR_AUTH_TYPE_AUTOSWITCH:
pCommand->u.roamCmd.roamProfile.negotiatedAuthType = eCSR_AUTH_TYPE_AUTOSWITCH;
break;
case eCSR_AUTH_TYPE_SAE:
pCommand->u.roamCmd.roamProfile.negotiatedAuthType =
eCSR_AUTH_TYPE_SAE;
break;
}
pCommand->u.roamCmd.roamProfile.negotiatedUCEncryptionType =
pCommand->u.roamCmd.roamProfile.EncryptionType.encryptionType[0];
//In this case, the multicast encryption needs to follow the uncast ones.
pCommand->u.roamCmd.roamProfile.negotiatedMCEncryptionType =
pCommand->u.roamCmd.roamProfile.EncryptionType.encryptionType[0];
}
static void csrSetAbortRoamingCommand(tpAniSirGlobal pMac, tSmeCmd *pCommand)
{
switch(pCommand->u.roamCmd.roamReason)
{
case eCsrLostLink1:
pCommand->u.roamCmd.roamReason = eCsrLostLink1Abort;
break;
case eCsrLostLink2:
pCommand->u.roamCmd.roamReason = eCsrLostLink2Abort;
break;
case eCsrLostLink3:
pCommand->u.roamCmd.roamReason = eCsrLostLink3Abort;
break;
default:
smsLog(pMac, LOGE, FL(" aborting roaming reason %d not recognized"),
pCommand->u.roamCmd.roamReason);
break;
}
}
static eCsrJoinState csrRoamJoinNextBss( tpAniSirGlobal pMac, tSmeCmd *pCommand, tANI_BOOLEAN fUseSameBss )
{
eHalStatus status;
tCsrScanResult *pScanResult = NULL;
eCsrJoinState eRoamState = eCsrStopRoaming;
tScanResultList *pBSSList = (tScanResultList *)pCommand->u.roamCmd.hBSSList;
tANI_BOOLEAN fDone = eANI_BOOLEAN_FALSE;
tCsrRoamInfo roamInfo, *pRoamInfo = NULL;
#ifndef WLAN_MDM_CODE_REDUCTION_OPT
v_U8_t acm_mask = 0;
#endif
tANI_U32 sessionId = pCommand->sessionId;
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
tCsrRoamProfile *pProfile = &pCommand->u.roamCmd.roamProfile;
tANI_U8 concurrentChannel = 0;
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return (eCsrStopRoaming);
}
do
{
// Check for Cardbus eject condition, before trying to Roam to any BSS
//***if( !balIsCardPresent(pAdapter) ) break;
vos_mem_set(&roamInfo, sizeof(roamInfo), 0);
vos_mem_copy (&roamInfo.bssid, &pSession->joinFailStatusCode.bssId, sizeof(tSirMacAddr));
if(NULL != pBSSList)
{
// When handling AP's capability change, continue to associate to
// same BSS and make sure pRoamBssEntry is not Null.
if((eANI_BOOLEAN_FALSE == fUseSameBss) || (pCommand->u.roamCmd.pRoamBssEntry == NULL))
{
if(pCommand->u.roamCmd.pRoamBssEntry == NULL)
{
//Try the first BSS
pCommand->u.roamCmd.pLastRoamBss = NULL;
pCommand->u.roamCmd.pRoamBssEntry = csrLLPeekHead(&pBSSList->List, LL_ACCESS_LOCK);
}
else
{
pCommand->u.roamCmd.pRoamBssEntry = csrLLNext(&pBSSList->List, pCommand->u.roamCmd.pRoamBssEntry, LL_ACCESS_LOCK);
if(NULL == pCommand->u.roamCmd.pRoamBssEntry)
{
//Done with all the BSSs
//In this case, will tell HDD the completion
break;
}
else
{
//We need to indicate to HDD that we are done with this one.
//vos_mem_set(&roamInfo, sizeof(tCsrRoamInfo), 0);
roamInfo.pBssDesc = pCommand->u.roamCmd.pLastRoamBss; //this shall not be NULL
roamInfo.statusCode = pSession->joinFailStatusCode.statusCode;
roamInfo.reasonCode = pSession->joinFailStatusCode.reasonCode;
pRoamInfo = &roamInfo;
}
}
while(pCommand->u.roamCmd.pRoamBssEntry)
{
pScanResult = GET_BASE_ADDR(pCommand->u.roamCmd.pRoamBssEntry, tCsrScanResult, Link);
/*If concurrency enabled take the concurrent connected channel first. */
/* Valid multichannel concurrent sessions exempted */
if (vos_concurrent_open_sessions_running() &&
!csrIsValidMcConcurrentSession(pMac, sessionId,
&pScanResult->Result.BssDescriptor))
{
concurrentChannel =
csrGetConcurrentOperationChannel(pMac);
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH, "%s: "
" csr Concurrent Channel = %d", __func__, concurrentChannel);
if ((concurrentChannel) &&
(concurrentChannel ==
pScanResult->Result.BssDescriptor.channelId))
{
//make this 0 because we do not want the
//below check to pass as we don't want to
//connect on other channel
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
FL("Concurrent channel match =%d"),
concurrentChannel);
concurrentChannel = 0;
}
}
if (!concurrentChannel)
{
if(HAL_STATUS_SUCCESS(csrRoamShouldRoam(pMac,
sessionId, &pScanResult->Result.BssDescriptor,
pCommand->u.roamCmd.roamId)))
{
//Ok to roam this
break;
}
}
else
{
eRoamState = eCsrStopRoamingDueToConcurrency;
}
pCommand->u.roamCmd.pRoamBssEntry = csrLLNext(&pBSSList->List, pCommand->u.roamCmd.pRoamBssEntry, LL_ACCESS_LOCK);
if(NULL == pCommand->u.roamCmd.pRoamBssEntry)
{
//Done with all the BSSs
fDone = eANI_BOOLEAN_TRUE;
break;
}
}
if(fDone)
{
break;
}
}
}
//We have something to roam, tell HDD when it is infra.
//For IBSS, the indication goes back to HDD via eCSR_ROAM_IBSS_IND
//For WDS, the indication is eCSR_ROAM_WDS_IND
if( CSR_IS_INFRASTRUCTURE( pProfile ) )
{
if(pRoamInfo)
{
if(pSession->bRefAssocStartCnt)
{
pSession->bRefAssocStartCnt--;
//Complete the last association attemp because a new one is about to be tried
csrRoamCallCallback(pMac, sessionId, pRoamInfo, pCommand->u.roamCmd.roamId,
eCSR_ROAM_ASSOCIATION_COMPLETION,
eCSR_ROAM_RESULT_NOT_ASSOCIATED);
}
}
/* If the roaming has stopped, not to continue the roaming command*/
if ( !CSR_IS_ROAMING(pSession) && CSR_IS_ROAMING_COMMAND(pCommand) )
{
//No need to complete roaming here as it already completes
smsLog(pMac, LOGW, FL(" Roam command (reason %d) aborted due to roaming completed"),
pCommand->u.roamCmd.roamReason);
eRoamState = eCsrStopRoaming;
csrSetAbortRoamingCommand(pMac, pCommand);
break;
}
vos_mem_set(&roamInfo, sizeof(roamInfo), 0);
if(pScanResult)
{
tDot11fBeaconIEs *pIesLocal = (tDot11fBeaconIEs *)pScanResult->Result.pvIes;
if( !pIesLocal && (!HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, &pScanResult->Result.BssDescriptor, &pIesLocal))) )
{
smsLog(pMac, LOGE, FL(" cannot parse IEs"));
fDone = eANI_BOOLEAN_TRUE;
eRoamState = eCsrStopRoaming;
break;
}
roamInfo.pBssDesc = &pScanResult->Result.BssDescriptor;
pCommand->u.roamCmd.pLastRoamBss = roamInfo.pBssDesc;
//No need to put uapsd_mask in if the BSS doesn't support uAPSD
if( pCommand->u.roamCmd.roamProfile.uapsd_mask &&
CSR_IS_QOS_BSS(pIesLocal) &&
CSR_IS_UAPSD_BSS(pIesLocal) )
{
#ifndef WLAN_MDM_CODE_REDUCTION_OPT
acm_mask = sme_QosGetACMMask(pMac, &pScanResult->Result.BssDescriptor,
pIesLocal);
#endif /* WLAN_MDM_CODE_REDUCTION_OPT*/
}
else
{
pCommand->u.roamCmd.roamProfile.uapsd_mask = 0;
}
if( pIesLocal && !pScanResult->Result.pvIes)
{
vos_mem_free(pIesLocal);
}
}
else
{
pCommand->u.roamCmd.roamProfile.uapsd_mask = 0;
}
roamInfo.pProfile = pProfile;
pSession->bRefAssocStartCnt++;
csrRoamCallCallback( pMac, sessionId, &roamInfo, pCommand->u.roamCmd.roamId,
eCSR_ROAM_ASSOCIATION_START, eCSR_ROAM_RESULT_NONE );
}
if ( NULL == pCommand->u.roamCmd.pRoamBssEntry )
{
// If this is a start IBSS profile, then we need to start the IBSS.
if ( CSR_IS_START_IBSS(pProfile) )
{
tANI_BOOLEAN fSameIbss = eANI_BOOLEAN_FALSE;
// Attempt to start this IBSS...
csrRoamAssignDefaultParam( pMac, pCommand );
status = csrRoamStartIbss( pMac, sessionId, pProfile, &fSameIbss );
if(HAL_STATUS_SUCCESS(status))
{
if ( fSameIbss )
{
eRoamState = eCsrStartIbssSameIbss;
}
else
{
eRoamState = eCsrContinueRoaming;
}
}
else
{
//it somehow fail need to stop
eRoamState = eCsrStopRoaming;
}
break;
}
else if ( (CSR_IS_WDS_AP(pProfile))
|| (CSR_IS_INFRA_AP(pProfile))
)
{
// Attempt to start this WDS...
csrRoamAssignDefaultParam( pMac, pCommand );
/* For AP WDS, we dont have any BSSDescription */
status = csrRoamStartWds( pMac, sessionId, pProfile, NULL );
if(HAL_STATUS_SUCCESS(status))
{
eRoamState = eCsrContinueRoaming;
}
else
{
//it somehow fail need to stop
eRoamState = eCsrStopRoaming;
}
}
else
{
//Nothing we can do
smsLog(pMac, LOGW, FL("cannot continue without BSS list"));
eRoamState = eCsrStopRoaming;
break;
}
}
else //We have BSS
{
//Need to assign these value because they are used in csrIsSameProfile
pScanResult = GET_BASE_ADDR(pCommand->u.roamCmd.pRoamBssEntry, tCsrScanResult, Link);
/* The OSEN IE doesn't provide the cipher suite.
* Therefore set to constant value of AES */
if(pCommand->u.roamCmd.roamProfile.bOSENAssociation)
{
pCommand->u.roamCmd.roamProfile.negotiatedUCEncryptionType =
eCSR_ENCRYPT_TYPE_AES;
pCommand->u.roamCmd.roamProfile.negotiatedMCEncryptionType =
eCSR_ENCRYPT_TYPE_AES;
}
else
{
pCommand->u.roamCmd.roamProfile.negotiatedUCEncryptionType =
pScanResult->ucEncryptionType; //Negotiated while building scan result.
pCommand->u.roamCmd.roamProfile.negotiatedMCEncryptionType =
pScanResult->mcEncryptionType;
}
pCommand->u.roamCmd.roamProfile.negotiatedAuthType = pScanResult->authType;
if ( CSR_IS_START_IBSS(&pCommand->u.roamCmd.roamProfile) )
{
if(csrIsSameProfile(pMac, &pSession->connectedProfile, pProfile))
{
eRoamState = eCsrStartIbssSameIbss;
break;
}
}
if( pCommand->u.roamCmd.fReassocToSelfNoCapChange )
{
//trying to connect to the one already connected
pCommand->u.roamCmd.fReassocToSelfNoCapChange = eANI_BOOLEAN_FALSE;
eRoamState = eCsrReassocToSelfNoCapChange;
break;
}
// Attempt to Join this Bss...
eRoamState = csrRoamJoin( pMac, sessionId, &pScanResult->Result, pProfile );
break;
}
} while( 0 );
if( (eCsrStopRoaming == eRoamState) && (CSR_IS_INFRASTRUCTURE( pProfile )) )
{
//Need to indicate association_completion if association_start has been done
if(pSession->bRefAssocStartCnt > 0)
{
pSession->bRefAssocStartCnt--;
//Complete the last association attemp because a new one is about to be tried
pRoamInfo = &roamInfo;
csrRoamCallCallback(pMac, sessionId, pRoamInfo, pCommand->u.roamCmd.roamId,
eCSR_ROAM_ASSOCIATION_COMPLETION,
eCSR_ROAM_RESULT_NOT_ASSOCIATED);
}
}
return( eRoamState );
}
static eHalStatus csrRoam( tpAniSirGlobal pMac, tSmeCmd *pCommand )
{
eHalStatus status = eHAL_STATUS_SUCCESS;
eCsrJoinState RoamState;
tANI_U32 sessionId = pCommand->sessionId;
//***if( hddIsRadioStateOn( pAdapter ) )
{
// Attept to join a Bss...
RoamState = csrRoamJoinNextBss( pMac, pCommand, eANI_BOOLEAN_FALSE );
// if nothing to join..
if (( eCsrStopRoaming == RoamState ) || ( eCsrStopRoamingDueToConcurrency == RoamState))
{
tANI_BOOLEAN fComplete = eANI_BOOLEAN_FALSE;
// and if connected in Infrastructure mode...
if ( csrIsConnStateInfra(pMac, sessionId) )
{
//... then we need to issue a disassociation
status = csrRoamIssueDisassociate( pMac, sessionId, eCSR_ROAM_SUBSTATE_DISASSOC_NOTHING_TO_JOIN, FALSE );
if(!HAL_STATUS_SUCCESS(status))
{
smsLog(pMac, LOGW, FL(" failed to issue disassociate, status = %d"), status);
//roam command is completed by caller in the failed case
fComplete = eANI_BOOLEAN_TRUE;
}
}
else if( csrIsConnStateIbss(pMac, sessionId) )
{
status = csrRoamIssueStopBss( pMac, sessionId, eCSR_ROAM_SUBSTATE_STOP_BSS_REQ );
if(!HAL_STATUS_SUCCESS(status))
{
smsLog(pMac, LOGW, FL(" failed to issue stop bss, status = %d"), status);
//roam command is completed by caller in the failed case
fComplete = eANI_BOOLEAN_TRUE;
}
}
else if (csrIsConnStateConnectedInfraAp(pMac, sessionId))
{
status = csrRoamIssueStopBss( pMac, sessionId, eCSR_ROAM_SUBSTATE_STOP_BSS_REQ );
if(!HAL_STATUS_SUCCESS(status))
{
smsLog(pMac, LOGW, FL(" failed to issue stop bss, status = %d"), status);
//roam command is completed by caller in the failed case
fComplete = eANI_BOOLEAN_TRUE;
}
}
else
{
fComplete = eANI_BOOLEAN_TRUE;
}
if(fComplete)
{
// ... otherwise, we can complete the Roam command here.
if(eCsrStopRoamingDueToConcurrency == RoamState)
{
csrRoamComplete( pMac, eCsrJoinFailureDueToConcurrency, NULL );
}
else
{
csrRoamComplete( pMac, eCsrNothingToJoin, NULL );
}
}
}
else if ( eCsrReassocToSelfNoCapChange == RoamState )
{
csrRoamComplete( pMac, eCsrSilentlyStopRoamingSaveState, NULL );
}
else if ( eCsrStartIbssSameIbss == RoamState )
{
csrRoamComplete( pMac, eCsrSilentlyStopRoaming, NULL );
}
}//hddIsRadioStateOn
return status;
}
eHalStatus csrProcessFTReassocRoamCommand ( tpAniSirGlobal pMac, tSmeCmd *pCommand )
{
tANI_U32 sessionId;
tCsrRoamSession *pSession = NULL;
tCsrScanResult *pScanResult = NULL;
tSirBssDescription *pBssDesc = NULL;
eHalStatus status = eHAL_STATUS_SUCCESS;
sessionId = pCommand->sessionId;
pSession = CSR_GET_SESSION( pMac, sessionId );
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return eHAL_STATUS_FAILURE;
}
if(CSR_IS_ROAMING(pSession) && pSession->fCancelRoaming)
{
//the roaming is cancelled. Simply complete the command
smsLog(pMac, LOG1, FL(" Roam command cancelled"));
csrRoamComplete(pMac, eCsrNothingToJoin, NULL);
return eHAL_STATUS_FAILURE;
}
if (pCommand->u.roamCmd.pRoamBssEntry)
{
pScanResult = GET_BASE_ADDR(pCommand->u.roamCmd.pRoamBssEntry, tCsrScanResult, Link);
pBssDesc = &pScanResult->Result.BssDescriptor;
}
else
{
//the roaming is cancelled. Simply complete the command
smsLog(pMac, LOG1, FL(" Roam command cancelled"));
csrRoamComplete(pMac, eCsrNothingToJoin, NULL);
return eHAL_STATUS_FAILURE;
}
status = csrRoamIssueReassociate(pMac, sessionId, pBssDesc,
(tDot11fBeaconIEs *)( pScanResult->Result.pvIes ), &pCommand->u.roamCmd.roamProfile);
return status;
}
eHalStatus csrRoamProcessCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand )
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tCsrRoamInfo roamInfo;
tANI_U32 sessionId = pCommand->sessionId;
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return eHAL_STATUS_FAILURE;
}
smsLog(pMac, LOG1, FL("Roam Reason : %d, sessionId: %d"),
pCommand->u.roamCmd.roamReason, sessionId);
switch ( pCommand->u.roamCmd.roamReason )
{
case eCsrForcedDisassoc:
status = csrRoamProcessDisassocDeauth( pMac, pCommand, TRUE, FALSE );
csrFreeRoamProfile(pMac, sessionId);
break;
case eCsrSmeIssuedDisassocForHandoff:
//Not to free pMac->roam.pCurRoamProfile (via csrFreeRoamProfile) because it is needed after disconnect
#if 0 // TODO : Confirm this change
status = csrRoamProcessDisassociate( pMac, pCommand, FALSE );
#else
status = csrRoamProcessDisassocDeauth( pMac, pCommand, TRUE, FALSE );
#endif
break;
case eCsrForcedDisassocMICFailure:
status = csrRoamProcessDisassocDeauth( pMac, pCommand, TRUE, TRUE );
csrFreeRoamProfile(pMac, sessionId);
break;
case eCsrForcedDeauth:
status = csrRoamProcessDisassocDeauth( pMac, pCommand, FALSE, FALSE );
csrFreeRoamProfile(pMac, sessionId);
break;
case eCsrHddIssuedReassocToSameAP:
case eCsrSmeIssuedReassocToSameAP:
{
tDot11fBeaconIEs *pIes = NULL;
if( pSession->pConnectBssDesc )
{
status = csrGetParsedBssDescriptionIEs(pMac, pSession->pConnectBssDesc, &pIes);
if(!HAL_STATUS_SUCCESS(status) )
{
smsLog(pMac, LOGE, FL(" fail to parse IEs"));
}
else
{
roamInfo.reasonCode = eCsrRoamReasonStaCapabilityChanged;
csrRoamCallCallback(pMac, pSession->sessionId, &roamInfo, 0, eCSR_ROAM_ROAMING_START, eCSR_ROAM_RESULT_NONE);
pSession->roamingReason = eCsrReassocRoaming;
roamInfo.pBssDesc = pSession->pConnectBssDesc;
roamInfo.pProfile = &pCommand->u.roamCmd.roamProfile;
pSession->bRefAssocStartCnt++;
csrRoamCallCallback( pMac, sessionId, &roamInfo, pCommand->u.roamCmd.roamId,
eCSR_ROAM_ASSOCIATION_START, eCSR_ROAM_RESULT_NONE );
smsLog(pMac, LOG1, FL(" calling csrRoamIssueReassociate"));
status = csrRoamIssueReassociate( pMac, sessionId, pSession->pConnectBssDesc, pIes,
&pCommand->u.roamCmd.roamProfile );
if(!HAL_STATUS_SUCCESS(status))
{
smsLog(pMac, LOGE, FL("csrRoamIssueReassociate failed with status %d"), status);
csrReleaseCommandRoam( pMac, pCommand );
}
vos_mem_free(pIes);
pIes = NULL;
}
}
else
status = eHAL_STATUS_FAILURE;
break;
}
case eCsrCapsChange:
smsLog(pMac, LOGE, FL("received eCsrCapsChange "));
csrRoamStateChange( pMac, eCSR_ROAMING_STATE_JOINING, sessionId );
status = csrRoamIssueDisassociate( pMac, sessionId, eCSR_ROAM_SUBSTATE_DISCONNECT_CONTINUE_ROAMING, FALSE);
break;
case eCsrSmeIssuedFTReassoc:
smsLog(pMac, LOG1, FL("received FT Reassoc Req "));
status = csrProcessFTReassocRoamCommand(pMac, pCommand);
break;
case eCsrStopBss:
csrRoamStateChange( pMac, eCSR_ROAMING_STATE_JOINING, sessionId);
status = csrRoamIssueStopBss( pMac, sessionId, eCSR_ROAM_SUBSTATE_STOP_BSS_REQ );
break;
case eCsrForcedDisassocSta:
csrRoamStateChange( pMac, eCSR_ROAMING_STATE_JOINING, sessionId);
csrRoamSubstateChange( pMac, eCSR_ROAM_SUBSTATE_DISASSOC_REQ, sessionId);
status = csrSendMBDisassocReqMsg( pMac, sessionId, pCommand->u.roamCmd.peerMac,
pCommand->u.roamCmd.reason);
break;
case eCsrForcedDeauthSta:
csrRoamStateChange( pMac, eCSR_ROAMING_STATE_JOINING, sessionId);
csrRoamSubstateChange( pMac, eCSR_ROAM_SUBSTATE_DEAUTH_REQ, sessionId);
status = csrSendMBDeauthReqMsg( pMac, sessionId, pCommand->u.roamCmd.peerMac,
pCommand->u.roamCmd.reason);
break;
case eCsrPerformPreauth:
smsLog(pMac, LOG1, FL("Attempting FT PreAuth Req"));
status = csrRoamIssueFTPreauthReq(pMac, sessionId,
pCommand->u.roamCmd.pLastRoamBss);
break;
#ifdef WLAN_FEATURE_LFR_MBB
case ecsr_mbb_perform_preauth_reassoc:
smsLog(pMac, LOG1, FL("Attempting MBB PreAuth/Reassoc Req"));
status = csr_roam_issue_preauth_reassoc_req(pMac, sessionId,
pCommand->u.roamCmd.pLastRoamBss);
if (eHAL_STATUS_SUCCESS != status)
{
pMac->ft.ftSmeContext.is_preauth_lfr_mbb = false;
smsLog(pMac, LOG1, FL("is_preauth_lfr_mbb %d"),
pMac->ft.ftSmeContext.is_preauth_lfr_mbb);
}
break;
#endif
default:
csrRoamStateChange( pMac, eCSR_ROAMING_STATE_JOINING, sessionId );
if( pCommand->u.roamCmd.fUpdateCurRoamProfile )
{
//Remember the roaming profile
csrFreeRoamProfile(pMac, sessionId);
pSession->pCurRoamProfile = vos_mem_malloc(sizeof(tCsrRoamProfile));
if ( NULL != pSession->pCurRoamProfile )
{
vos_mem_set(pSession->pCurRoamProfile, sizeof(tCsrRoamProfile), 0);
csrRoamCopyProfile(pMac, pSession->pCurRoamProfile, &pCommand->u.roamCmd.roamProfile);
}
}
//At this point, original uapsd_mask is saved in pCurRoamProfile
//uapsd_mask in the pCommand may change from this point on.
// Attempt to roam with the new scan results (if we need to..)
status = csrRoam( pMac, pCommand );
if(!HAL_STATUS_SUCCESS(status))
{
smsLog(pMac, LOGW, FL("csrRoam() failed with status = 0x%08X"), status);
}
break;
}
return (status);
}
void csrReinitPreauthCmd(tpAniSirGlobal pMac, tSmeCmd *pCommand)
{
pCommand->u.roamCmd.pLastRoamBss = NULL;
pCommand->u.roamCmd.pRoamBssEntry = NULL;
//Because u.roamCmd is union and share with scanCmd and StatusChange
vos_mem_set(&pCommand->u.roamCmd, sizeof(tRoamCmd), 0);
}
void csrReinitRoamCmd(tpAniSirGlobal pMac, tSmeCmd *pCommand)
{
if(pCommand->u.roamCmd.fReleaseBssList)
{
csrScanResultPurge(pMac, pCommand->u.roamCmd.hBSSList);
pCommand->u.roamCmd.fReleaseBssList = eANI_BOOLEAN_FALSE;
pCommand->u.roamCmd.hBSSList = CSR_INVALID_SCANRESULT_HANDLE;
}
if(pCommand->u.roamCmd.fReleaseProfile)
{
csrReleaseProfile(pMac, &pCommand->u.roamCmd.roamProfile);
pCommand->u.roamCmd.fReleaseProfile = eANI_BOOLEAN_FALSE;
}
pCommand->u.roamCmd.pRoamBssEntry = NULL;
//Because u.roamCmd is union and share with scanCmd and StatusChange
vos_mem_set(&pCommand->u.roamCmd, sizeof(tRoamCmd), 0);
}
void csrReinitWmStatusChangeCmd(tpAniSirGlobal pMac, tSmeCmd *pCommand)
{
vos_mem_set(&pCommand->u.wmStatusChangeCmd, sizeof(tWmStatusChangeCmd), 0);
}
void csrRoamComplete( tpAniSirGlobal pMac, eCsrRoamCompleteResult Result, void *Context )
{
tListElem *pEntry;
tSmeCmd *pCommand;
tANI_BOOLEAN fReleaseCommand = eANI_BOOLEAN_TRUE;
smsLog( pMac, LOG2, "Roam Completion ..." );
pEntry = csrLLPeekHead( &pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK );
if ( pEntry )
{
pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link );
// If the head of the queue is Active and it is a ROAM command, remove
// and put this on the Free queue.
if ( eSmeCommandRoam == pCommand->command )
{
//we need to process the result first before removing it from active list because state changes
//still happening insides roamQProcessRoamResults so no other roam command should be issued
fReleaseCommand = csrRoamProcessResults( pMac, pCommand, Result, Context );
if( fReleaseCommand )
{
if( csrLLRemoveEntry( &pMac->sme.smeCmdActiveList, pEntry, LL_ACCESS_LOCK ) )
{
csrReleaseCommandRoam( pMac, pCommand );
}
else
{
smsLog( pMac, LOGE, " **********csrRoamComplete fail to release command reason %d",
pCommand->u.roamCmd.roamReason );
}
}
else
{
smsLog( pMac, LOGE, " **********csrRoamComplete fail to release command reason %d",
pCommand->u.roamCmd.roamReason );
}
}
else
{
smsLog( pMac, LOGW, "CSR: Roam Completion called but ROAM command is not ACTIVE ..." );
}
}
else
{
smsLog( pMac, LOGW, "CSR: Roam Completion called but NO commands are ACTIVE ..." );
}
if( fReleaseCommand )
{
smeProcessPendingQueue( pMac );
}
}
void csrResetPMKIDCandidateList( tpAniSirGlobal pMac, tANI_U32 sessionId )
{
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return;
}
vos_mem_set(&(pSession->PmkidCandidateInfo[0]),
sizeof(tPmkidCandidateInfo) * CSR_MAX_PMKID_ALLOWED, 0);
pSession->NumPmkidCandidate = 0;
}
#ifdef FEATURE_WLAN_WAPI
void csrResetBKIDCandidateList( tpAniSirGlobal pMac, tANI_U32 sessionId )
{
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return;
}
vos_mem_set(&(pSession->BkidCandidateInfo[0]),
sizeof(tBkidCandidateInfo) * CSR_MAX_BKID_ALLOWED, 0);
pSession->NumBkidCandidate = 0;
}
#endif /* FEATURE_WLAN_WAPI */
extern tANI_U8 csrWpaOui[][ CSR_WPA_OUI_SIZE ];
eHalStatus csrRoamSaveSecurityRspIE(tpAniSirGlobal pMac,
tANI_U32 sessionId, eCsrAuthType authType,
tSirBssDescription *pSirBssDesc,
tDot11fBeaconIEs *pIes)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
tDot11fBeaconIEs *pIesLocal = pIes;
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return eHAL_STATUS_FAILURE;
}
if((eCSR_AUTH_TYPE_WPA == authType) ||
(eCSR_AUTH_TYPE_WPA_PSK == authType) ||
(eCSR_AUTH_TYPE_RSN == authType) ||
(eCSR_AUTH_TYPE_RSN_PSK == authType)
#if defined WLAN_FEATURE_VOWIFI_11R
||
(eCSR_AUTH_TYPE_FT_RSN == authType) ||
(eCSR_AUTH_TYPE_FT_RSN_PSK == authType)
#endif /* FEATURE_WLAN_WAPI */
#ifdef FEATURE_WLAN_WAPI
||
(eCSR_AUTH_TYPE_WAPI_WAI_PSK == authType) ||
(eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE == authType)
#endif /* FEATURE_WLAN_WAPI */
#ifdef WLAN_FEATURE_11W
||
(eCSR_AUTH_TYPE_RSN_PSK_SHA256 == authType) ||
(eCSR_AUTH_TYPE_RSN_8021X_SHA256 == authType)
#endif /* FEATURE_WLAN_WAPI */
|| (eCSR_AUTH_TYPE_SAE == authType))
{
if( !pIesLocal && (!HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, pSirBssDesc, &pIesLocal))) )
{
smsLog(pMac, LOGE, FL(" cannot parse IEs"));
}
if( pIesLocal )
{
tANI_U32 nIeLen;
tANI_U8 *pIeBuf;
if((eCSR_AUTH_TYPE_RSN == authType) ||
#if defined WLAN_FEATURE_VOWIFI_11R
(eCSR_AUTH_TYPE_FT_RSN == authType) ||
(eCSR_AUTH_TYPE_FT_RSN_PSK == authType) ||
#endif /* WLAN_FEATURE_VOWIFI_11R */
#if defined WLAN_FEATURE_11W
(eCSR_AUTH_TYPE_RSN_PSK_SHA256 == authType) ||
(eCSR_AUTH_TYPE_RSN_8021X_SHA256 == authType) ||
#endif
(eCSR_AUTH_TYPE_RSN_PSK == authType))
{
if(pIesLocal->RSN.present)
{
//Calculate the actual length
nIeLen = 8 //version + gp_cipher_suite + pwise_cipher_suite_count
+ pIesLocal->RSN.pwise_cipher_suite_count * 4 //pwise_cipher_suites
+ 2 //akm_suite_count
+ pIesLocal->RSN.akm_suite_cnt * 4 //akm_suites
+ 2; //reserved
if( pIesLocal->RSN.pmkid_count )
{
nIeLen += 2 + pIesLocal->RSN.pmkid_count * 4; //pmkid
}
//nIeLen doesn't count EID and length fields
pSession->pWpaRsnRspIE = vos_mem_malloc(nIeLen + 2);
if (NULL == pSession->pWpaRsnRspIE)
status = eHAL_STATUS_FAILURE;
else
{
vos_mem_set(pSession->pWpaRsnRspIE, nIeLen + 2, 0);
pSession->pWpaRsnRspIE[0] = DOT11F_EID_RSN;
pSession->pWpaRsnRspIE[1] = (tANI_U8)nIeLen;
//copy upto akm_suite
pIeBuf = pSession->pWpaRsnRspIE + 2;
vos_mem_copy(pIeBuf, &pIesLocal->RSN.version,
sizeof(pIesLocal->RSN.version));
pIeBuf += sizeof(pIesLocal->RSN.version);
vos_mem_copy(pIeBuf, &pIesLocal->RSN.gp_cipher_suite,
sizeof(pIesLocal->RSN.gp_cipher_suite));
pIeBuf += sizeof(pIesLocal->RSN.gp_cipher_suite);
vos_mem_copy(pIeBuf, &pIesLocal->RSN.pwise_cipher_suite_count,
sizeof(pIesLocal->RSN.pwise_cipher_suite_count));
pIeBuf += sizeof(pIesLocal->RSN.pwise_cipher_suite_count );
if( pIesLocal->RSN.pwise_cipher_suite_count )
{
//copy pwise_cipher_suites
vos_mem_copy(pIeBuf,
pIesLocal->RSN.pwise_cipher_suites,
pIesLocal->RSN.pwise_cipher_suite_count * 4);
pIeBuf += pIesLocal->RSN.pwise_cipher_suite_count * 4;
}
vos_mem_copy(pIeBuf, &pIesLocal->RSN.akm_suite_cnt, 2);
pIeBuf += 2;
if( pIesLocal->RSN.akm_suite_cnt )
{
//copy akm_suite
vos_mem_copy(pIeBuf,
pIesLocal->RSN.akm_suite,
pIesLocal->RSN.akm_suite_cnt * 4);
pIeBuf += pIesLocal->RSN.akm_suite_cnt * 4;
}
//copy the rest
vos_mem_copy(pIeBuf,
pIesLocal->RSN.akm_suite + pIesLocal->RSN.akm_suite_cnt * 4,
2 + pIesLocal->RSN.pmkid_count * 4);
pSession->nWpaRsnRspIeLength = nIeLen + 2;
}
}
}
else if((eCSR_AUTH_TYPE_WPA == authType) ||
(eCSR_AUTH_TYPE_WPA_PSK == authType))
{
if(pIesLocal->WPA.present)
{
//Calculate the actual length
nIeLen = 12 //OUI + version + multicast_cipher + unicast_cipher_count
+ pIesLocal->WPA.unicast_cipher_count * 4 //unicast_ciphers
+ 2 //auth_suite_count
+ pIesLocal->WPA.auth_suite_count * 4; //auth_suites
// The WPA capabilities follows the Auth Suite (two octects)--
// this field is optional, and we always "send" zero, so just
// remove it. This is consistent with our assumptions in the
// frames compiler; c.f. bug 15234:
//nIeLen doesn't count EID and length fields
pSession->pWpaRsnRspIE = vos_mem_malloc(nIeLen + 2);
if ( NULL == pSession->pWpaRsnRspIE )
status = eHAL_STATUS_FAILURE;
else
{
pSession->pWpaRsnRspIE[0] = DOT11F_EID_WPA;
pSession->pWpaRsnRspIE[1] = (tANI_U8)nIeLen;
pIeBuf = pSession->pWpaRsnRspIE + 2;
//Copy WPA OUI
vos_mem_copy(pIeBuf, &csrWpaOui[1], 4);
pIeBuf += 4;
vos_mem_copy(pIeBuf, &pIesLocal->WPA.version,
8 + pIesLocal->WPA.unicast_cipher_count * 4);
pIeBuf += 8 + pIesLocal->WPA.unicast_cipher_count * 4;
vos_mem_copy(pIeBuf, &pIesLocal->WPA.auth_suite_count,
2 + pIesLocal->WPA.auth_suite_count * 4);
pIeBuf += pIesLocal->WPA.auth_suite_count * 4;
pSession->nWpaRsnRspIeLength = nIeLen + 2;
}
}
}
#ifdef FEATURE_WLAN_WAPI
else if((eCSR_AUTH_TYPE_WAPI_WAI_PSK == authType) ||
(eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE == authType))
{
if(pIesLocal->WAPI.present)
{
//Calculate the actual length
nIeLen = 4 //version + akm_suite_count
+ pIesLocal->WAPI.akm_suite_count * 4 // akm_suites
+ 2 //pwise_cipher_suite_count
+ pIesLocal->WAPI.unicast_cipher_suite_count * 4 //pwise_cipher_suites
+ 6; //gp_cipher_suite + preauth + reserved
if( pIesLocal->WAPI.bkid_count )
{
nIeLen += 2 + pIesLocal->WAPI.bkid_count * 4; //bkid
}
//nIeLen doesn't count EID and length fields
pSession->pWapiRspIE = vos_mem_malloc(nIeLen + 2);
if ( NULL == pSession->pWapiRspIE )
status = eHAL_STATUS_FAILURE;
else
{
pSession->pWapiRspIE[0] = DOT11F_EID_WAPI;
pSession->pWapiRspIE[1] = (tANI_U8)nIeLen;
pIeBuf = pSession->pWapiRspIE + 2;
//copy upto akm_suite_count
vos_mem_copy(pIeBuf, &pIesLocal->WAPI.version, 2);
pIeBuf += 4;
if( pIesLocal->WAPI.akm_suite_count )
{
//copy akm_suites
vos_mem_copy(pIeBuf, pIesLocal->WAPI.akm_suites,
pIesLocal->WAPI.akm_suite_count * 4);
pIeBuf += pIesLocal->WAPI.akm_suite_count * 4;
}
vos_mem_copy(pIeBuf,
&pIesLocal->WAPI.unicast_cipher_suite_count,
2);
pIeBuf += 2;
if( pIesLocal->WAPI.unicast_cipher_suite_count )
{
//copy pwise_cipher_suites
vos_mem_copy( pIeBuf,
pIesLocal->WAPI.unicast_cipher_suites,
pIesLocal->WAPI.unicast_cipher_suite_count * 4);
pIeBuf += pIesLocal->WAPI.unicast_cipher_suite_count * 4;
}
//gp_cipher_suite
vos_mem_copy(pIeBuf,
pIesLocal->WAPI.multicast_cipher_suite,
4);
pIeBuf += 4;
//preauth + reserved
vos_mem_copy(pIeBuf,
pIesLocal->WAPI.multicast_cipher_suite + 4,
2);
pIeBuf += 2;
if ( pIesLocal->WAPI.bkid_count )
{
//bkid_count
vos_mem_copy(pIeBuf, &pIesLocal->WAPI.bkid_count, 2);
pIeBuf += 2;
//copy akm_suites
vos_mem_copy(pIeBuf, pIesLocal->WAPI.bkid,
pIesLocal->WAPI.bkid_count * 4);
pIeBuf += pIesLocal->WAPI.bkid_count * 4;
}
pSession->nWapiRspIeLength = nIeLen + 2;
}
}
}
#endif /* FEATURE_WLAN_WAPI */
if( !pIes )
{
//locally allocated
vos_mem_free(pIesLocal);
}
}
}
return (status);
}
static void csrCheckAndUpdateACWeight( tpAniSirGlobal pMac, tDot11fBeaconIEs *pIEs )
{
v_U8_t bACWeights[WLANTL_MAX_AC];
v_U8_t paramBk, paramBe, paramVi, paramVo;
v_BOOL_t fWeightChange = VOS_FALSE;
//Compare two ACs' EDCA parameters, from low to high (BK, BE, VI, VO)
//The "formula" is, if lower AC's AIFSN+CWMin is bigger than a fixed amount
//of the higher AC one, make the higher AC has the same weight as the lower AC.
//This doesn't address the case where the lower AC needs a real higher weight
if( pIEs->WMMParams.present )
{
//no change to the lowest ones
bACWeights[WLANTL_AC_BK] = pMac->roam.ucACWeights[WLANTL_AC_BK];
bACWeights[WLANTL_AC_BE] = pMac->roam.ucACWeights[WLANTL_AC_BE];
bACWeights[WLANTL_AC_VI] = pMac->roam.ucACWeights[WLANTL_AC_VI];
bACWeights[WLANTL_AC_VO] = pMac->roam.ucACWeights[WLANTL_AC_VO];
paramBk = pIEs->WMMParams.acbk_aifsn + pIEs->WMMParams.acbk_acwmin;
paramBe = pIEs->WMMParams.acbe_aifsn + pIEs->WMMParams.acbe_acwmin;
paramVi = pIEs->WMMParams.acvi_aifsn + pIEs->WMMParams.acvi_acwmin;
paramVo = pIEs->WMMParams.acvo_aifsn + pIEs->WMMParams.acvo_acwmin;
if( SME_DETECT_AC_WEIGHT_DIFF(paramBk, paramBe) )
{
bACWeights[WLANTL_AC_BE] = bACWeights[WLANTL_AC_BK];
fWeightChange = VOS_TRUE;
}
if( SME_DETECT_AC_WEIGHT_DIFF(paramBk, paramVi) )
{
bACWeights[WLANTL_AC_VI] = bACWeights[WLANTL_AC_BK];
fWeightChange = VOS_TRUE;
}
else if( SME_DETECT_AC_WEIGHT_DIFF(paramBe, paramVi) )
{
bACWeights[WLANTL_AC_VI] = bACWeights[WLANTL_AC_BE];
fWeightChange = VOS_TRUE;
}
if( SME_DETECT_AC_WEIGHT_DIFF(paramBk, paramVo) )
{
bACWeights[WLANTL_AC_VO] = bACWeights[WLANTL_AC_BK];
fWeightChange = VOS_TRUE;
}
else if( SME_DETECT_AC_WEIGHT_DIFF(paramBe, paramVo) )
{
bACWeights[WLANTL_AC_VO] = bACWeights[WLANTL_AC_BE];
fWeightChange = VOS_TRUE;
}
else if( SME_DETECT_AC_WEIGHT_DIFF(paramVi, paramVo) )
{
bACWeights[WLANTL_AC_VO] = bACWeights[WLANTL_AC_VI];
fWeightChange = VOS_TRUE;
}
if(fWeightChange)
{
smsLog(pMac, LOGE, FL(" change AC weights (%d-%d-%d-%d)"), bACWeights[0], bACWeights[1],
bACWeights[2], bACWeights[3]);
WLANTL_SetACWeights(pMac->roam.gVosContext, bACWeights);
}
}
}
#ifdef WLAN_FEATURE_VOWIFI_11R
//Returns whether the current association is a 11r assoc or not
tANI_BOOLEAN csrRoamIs11rAssoc(tpAniSirGlobal pMac)
{
#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
return csrNeighborRoamIs11rAssoc(pMac);
#else
return eANI_BOOLEAN_FALSE;
#endif
}
#endif
#ifdef FEATURE_WLAN_ESE
//Returns whether the current association is a ESE assoc or not
tANI_BOOLEAN csrRoamIsESEAssoc(tpAniSirGlobal pMac)
{
#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
return csrNeighborRoamIsESEAssoc(pMac);
#else
return eANI_BOOLEAN_FALSE;
#endif
}
#endif
#ifdef FEATURE_WLAN_LFR
//Returns whether "Legacy Fast Roaming" is currently enabled...or not
tANI_BOOLEAN csrRoamIsFastRoamEnabled(tpAniSirGlobal pMac, tANI_U32 sessionId)
{
tCsrRoamSession *pSession = NULL;
if (CSR_IS_SESSION_VALID( pMac, sessionId ) )
{
pSession = CSR_GET_SESSION( pMac, sessionId );
if (NULL != pSession->pCurRoamProfile)
{
if (pSession->pCurRoamProfile->csrPersona != VOS_STA_MODE)
{
return eANI_BOOLEAN_FALSE;
}
}
}
#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
if (eANI_BOOLEAN_TRUE == CSR_IS_FASTROAM_IN_CONCURRENCY_INI_FEATURE_ENABLED(pMac))
{
return (pMac->roam.configParam.isFastRoamIniFeatureEnabled);
}
else
#endif
{
return (pMac->roam.configParam.isFastRoamIniFeatureEnabled &&
(!csrIsConcurrentSessionRunning(pMac)));
}
}
#ifdef FEATURE_WLAN_ESE
/* ---------------------------------------------------------------------------
\fn csrNeighborRoamIsESEAssoc
\brief This function returns whether the current association is a ESE assoc or not
\param pMac - The handle returned by macOpen.
\return eANI_BOOLEAN_TRUE if current assoc is ESE, eANI_BOOLEAN_FALSE otherwise
---------------------------------------------------------------------------*/
tANI_BOOLEAN csrNeighborRoamIsESEAssoc(tpAniSirGlobal pMac)
{
return pMac->roam.neighborRoamInfo.isESEAssoc;
}
#endif /* FEATURE_WLAN_ESE */
#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
//Returns whether "FW based BG scan" is currently enabled...or not
tANI_BOOLEAN csrRoamIsRoamOffloadScanEnabled(tpAniSirGlobal pMac)
{
return (pMac->roam.configParam.isRoamOffloadScanEnabled);
}
#endif
#endif
#if defined(FEATURE_WLAN_ESE)
tANI_BOOLEAN csrRoamIsEseIniFeatureEnabled(tpAniSirGlobal pMac)
{
return pMac->roam.configParam.isEseIniFeatureEnabled;
}
#endif /*FEATURE_WLAN_ESE*/
//Return true means the command can be release, else not
static tANI_BOOLEAN csrRoamProcessResults( tpAniSirGlobal pMac, tSmeCmd *pCommand,
eCsrRoamCompleteResult Result, void *Context )
{
tANI_BOOLEAN fReleaseCommand = eANI_BOOLEAN_TRUE;
tSirBssDescription *pSirBssDesc = NULL;
tSirMacAddr BroadcastMac = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
tCsrScanResult *pScanResult = NULL;
tCsrRoamInfo roamInfo;
sme_QosAssocInfo assocInfo;
sme_QosCsrEventIndType ind_qos;//indication for QoS module in SME
tANI_U8 acm_mask = 0; //HDD needs the ACM mask in the assoc rsp callback
tDot11fBeaconIEs *pIes = NULL;
tANI_U32 sessionId = pCommand->sessionId;
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
tCsrRoamProfile *pProfile = &pCommand->u.roamCmd.roamProfile;
eRoamCmdStatus roamStatus;
eCsrRoamResult roamResult;
eHalStatus status;
tANI_U32 key_timeout_interval = 0;
tSirSmeStartBssRsp *pSmeStartBssRsp = NULL;
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return eANI_BOOLEAN_FALSE;
}
smsLog( pMac, LOG1, FL("Processing ROAM results..."));
switch( Result )
{
case eCsrJoinSuccess:
// reset the IDLE timer
// !!
// !! fall through to the next CASE statement here is intentional !!
// !!
case eCsrReassocSuccess:
if(eCsrReassocSuccess == Result)
{
roamInfo.reassoc = true;
ind_qos = SME_QOS_CSR_REASSOC_COMPLETE;
}
else
{
roamInfo.reassoc = false;
ind_qos = SME_QOS_CSR_ASSOC_COMPLETE;
}
// Success Join Response from LIM. Tell NDIS we are connected and save the
// Connected state...
smsLog(pMac, LOGW, FL("receives association indication"));
vos_mem_set(&roamInfo, sizeof(roamInfo), 0);
//always free the memory here
if(pSession->pWpaRsnRspIE)
{
pSession->nWpaRsnRspIeLength = 0;
vos_mem_free(pSession->pWpaRsnRspIE);
pSession->pWpaRsnRspIE = NULL;
}
#ifdef FEATURE_WLAN_WAPI
if(pSession->pWapiRspIE)
{
pSession->nWapiRspIeLength = 0;
vos_mem_free(pSession->pWapiRspIE);
pSession->pWapiRspIE = NULL;
}
#endif /* FEATURE_WLAN_WAPI */
#ifdef FEATURE_WLAN_BTAMP_UT_RF
//Reset counter so no join retry is needed.
pSession->maxRetryCount = 0;
csrRoamStopJoinRetryTimer(pMac, sessionId);
#endif
/* This creates problem since we have not saved the connected profile.
So moving this after saving the profile
*/
//csrRoamStateChange( pMac, eCSR_ROAMING_STATE_JOINED );
/* Reset full_power_till_set_key as it might have been set
* by last failed secured connection.
* It should be set only for secured connection.
*/
pMac->pmc.full_power_till_set_key = false;
if( CSR_IS_INFRASTRUCTURE( pProfile ) )
{
pSession->connectState = eCSR_ASSOC_STATE_TYPE_INFRA_ASSOCIATED;
}
else
{
pSession->connectState = eCSR_ASSOC_STATE_TYPE_WDS_CONNECTED;
}
//Use the last connected bssdesc for reassoc-ing to the same AP.
//NOTE: What to do when reassoc to a different AP???
if( (eCsrHddIssuedReassocToSameAP == pCommand->u.roamCmd.roamReason) ||
(eCsrSmeIssuedReassocToSameAP == pCommand->u.roamCmd.roamReason) )
{
pSirBssDesc = pSession->pConnectBssDesc;
if(pSirBssDesc)
{
vos_mem_copy(&roamInfo.bssid, &pSirBssDesc->bssId,
sizeof(tCsrBssid));
}
}
else
{
if(pCommand->u.roamCmd.pRoamBssEntry)
{
pScanResult = GET_BASE_ADDR(pCommand->u.roamCmd.pRoamBssEntry, tCsrScanResult, Link);
if(pScanResult != NULL)
{
pSirBssDesc = &pScanResult->Result.BssDescriptor;
//this can be NULL
pIes = (tDot11fBeaconIEs *)( pScanResult->Result.pvIes );
vos_mem_copy(&roamInfo.bssid, &pSirBssDesc->bssId,
sizeof(tCsrBssid));
}
}
}
if( pSirBssDesc )
{
roamInfo.staId = HAL_STA_INVALID_IDX;
csrRoamSaveConnectedInfomation(pMac, sessionId, pProfile, pSirBssDesc, pIes);
//Save WPA/RSN IE
csrRoamSaveSecurityRspIE(pMac, sessionId, pProfile->negotiatedAuthType, pSirBssDesc, pIes);
#ifdef FEATURE_WLAN_ESE
roamInfo.isESEAssoc = pSession->connectedProfile.isESEAssoc;
#endif
#ifdef WLAN_FEATURE_VOWIFI_11R
if (pSirBssDesc->mdiePresent)
{
if(csrIsAuthType11r(pProfile->negotiatedAuthType, VOS_TRUE)
#ifdef FEATURE_WLAN_ESE
&& !((pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_OPEN_SYSTEM) &&
(pIes->ESEVersion.present) && (pMac->roam.configParam.isEseIniFeatureEnabled))
#endif
)
{
// is11Rconnection;
roamInfo.is11rAssoc = VOS_TRUE;
}
else
{
// is11Rconnection;
roamInfo.is11rAssoc = VOS_FALSE;
}
}
#endif
// csrRoamStateChange also affects sub-state. Hence, csrRoamStateChange happens first and then
// substate change.
// Moving even save profile above so that below mentioned conditon is also met.
// JEZ100225: Moved to after saving the profile. Fix needed in main/latest
csrRoamStateChange( pMac, eCSR_ROAMING_STATE_JOINED, sessionId );
// Make sure the Set Context is issued before link indication to NDIS. After link indication is
// made to NDIS, frames could start flowing. If we have not set context with LIM, the frames
// will be dropped for the security context may not be set properly.
//
// this was causing issues in the 2c_wlan_wep WHQL test when the SetContext was issued after the link
// indication. (Link Indication happens in the profFSMSetConnectedInfra call).
//
// this reordering was done on titan_prod_usb branch and is being replicated here.
//
if( CSR_IS_ENC_TYPE_STATIC( pProfile->negotiatedUCEncryptionType ) &&
!pProfile->bWPSAssociation)
{
// Issue the set Context request to LIM to establish the Unicast STA context
if( !HAL_STATUS_SUCCESS( csrRoamIssueSetContextReq( pMac, sessionId,
pProfile->negotiatedUCEncryptionType,
pSirBssDesc, &(pSirBssDesc->bssId),
FALSE, TRUE, eSIR_TX_RX, 0, 0, NULL, 0 ) ) ) // NO keys... these key parameters don't matter.
{
smsLog( pMac, LOGE, FL(" Set context for unicast fail") );
csrRoamSubstateChange( pMac, eCSR_ROAM_SUBSTATE_NONE, sessionId );
}
// Issue the set Context request to LIM to establish the Broadcast STA context
csrRoamIssueSetContextReq( pMac, sessionId, pProfile->negotiatedMCEncryptionType,
pSirBssDesc, &BroadcastMac,
FALSE, FALSE, eSIR_TX_RX, 0, 0, NULL, 0 ); // NO keys... these key parameters don't matter.
}
else if (!pSession->abortConnection)
{
//Need to wait for supplicant authtication
roamInfo.fAuthRequired = eANI_BOOLEAN_TRUE;
//Set the subestate to WaitForKey in case authentiation is needed
csrRoamSubstateChange( pMac, eCSR_ROAM_SUBSTATE_WAIT_FOR_KEY, sessionId );
if(pProfile->bWPSAssociation)
{
key_timeout_interval = CSR_WAIT_FOR_WPS_KEY_TIMEOUT_PERIOD;
}
else
{
key_timeout_interval = CSR_WAIT_FOR_KEY_TIMEOUT_PERIOD;
}
//Save sessionId in case of timeout
pMac->roam.WaitForKeyTimerInfo.sessionId = (tANI_U8)sessionId;
//This time should be long enough for the rest of the process plus setting key
if(!HAL_STATUS_SUCCESS( csrRoamStartWaitForKeyTimer( pMac, key_timeout_interval ) ) )
{
//Reset our state so nothting is blocked.
smsLog( pMac, LOGE, FL(" Failed to start pre-auth timer") );
csrRoamSubstateChange( pMac, eCSR_ROAM_SUBSTATE_NONE, sessionId);
}
}
assocInfo.pBssDesc = pSirBssDesc; //could be NULL
assocInfo.pProfile = pProfile;
if(Context)
{
tSirSmeJoinRsp *pJoinRsp = (tSirSmeJoinRsp *)Context;
tANI_U32 len;
csrRoamFreeConnectedInfo( pMac, &pSession->connectedInfo );
len = pJoinRsp->assocReqLength + pJoinRsp->assocRspLength + pJoinRsp->beaconLength;
#ifdef WLAN_FEATURE_VOWIFI_11R
len += pJoinRsp->parsedRicRspLen;
#endif /* WLAN_FEATURE_VOWIFI_11R */
#ifdef FEATURE_WLAN_ESE
len += pJoinRsp->tspecIeLen;
#endif
if(len)
{
pSession->connectedInfo.pbFrames = vos_mem_malloc(len);
if ( pSession->connectedInfo.pbFrames != NULL )
{
vos_mem_copy(pSession->connectedInfo.pbFrames,
pJoinRsp->frames, len);
pSession->connectedInfo.nAssocReqLength = pJoinRsp->assocReqLength;
pSession->connectedInfo.nAssocRspLength = pJoinRsp->assocRspLength;
pSession->connectedInfo.nBeaconLength = pJoinRsp->beaconLength;
#ifdef WLAN_FEATURE_VOWIFI_11R
pSession->connectedInfo.nRICRspLength = pJoinRsp->parsedRicRspLen;
#endif /* WLAN_FEATURE_VOWIFI_11R */
#ifdef FEATURE_WLAN_ESE
pSession->connectedInfo.nTspecIeLength = pJoinRsp->tspecIeLen;
#endif
roamInfo.nAssocReqLength = pJoinRsp->assocReqLength;
roamInfo.nAssocRspLength = pJoinRsp->assocRspLength;
roamInfo.nBeaconLength = pJoinRsp->beaconLength;
roamInfo.pbFrames = pSession->connectedInfo.pbFrames;
}
}
if(pCommand->u.roamCmd.fReassoc)
{
roamInfo.fReassocReq = roamInfo.fReassocRsp = eANI_BOOLEAN_TRUE;
}
pSession->connectedInfo.staId = ( tANI_U8 )pJoinRsp->staId;
roamInfo.staId = ( tANI_U8 )pJoinRsp->staId;
roamInfo.ucastSig = ( tANI_U8 )pJoinRsp->ucastSig;
roamInfo.bcastSig = ( tANI_U8 )pJoinRsp->bcastSig;
roamInfo.maxRateFlags = pJoinRsp->maxRateFlags;
roamInfo.vht_caps = pJoinRsp->vht_caps;
roamInfo.ht_caps = pJoinRsp->ht_caps;
roamInfo.hs20vendor_ie = pJoinRsp->hs20vendor_ie;
roamInfo.ht_operation = pJoinRsp->ht_operation;
roamInfo.vht_operation = pJoinRsp->vht_operation;
}
else
{
if(pCommand->u.roamCmd.fReassoc)
{
roamInfo.fReassocReq = roamInfo.fReassocRsp = eANI_BOOLEAN_TRUE;
roamInfo.nAssocReqLength = pSession->connectedInfo.nAssocReqLength;
roamInfo.nAssocRspLength = pSession->connectedInfo.nAssocRspLength;
roamInfo.nBeaconLength = pSession->connectedInfo.nBeaconLength;
roamInfo.pbFrames = pSession->connectedInfo.pbFrames;
}
}
/* Update the staId from the previous connected profile info
as the reassociation is triggred at SME/HDD */
if( (eCsrHddIssuedReassocToSameAP == pCommand->u.roamCmd.roamReason) ||
(eCsrSmeIssuedReassocToSameAP == pCommand->u.roamCmd.roamReason) )
{
roamInfo.staId = pSession->connectedInfo.staId;
}
#ifndef WLAN_MDM_CODE_REDUCTION_OPT
// Indicate SME-QOS with reassoc success event, only after
// copying the frames
sme_QosCsrEventInd(pMac, (v_U8_t)sessionId, ind_qos, &assocInfo);
#endif
roamInfo.pBssDesc = pSirBssDesc;
roamInfo.statusCode = pSession->joinFailStatusCode.statusCode;
roamInfo.reasonCode = pSession->joinFailStatusCode.reasonCode;
#ifndef WLAN_MDM_CODE_REDUCTION_OPT
acm_mask = sme_QosGetACMMask(pMac, pSirBssDesc, NULL);
#endif /* WLAN_MDM_CODE_REDUCTION_OPT*/
pSession->connectedProfile.acm_mask = acm_mask;
//start UAPSD if uapsd_mask is not 0 because HDD will configure for trigger frame
//It may be better to let QoS do this????
if( pSession->connectedProfile.modifyProfileFields.uapsd_mask )
{
smsLog(pMac, LOGE, " uapsd_mask (0x%X) set, request UAPSD now",
pSession->connectedProfile.modifyProfileFields.uapsd_mask);
pmcStartUapsd( pMac, NULL, NULL );
}
pSession->connectedProfile.dot11Mode = pSession->bssParams.uCfgDot11Mode;
roamInfo.u.pConnectedProfile = &pSession->connectedProfile;
if( pSession->bRefAssocStartCnt > 0 )
{
pSession->bRefAssocStartCnt--;
//Remove this code once SLM_Sessionization is supported
//BMPS_WORKAROUND_NOT_NEEDED
if(!IS_FEATURE_SUPPORTED_BY_FW(SLM_SESSIONIZATION) && ( csrIsConcurrentSessionRunning( pMac )))
{
pMac->roam.configParam.doBMPSWorkaround = 1;
}
csrRoamCallCallback(pMac, sessionId, &roamInfo, pCommand->u.roamCmd.roamId, eCSR_ROAM_ASSOCIATION_COMPLETION, eCSR_ROAM_RESULT_ASSOCIATED);
}
csrRoamCompletion(pMac, sessionId, NULL, pCommand, eCSR_ROAM_RESULT_NONE, eANI_BOOLEAN_TRUE);
// reset the PMKID candidate list
csrResetPMKIDCandidateList( pMac, sessionId );
//Update TL's AC weight base on the current EDCA parameters
//These parameters may change in the course of the connection, that sictuation
//is not taken care here. This change is mainly to address a WIFI WMM test where
//BE has a equal or higher TX priority than VI.
//We only do this for infra link
if( csrIsConnStateConnectedInfra(pMac, sessionId ) && pIes )
{
csrCheckAndUpdateACWeight(pMac, pIes);
}
#ifdef FEATURE_WLAN_WAPI
// reset the BKID candidate list
csrResetBKIDCandidateList( pMac, sessionId );
#endif /* FEATURE_WLAN_WAPI */
}
else
{
smsLog(pMac, LOGW, " Roam command doesn't have a BSS desc");
}
csrScanCancelIdleScan(pMac);
//Not to signal link up because keys are yet to be set.
//The linkup function will overwrite the sub-state that we need to keep at this point.
if( !CSR_IS_WAIT_FOR_KEY(pMac, sessionId) )
{
csrRoamLinkUp(pMac, pSession->connectedProfile.bssid);
}
//Check if BMPS is required and start the BMPS retry timer. Timer period is large
//enough to let security and DHCP handshake succeed before entry into BMPS
if (pmcShouldBmpsTimerRun(pMac))
{
/* Set full_power_till_set_key to make sure we wait for
* until keys are set before going into BMPS.
*/
if(eANI_BOOLEAN_TRUE == roamInfo.fAuthRequired)
{
pMac->pmc.full_power_till_set_key = true;
smsLog(pMac, LOG1,
FL("Set full_power_till_set_key to make sure we wait until keys are set before going to BMPS"));
}
if (pmcStartTrafficTimer(pMac, BMPS_TRAFFIC_TIMER_ALLOW_SECURITY_DHCP)
!= eHAL_STATUS_SUCCESS)
{
smsLog(pMac, LOGP, FL("Cannot start BMPS Retry timer"));
}
smsLog(pMac, LOG2, FL("BMPS Retry Timer already running or started"));
}
break;
case eCsrStartBssSuccess:
// on the StartBss Response, LIM is returning the Bss Description that we
// are beaconing. Add this Bss Description to our scan results and
// chain the Profile to this Bss Description. On a Start BSS, there was no
// detected Bss description (no partner) so we issued the Start Bss to
// start the Ibss without any Bss description. Lim was kind enough to return
// the Bss Description that we start beaconing for the newly started Ibss.
smsLog(pMac, LOG2, FL("receives start BSS ok indication"));
status = eHAL_STATUS_FAILURE;
pSmeStartBssRsp = (tSirSmeStartBssRsp *)Context;
vos_mem_set(&roamInfo, sizeof(tCsrRoamInfo), 0);
if( CSR_IS_IBSS( pProfile ) )
{
pSession->connectState = eCSR_ASSOC_STATE_TYPE_IBSS_DISCONNECTED;
}
else if (CSR_IS_INFRA_AP(pProfile))
{
pSession->connectState = eCSR_ASSOC_STATE_TYPE_INFRA_DISCONNECTED;
}
else
{
pSession->connectState = eCSR_ASSOC_STATE_TYPE_WDS_DISCONNECTED;
}
if( !CSR_IS_WDS_STA( pProfile ) )
{
csrRoamStateChange( pMac, eCSR_ROAMING_STATE_JOINED, sessionId );
pSirBssDesc = &pSmeStartBssRsp->bssDescription;
if( !HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs( pMac, pSirBssDesc, &pIes )) )
{
smsLog(pMac, LOGW, FL("cannot parse IBSS IEs"));
roamInfo.pBssDesc = pSirBssDesc;
//We need to associate_complete it first, becasue Associate_start already indicated.
csrRoamCallCallback( pMac, sessionId, &roamInfo, pCommand->u.roamCmd.roamId,
eCSR_ROAM_IBSS_IND, eCSR_ROAM_RESULT_IBSS_START_FAILED );
break;
}
if (!CSR_IS_INFRA_AP(pProfile))
{
pScanResult = csrScanAppendBssDescription( pMac, pSirBssDesc, pIes, FALSE );
}
csrRoamSaveConnectedBssDesc(pMac, sessionId, pSirBssDesc);
csrRoamFreeConnectProfile(pMac, &pSession->connectedProfile);
csrRoamFreeConnectedInfo( pMac, &pSession->connectedInfo );
if(pSirBssDesc)
{
csrRoamSaveConnectedInfomation(pMac, sessionId, pProfile, pSirBssDesc, pIes);
vos_mem_copy(&roamInfo.bssid, &pSirBssDesc->bssId,
sizeof(tCsrBssid));
}
//We are doen with the IEs so free it
vos_mem_free(pIes);
#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
{
vos_log_ibss_pkt_type *pIbssLog;
tANI_U32 bi;
WLAN_VOS_DIAG_LOG_ALLOC(pIbssLog, vos_log_ibss_pkt_type, LOG_WLAN_IBSS_C);
if(pIbssLog)
{
if(CSR_INVALID_SCANRESULT_HANDLE == pCommand->u.roamCmd.hBSSList)
{
//We start the IBSS (didn't find any matched IBSS out there)
pIbssLog->eventId = WLAN_IBSS_EVENT_START_IBSS_RSP;
}
else
{
pIbssLog->eventId = WLAN_IBSS_EVENT_JOIN_IBSS_RSP;
}
if(pSirBssDesc)
{
vos_mem_copy(pIbssLog->bssid, pSirBssDesc->bssId, 6);
pIbssLog->operatingChannel = pSirBssDesc->channelId;
}
if(HAL_STATUS_SUCCESS(ccmCfgGetInt(pMac, WNI_CFG_BEACON_INTERVAL, &bi)))
{
//***U8 is not enough for beacon interval
pIbssLog->beaconInterval = (v_U8_t)bi;
}
WLAN_VOS_DIAG_LOG_REPORT(pIbssLog);
}
}
#endif //#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
//Only set context for non-WDS_STA. We don't even need it for WDS_AP. But since the encryption
//is WPA2-PSK so it won't matter.
if( CSR_IS_ENC_TYPE_STATIC( pProfile->negotiatedUCEncryptionType ) && !CSR_IS_INFRA_AP( pSession->pCurRoamProfile ))
{
// Issue the set Context request to LIM to establish the Broadcast STA context for the Ibss.
csrRoamIssueSetContextReq( pMac, sessionId,
pProfile->negotiatedMCEncryptionType,
pSirBssDesc, &BroadcastMac,
FALSE, FALSE, eSIR_TX_RX, 0, 0, NULL, 0 ); // NO keys... these key parameters don't matter.
}
}
else
{
//Keep the state to eCSR_ROAMING_STATE_JOINING
//Need to send join_req.
if(pCommand->u.roamCmd.pRoamBssEntry)
{
if((pScanResult = GET_BASE_ADDR(pCommand->u.roamCmd.pRoamBssEntry, tCsrScanResult, Link)))
{
pSirBssDesc = &pScanResult->Result.BssDescriptor;
pIes = (tDot11fBeaconIEs *)( pScanResult->Result.pvIes );
// Set the roaming substate to 'join attempt'...
csrRoamSubstateChange( pMac, eCSR_ROAM_SUBSTATE_JOIN_REQ, sessionId);
status = csrSendJoinReqMsg( pMac, sessionId, pSirBssDesc, pProfile, pIes, eWNI_SME_JOIN_REQ );
}
}
else
{
smsLog( pMac, LOGE, " StartBSS for WDS station with no BssDesc" );
VOS_ASSERT( 0 );
}
}
//Only tell upper layer is we start the BSS because Vista doesn't like multiple connection
//indications. If we don't start the BSS ourself, handler of eSIR_SME_JOINED_NEW_BSS will
//trigger the connection start indication in Vista
if( !CSR_IS_JOIN_TO_IBSS( pProfile ) )
{
roamStatus = eCSR_ROAM_IBSS_IND;
roamResult = eCSR_ROAM_RESULT_IBSS_STARTED;
if( CSR_IS_WDS( pProfile ) )
{
roamStatus = eCSR_ROAM_WDS_IND;
roamResult = eCSR_ROAM_RESULT_WDS_STARTED;
}
if( CSR_IS_INFRA_AP( pProfile ) )
{
roamStatus = eCSR_ROAM_INFRA_IND;
roamResult = eCSR_ROAM_RESULT_INFRA_STARTED;
}
//Only tell upper layer is we start the BSS because Vista doesn't like multiple connection
//indications. If we don't start the BSS ourself, handler of eSIR_SME_JOINED_NEW_BSS will
//trigger the connection start indication in Vista
vos_mem_set(&roamInfo, sizeof(tCsrRoamInfo), 0);
roamInfo.statusCode = pSession->joinFailStatusCode.statusCode;
roamInfo.reasonCode = pSession->joinFailStatusCode.reasonCode;
//We start the IBSS (didn't find any matched IBSS out there)
roamInfo.pBssDesc = pSirBssDesc;
roamInfo.staId = (tANI_U8)pSmeStartBssRsp->staId;
vos_mem_copy(roamInfo.bssid, pSirBssDesc->bssId,
sizeof(tCsrBssid));
//Remove this code once SLM_Sessionization is supported
//BMPS_WORKAROUND_NOT_NEEDED
if(!IS_FEATURE_SUPPORTED_BY_FW(SLM_SESSIONIZATION) &&
( csrIsConcurrentSessionRunning( pMac )))
{
pMac->roam.configParam.doBMPSWorkaround = 1;
}
csrRoamCallCallback( pMac, sessionId, &roamInfo, pCommand->u.roamCmd.roamId, roamStatus, roamResult );
}
csrScanCancelIdleScan(pMac);
if( CSR_IS_WDS_STA( pProfile ) )
{
//need to send stop BSS because we fail to send join_req
csrRoamIssueDisassociateCmd( pMac, sessionId, eCSR_DISCONNECT_REASON_UNSPECIFIED );
csrRoamCallCallback( pMac, sessionId, &roamInfo, pCommand->u.roamCmd.roamId,
eCSR_ROAM_WDS_IND, eCSR_ROAM_RESULT_WDS_STOPPED );
}
break;
case eCsrStartBssFailure:
#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
{
vos_log_ibss_pkt_type *pIbssLog;
WLAN_VOS_DIAG_LOG_ALLOC(pIbssLog, vos_log_ibss_pkt_type, LOG_WLAN_IBSS_C);
if(pIbssLog)
{
pIbssLog->status = WLAN_IBSS_STATUS_FAILURE;
WLAN_VOS_DIAG_LOG_REPORT(pIbssLog);
}
}
#endif //#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
roamStatus = eCSR_ROAM_IBSS_IND;
roamResult = eCSR_ROAM_RESULT_IBSS_STARTED;
if( CSR_IS_WDS( pProfile ) )
{
roamStatus = eCSR_ROAM_WDS_IND;
roamResult = eCSR_ROAM_RESULT_WDS_STARTED;
}
if( CSR_IS_INFRA_AP( pProfile ) )
{
roamStatus = eCSR_ROAM_INFRA_IND;
roamResult = eCSR_ROAM_RESULT_INFRA_START_FAILED;
}
if(Context)
{
pSirBssDesc = (tSirBssDescription *)Context;
}
else
{
pSirBssDesc = NULL;
}
vos_mem_set(&roamInfo, sizeof(tCsrRoamInfo), 0);
roamInfo.pBssDesc = pSirBssDesc;
//We need to associate_complete it first, becasue Associate_start already indicated.
csrRoamCallCallback( pMac, sessionId, &roamInfo, pCommand->u.roamCmd.roamId, roamStatus, roamResult );
csrSetDefaultDot11Mode( pMac );
break;
case eCsrSilentlyStopRoaming:
// We are here because we try to start the same IBSS
//No message to PE
// return the roaming state to Joined.
smsLog(pMac, LOGW, FL("receives silently roaming indication"));
csrRoamStateChange( pMac, eCSR_ROAMING_STATE_JOINED, sessionId );
csrRoamSubstateChange( pMac, eCSR_ROAM_SUBSTATE_NONE, sessionId );
vos_mem_set(&roamInfo, sizeof(tCsrRoamInfo), 0);
roamInfo.pBssDesc = pSession->pConnectBssDesc;
if( roamInfo.pBssDesc )
{
vos_mem_copy(&roamInfo.bssid, &roamInfo.pBssDesc->bssId,
sizeof(tCsrBssid));
}
//Since there is no change in the current state, simply pass back no result otherwise
//HDD may be mistakenly mark to disconnected state.
csrRoamCallCallback( pMac, sessionId, &roamInfo, pCommand->u.roamCmd.roamId,
eCSR_ROAM_IBSS_IND, eCSR_ROAM_RESULT_NONE );
break;
case eCsrSilentlyStopRoamingSaveState:
//We are here because we try to connect to the same AP
//No message to PE
smsLog(pMac, LOGW, FL("receives silently stop roaming indication"));
vos_mem_set(&roamInfo, sizeof(roamInfo), 0);
//to aviod resetting the substate to NONE
pMac->roam.curState[sessionId] = eCSR_ROAMING_STATE_JOINED;
//No need to change substate to wai_for_key because there is no state change
roamInfo.pBssDesc = pSession->pConnectBssDesc;
if( roamInfo.pBssDesc )
{
vos_mem_copy(&roamInfo.bssid, &roamInfo.pBssDesc->bssId,
sizeof(tCsrBssid));
}
roamInfo.statusCode = pSession->joinFailStatusCode.statusCode;
roamInfo.reasonCode = pSession->joinFailStatusCode.reasonCode;
roamInfo.nBeaconLength = pSession->connectedInfo.nBeaconLength;
roamInfo.nAssocReqLength = pSession->connectedInfo.nAssocReqLength;
roamInfo.nAssocRspLength = pSession->connectedInfo.nAssocRspLength;
roamInfo.pbFrames = pSession->connectedInfo.pbFrames;
roamInfo.staId = pSession->connectedInfo.staId;
roamInfo.u.pConnectedProfile = &pSession->connectedProfile;
VOS_ASSERT( roamInfo.staId != 0 );
pSession->bRefAssocStartCnt--;
csrRoamCallCallback(pMac, sessionId, &roamInfo, pCommand->u.roamCmd.roamId,
eCSR_ROAM_ASSOCIATION_COMPLETION, eCSR_ROAM_RESULT_ASSOCIATED);
csrRoamCompletion(pMac, sessionId, NULL, pCommand, eCSR_ROAM_RESULT_ASSOCIATED, eANI_BOOLEAN_TRUE);
break;
case eCsrReassocFailure:
#ifndef WLAN_MDM_CODE_REDUCTION_OPT
sme_QosCsrEventInd(pMac, (tANI_U8)sessionId, SME_QOS_CSR_REASSOC_FAILURE, NULL);
#endif
case eCsrJoinWdsFailure:
smsLog(pMac, LOGW, FL("failed to join WDS"));
csrFreeConnectBssDesc(pMac, sessionId);
csrRoamFreeConnectProfile(pMac, &pSession->connectedProfile);
csrRoamFreeConnectedInfo( pMac, &pSession->connectedInfo );
vos_mem_set(&roamInfo, sizeof(tCsrRoamInfo), 0);
roamInfo.pBssDesc = pCommand->u.roamCmd.pLastRoamBss;
roamInfo.statusCode = pSession->joinFailStatusCode.statusCode;
roamInfo.reasonCode = pSession->joinFailStatusCode.reasonCode;
csrRoamCallCallback(pMac, sessionId, &roamInfo, pCommand->u.roamCmd.roamId,
eCSR_ROAM_WDS_IND,
eCSR_ROAM_RESULT_WDS_NOT_ASSOCIATED);
//Need to issue stop_bss
break;
case eCsrJoinFailure:
case eCsrNothingToJoin:
case eCsrJoinFailureDueToConcurrency:
default:
{
smsLog(pMac, LOGW, FL("receives no association indication"));
smsLog(pMac, LOG1, FL("Assoc ref count %d"),
pSession->bRefAssocStartCnt);
if( CSR_IS_INFRASTRUCTURE( &pSession->connectedProfile ) ||
CSR_IS_ROAM_SUBSTATE_STOP_BSS_REQ( pMac, sessionId ) )
{
//do not free for the other profiles as we need to send down stop BSS later
csrFreeConnectBssDesc(pMac, sessionId);
csrRoamFreeConnectProfile(pMac, &pSession->connectedProfile);
csrRoamFreeConnectedInfo( pMac, &pSession->connectedInfo );
csrSetDefaultDot11Mode( pMac );
}
switch( pCommand->u.roamCmd.roamReason )
{
// If this transition is because of an 802.11 OID, then we transition
// back to INIT state so we sit waiting for more OIDs to be issued and
// we don't start the IDLE timer.
case eCsrSmeIssuedFTReassoc:
case eCsrSmeIssuedAssocToSimilarAP:
case eCsrHddIssued:
case eCsrSmeIssuedDisassocForHandoff:
csrRoamStateChange( pMac, eCSR_ROAMING_STATE_IDLE, sessionId );
vos_mem_set(&roamInfo, sizeof(tCsrRoamInfo), 0);
roamInfo.pBssDesc = pCommand->u.roamCmd.pLastRoamBss;
roamInfo.statusCode = pSession->joinFailStatusCode.statusCode;
roamInfo.reasonCode = pSession->joinFailStatusCode.reasonCode;
vos_mem_copy(&roamInfo.bssid,
&pSession->joinFailStatusCode.bssId,
sizeof(tCsrBssid));
/* Defeaturize this later if needed */
#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
/* If Join fails while Handoff is in progress, indicate disassociated event to supplicant to reconnect */
if (csrRoamIsHandoffInProgress(pMac))
{
/* Should indicate neighbor roam algorithm about the connect failure here */
csrNeighborRoamIndicateConnect(pMac, (tANI_U8)sessionId, VOS_STATUS_E_FAILURE);
}
#endif
if(pSession->bRefAssocStartCnt > 0)
{
pSession->bRefAssocStartCnt--;
if(eCsrJoinFailureDueToConcurrency == Result)
{
csrRoamCallCallback(pMac, sessionId, &roamInfo, pCommand->u.roamCmd.roamId,
eCSR_ROAM_ASSOCIATION_COMPLETION,
eCSR_ROAM_RESULT_ASSOC_FAIL_CON_CHANNEL);
}
else
{
csrRoamCallCallback(pMac, sessionId, &roamInfo, pCommand->u.roamCmd.roamId,
eCSR_ROAM_ASSOCIATION_COMPLETION,
eCSR_ROAM_RESULT_FAILURE);
}
}
else
{
/* bRefAssocStartCnt is not incremented when
* eRoamState == eCsrStopRoamingDueToConcurrency
* in csrRoamJoinNextBss API. so handle this in
* else case by sending assoc failure
*/
csrRoamCallCallback(pMac, sessionId, &roamInfo,
pCommand->u.scanCmd.roamId,
eCSR_ROAM_ASSOCIATION_FAILURE,
eCSR_ROAM_RESULT_FAILURE);
}
smsLog(pMac, LOG1, FL(" roam(reason %d) failed"), pCommand->u.roamCmd.roamReason);
#ifndef WLAN_MDM_CODE_REDUCTION_OPT
sme_QosUpdateHandOff((tANI_U8)sessionId, VOS_FALSE);
sme_QosCsrEventInd(pMac, (tANI_U8)sessionId, SME_QOS_CSR_DISCONNECT_IND, NULL);
#endif
csrRoamCompletion(pMac, sessionId, NULL, pCommand, eCSR_ROAM_RESULT_FAILURE, eANI_BOOLEAN_FALSE);
csrScanStartIdleScan(pMac);
#ifdef FEATURE_WLAN_BTAMP_UT_RF
//For WDS STA. To fix the issue where the WDS AP side may be too busy by
//BT activity and not able to recevie WLAN traffic. Retry the join
if( CSR_IS_WDS_STA(pProfile) )
{
csrRoamStartJoinRetryTimer(pMac, sessionId, CSR_JOIN_RETRY_TIMEOUT_PERIOD);
}
#endif
break;
case eCsrHddIssuedReassocToSameAP:
case eCsrSmeIssuedReassocToSameAP:
csrRoamStateChange( pMac, eCSR_ROAMING_STATE_IDLE, sessionId);
csrRoamCallCallback(pMac, sessionId, NULL, pCommand->u.roamCmd.roamId, eCSR_ROAM_DISASSOCIATED, eCSR_ROAM_RESULT_FORCED);
#ifndef WLAN_MDM_CODE_REDUCTION_OPT
sme_QosCsrEventInd(pMac, (tANI_U8)sessionId, SME_QOS_CSR_DISCONNECT_IND, NULL);
#endif
csrRoamCompletion(pMac, sessionId, NULL, pCommand, eCSR_ROAM_RESULT_FAILURE, eANI_BOOLEAN_FALSE);
csrScanStartIdleScan(pMac);
break;
case eCsrForcedDisassoc:
case eCsrForcedDeauth:
case eCsrSmeIssuedIbssJoinFailure:
csrRoamStateChange( pMac, eCSR_ROAMING_STATE_IDLE, sessionId);
if(eCsrSmeIssuedIbssJoinFailure == pCommand->u.roamCmd.roamReason)
{
// Notify HDD that IBSS join failed
csrRoamCallCallback(pMac, sessionId, NULL, 0, eCSR_ROAM_IBSS_IND, eCSR_ROAM_RESULT_IBSS_JOIN_FAILED);
}
else
{
csrRoamCallCallback(pMac, sessionId, NULL,
pCommand->u.roamCmd.roamId,
eCSR_ROAM_DISASSOCIATED, eCSR_ROAM_RESULT_FORCED);
}
#ifndef WLAN_MDM_CODE_REDUCTION_OPT
sme_QosCsrEventInd(pMac, (tANI_U8)sessionId, SME_QOS_CSR_DISCONNECT_IND, NULL);
#endif
csrRoamLinkDown(pMac, sessionId);
/*
*DelSta not done FW still in conneced state so dont
*issue IMPS req
*/
if (pMac->roam.deauthRspStatus == eSIR_SME_DEAUTH_STATUS)
{
smsLog(pMac, LOGW, FL("FW still in connected state "));
break;
}
csrScanStartIdleScan(pMac);
break;
case eCsrForcedIbssLeave:
csrIbssAgeBss(pMac);
csrRoamCallCallback(pMac, sessionId, NULL,
pCommand->u.roamCmd.roamId,
eCSR_ROAM_IBSS_LEAVE,
eCSR_ROAM_RESULT_IBSS_STOP);
break;
case eCsrForcedDisassocMICFailure:
csrRoamStateChange( pMac, eCSR_ROAMING_STATE_IDLE, sessionId );
csrRoamCallCallback(pMac, sessionId, NULL, pCommand->u.roamCmd.roamId, eCSR_ROAM_DISASSOCIATED, eCSR_ROAM_RESULT_MIC_FAILURE);
#ifndef WLAN_MDM_CODE_REDUCTION_OPT
sme_QosCsrEventInd(pMac, (tANI_U8)sessionId, SME_QOS_CSR_DISCONNECT_REQ, NULL);
#endif
csrScanStartIdleScan(pMac);
break;
case eCsrStopBss:
csrRoamCallCallback(pMac, sessionId, NULL,
pCommand->u.roamCmd.roamId,
eCSR_ROAM_INFRA_IND,
eCSR_ROAM_RESULT_INFRA_STOPPED);
break;
case eCsrForcedDisassocSta:
case eCsrForcedDeauthSta:
csrRoamStateChange( pMac, eCSR_ROAMING_STATE_JOINED, sessionId);
pSession = CSR_GET_SESSION(pMac, sessionId);
if (pSession)
{
if( CSR_IS_SESSION_VALID(pMac, sessionId) )
{
if ( CSR_IS_INFRA_AP(&pSession->connectedProfile) )
{
roamInfo.u.pConnectedProfile =
&pSession->connectedProfile;
vos_mem_copy(roamInfo.peerMac,
pCommand->u.roamCmd.peerMac,
sizeof(tSirMacAddr));
roamInfo.reasonCode = eCSR_ROAM_RESULT_FORCED;
roamInfo.statusCode = eSIR_SME_SUCCESS;
status = csrRoamCallCallback(pMac, sessionId,
&roamInfo, pCommand->u.roamCmd.roamId,
eCSR_ROAM_LOSTLINK,
eCSR_ROAM_RESULT_FORCED);
}
}
else
{
smsLog(pMac, LOGE, FL("Inactive session %d"),
sessionId);
return eHAL_STATUS_FAILURE;
}
}
else
{
smsLog(pMac, LOGE, FL("Invalid session"));
return eHAL_STATUS_FAILURE;
}
break;
case eCsrLostLink1:
// if lost link roam1 failed, then issue lost link Scan2 ...
csrScanRequestLostLink2(pMac, sessionId);
break;
case eCsrLostLink2:
// if lost link roam2 failed, then issue lost link scan3 ...
csrScanRequestLostLink3(pMac, sessionId);
break;
case eCsrLostLink3:
default:
csrRoamStateChange( pMac, eCSR_ROAMING_STATE_IDLE, sessionId );
//We are done with one round of lostlink roaming here
csrScanHandleFailedLostlink3(pMac, sessionId);
break;
}
break;
}
}
return ( fReleaseCommand );
}
eHalStatus csrRoamRegisterCallback(tpAniSirGlobal pMac, csrRoamCompleteCallback callback, void *pContext)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
return (status);
}
eHalStatus csrRoamCopyProfile(tpAniSirGlobal pMac, tCsrRoamProfile *pDstProfile, tCsrRoamProfile *pSrcProfile)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tANI_U32 size = 0;
do
{
vos_mem_set(pDstProfile, sizeof(tCsrRoamProfile), 0);
if(pSrcProfile->BSSIDs.numOfBSSIDs)
{
size = sizeof(tCsrBssid) * pSrcProfile->BSSIDs.numOfBSSIDs;
pDstProfile->BSSIDs.bssid = vos_mem_malloc(size);
if ( NULL == pDstProfile->BSSIDs.bssid )
status = eHAL_STATUS_FAILURE;
else
status = eHAL_STATUS_SUCCESS;
if(!HAL_STATUS_SUCCESS(status))
{
break;
}
pDstProfile->BSSIDs.numOfBSSIDs = pSrcProfile->BSSIDs.numOfBSSIDs;
vos_mem_copy(pDstProfile->BSSIDs.bssid,
pSrcProfile->BSSIDs.bssid, size);
}
if(pSrcProfile->SSIDs.numOfSSIDs)
{
size = sizeof(tCsrSSIDInfo) * pSrcProfile->SSIDs.numOfSSIDs;
pDstProfile->SSIDs.SSIDList = vos_mem_malloc(size);
if ( NULL == pDstProfile->SSIDs.SSIDList )
status = eHAL_STATUS_FAILURE;
else
status = eHAL_STATUS_SUCCESS;
if (!HAL_STATUS_SUCCESS(status))
{
break;
}
pDstProfile->SSIDs.numOfSSIDs = pSrcProfile->SSIDs.numOfSSIDs;
vos_mem_copy(pDstProfile->SSIDs.SSIDList,
pSrcProfile->SSIDs.SSIDList, size);
}
if(pSrcProfile->nWPAReqIELength)
{
pDstProfile->pWPAReqIE = vos_mem_malloc(pSrcProfile->nWPAReqIELength);
if ( NULL == pDstProfile->pWPAReqIE )
status = eHAL_STATUS_FAILURE;
else
status = eHAL_STATUS_SUCCESS;
if (!HAL_STATUS_SUCCESS(status))
{
break;
}
pDstProfile->nWPAReqIELength = pSrcProfile->nWPAReqIELength;
vos_mem_copy(pDstProfile->pWPAReqIE, pSrcProfile->pWPAReqIE,
pSrcProfile->nWPAReqIELength);
}
if(pSrcProfile->nRSNReqIELength)
{
pDstProfile->pRSNReqIE = vos_mem_malloc(pSrcProfile->nRSNReqIELength);
if ( NULL == pDstProfile->pRSNReqIE )
status = eHAL_STATUS_FAILURE;
else
status = eHAL_STATUS_SUCCESS;
if (!HAL_STATUS_SUCCESS(status))
{
break;
}
pDstProfile->nRSNReqIELength = pSrcProfile->nRSNReqIELength;
vos_mem_copy(pDstProfile->pRSNReqIE, pSrcProfile->pRSNReqIE,
pSrcProfile->nRSNReqIELength);
}
#ifdef FEATURE_WLAN_WAPI
if(pSrcProfile->nWAPIReqIELength)
{
pDstProfile->pWAPIReqIE = vos_mem_malloc(pSrcProfile->nWAPIReqIELength);
if ( NULL == pDstProfile->pWAPIReqIE )
status = eHAL_STATUS_FAILURE;
else
status = eHAL_STATUS_SUCCESS;
if(!HAL_STATUS_SUCCESS(status))
{
break;
}
pDstProfile->nWAPIReqIELength = pSrcProfile->nWAPIReqIELength;
vos_mem_copy(pDstProfile->pWAPIReqIE, pSrcProfile->pWAPIReqIE,
pSrcProfile->nWAPIReqIELength);
}
#endif /* FEATURE_WLAN_WAPI */
if(pSrcProfile->nAddIEScanLength)
{
memset(pDstProfile->addIEScan, 0 , SIR_MAC_MAX_ADD_IE_LENGTH);
if ( SIR_MAC_MAX_ADD_IE_LENGTH >= pSrcProfile->nAddIEScanLength)
{
vos_mem_copy(pDstProfile->addIEScan, pSrcProfile->addIEScan,
pSrcProfile->nAddIEScanLength);
pDstProfile->nAddIEScanLength = pSrcProfile->nAddIEScanLength;
}
else
{
VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
FL(" AddIEScanLength is not valid %u"),
pSrcProfile->nAddIEScanLength);
}
}
if(pSrcProfile->nAddIEAssocLength)
{
pDstProfile->pAddIEAssoc = vos_mem_malloc(pSrcProfile->nAddIEAssocLength);
if ( NULL == pDstProfile->pAddIEAssoc )
status = eHAL_STATUS_FAILURE;
else
status = eHAL_STATUS_SUCCESS;
if(!HAL_STATUS_SUCCESS(status))
{
break;
}
pDstProfile->nAddIEAssocLength = pSrcProfile->nAddIEAssocLength;
vos_mem_copy(pDstProfile->pAddIEAssoc, pSrcProfile->pAddIEAssoc,
pSrcProfile->nAddIEAssocLength);
}
if(pSrcProfile->ChannelInfo.ChannelList)
{
pDstProfile->ChannelInfo.ChannelList = vos_mem_malloc(
pSrcProfile->ChannelInfo.numOfChannels);
if ( NULL == pDstProfile->ChannelInfo.ChannelList )
status = eHAL_STATUS_FAILURE;
else
status = eHAL_STATUS_SUCCESS;
if(!HAL_STATUS_SUCCESS(status))
{
break;
}
pDstProfile->ChannelInfo.numOfChannels = pSrcProfile->ChannelInfo.numOfChannels;
vos_mem_copy(pDstProfile->ChannelInfo.ChannelList,
pSrcProfile->ChannelInfo.ChannelList,
pSrcProfile->ChannelInfo.numOfChannels);
}
pDstProfile->AuthType = pSrcProfile->AuthType;
pDstProfile->EncryptionType = pSrcProfile->EncryptionType;
pDstProfile->mcEncryptionType = pSrcProfile->mcEncryptionType;
pDstProfile->negotiatedUCEncryptionType = pSrcProfile->negotiatedUCEncryptionType;
pDstProfile->negotiatedMCEncryptionType = pSrcProfile->negotiatedMCEncryptionType;
pDstProfile->negotiatedAuthType = pSrcProfile->negotiatedAuthType;
#ifdef WLAN_FEATURE_11W
pDstProfile->MFPEnabled = pSrcProfile->MFPEnabled;
pDstProfile->MFPRequired = pSrcProfile->MFPRequired;
pDstProfile->MFPCapable = pSrcProfile->MFPCapable;
#endif
pDstProfile->BSSType = pSrcProfile->BSSType;
pDstProfile->phyMode = pSrcProfile->phyMode;
pDstProfile->csrPersona = pSrcProfile->csrPersona;
#ifdef FEATURE_WLAN_WAPI
if(csrIsProfileWapi(pSrcProfile))
{
if(pDstProfile->phyMode & eCSR_DOT11_MODE_11n)
{
pDstProfile->phyMode &= ~eCSR_DOT11_MODE_11n;
}
}
#endif /* FEATURE_WLAN_WAPI */
pDstProfile->CBMode = pSrcProfile->CBMode;
/*Save the WPS info*/
pDstProfile->bWPSAssociation = pSrcProfile->bWPSAssociation;
pDstProfile->bOSENAssociation = pSrcProfile->bOSENAssociation;
pDstProfile->uapsd_mask = pSrcProfile->uapsd_mask;
pDstProfile->beaconInterval = pSrcProfile->beaconInterval;
pDstProfile->privacy = pSrcProfile->privacy;
pDstProfile->fwdWPSPBCProbeReq = pSrcProfile->fwdWPSPBCProbeReq;
pDstProfile->csr80211AuthType = pSrcProfile->csr80211AuthType;
pDstProfile->dtimPeriod = pSrcProfile->dtimPeriod;
pDstProfile->ApUapsdEnable = pSrcProfile->ApUapsdEnable;
pDstProfile->SSIDs.SSIDList[0].ssidHidden = pSrcProfile->SSIDs.SSIDList[0].ssidHidden;
pDstProfile->protEnabled = pSrcProfile->protEnabled;
pDstProfile->obssProtEnabled = pSrcProfile->obssProtEnabled;
pDstProfile->cfg_protection = pSrcProfile->cfg_protection;
pDstProfile->wps_state = pSrcProfile->wps_state;
pDstProfile->ieee80211d = pSrcProfile->ieee80211d;
pDstProfile->force_24ghz_in_ht20 =
pSrcProfile->force_24ghz_in_ht20;
pDstProfile->force_rsne_override = pSrcProfile->force_rsne_override;
vos_mem_copy(&pDstProfile->Keys, &pSrcProfile->Keys,
sizeof(pDstProfile->Keys));
#ifdef WLAN_FEATURE_VOWIFI_11R
if (pSrcProfile->MDID.mdiePresent)
{
pDstProfile->MDID.mdiePresent = 1;
pDstProfile->MDID.mobilityDomain = pSrcProfile->MDID.mobilityDomain;
}
#endif
}while(0);
if(!HAL_STATUS_SUCCESS(status))
{
csrReleaseProfile(pMac, pDstProfile);
pDstProfile = NULL;
}
return (status);
}
eHalStatus csrRoamCopyConnectedProfile(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfile *pDstProfile )
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tCsrRoamConnectedProfile *pSrcProfile = &pMac->roam.roamSession[sessionId].connectedProfile;
do
{
vos_mem_set(pDstProfile, sizeof(tCsrRoamProfile), 0);
if(pSrcProfile->bssid)
{
pDstProfile->BSSIDs.bssid = vos_mem_malloc(sizeof(tCsrBssid));
if ( NULL == pDstProfile->BSSIDs.bssid )
status = eHAL_STATUS_FAILURE;
else
status = eHAL_STATUS_SUCCESS;
if(!HAL_STATUS_SUCCESS(status))
{
smsLog( pMac, LOGE,
FL("failed to allocate memory for BSSID"
"%02x:%02x:%02x:%02x:%02x:%02x"),
pSrcProfile->bssid[0], pSrcProfile->bssid[1], pSrcProfile->bssid[2],
pSrcProfile->bssid[3], pSrcProfile->bssid[4], pSrcProfile->bssid[5]);
break;
}
pDstProfile->BSSIDs.numOfBSSIDs = 1;
vos_mem_copy(pDstProfile->BSSIDs.bssid, pSrcProfile->bssid,
sizeof(tCsrBssid));
}
if(pSrcProfile->SSID.ssId)
{
pDstProfile->SSIDs.SSIDList = vos_mem_malloc(sizeof(tCsrSSIDInfo));
if ( NULL == pDstProfile->SSIDs.SSIDList )
status = eHAL_STATUS_FAILURE;
else
status = eHAL_STATUS_SUCCESS;
if(!HAL_STATUS_SUCCESS(status))
{
smsLog( pMac, LOGE,
FL("failed to allocate memory for SSIDList"
"%02x:%02x:%02x:%02x:%02x:%02x"),
pSrcProfile->bssid[0], pSrcProfile->bssid[1], pSrcProfile->bssid[2],
pSrcProfile->bssid[3], pSrcProfile->bssid[4], pSrcProfile->bssid[5]);
break;
}
pDstProfile->SSIDs.numOfSSIDs = 1;
pDstProfile->SSIDs.SSIDList[0].handoffPermitted = pSrcProfile->handoffPermitted;
pDstProfile->SSIDs.SSIDList[0].ssidHidden = pSrcProfile->ssidHidden;
vos_mem_copy(&pDstProfile->SSIDs.SSIDList[0].SSID,
&pSrcProfile->SSID, sizeof(tSirMacSSid));
}
if(pSrcProfile->nAddIEAssocLength)
{
pDstProfile->pAddIEAssoc = vos_mem_malloc(pSrcProfile->nAddIEAssocLength);
if ( NULL == pDstProfile->pAddIEAssoc)
status = eHAL_STATUS_FAILURE;
else
status = eHAL_STATUS_SUCCESS;
if(!HAL_STATUS_SUCCESS(status))
{
smsLog( pMac, LOGE, FL(" failed to allocate memory for additional IEs ") );
break;
}
pDstProfile->nAddIEAssocLength = pSrcProfile->nAddIEAssocLength;
vos_mem_copy(pDstProfile->pAddIEAssoc, pSrcProfile->pAddIEAssoc,
pSrcProfile->nAddIEAssocLength);
}
pDstProfile->ChannelInfo.ChannelList = vos_mem_malloc(1);
if ( NULL == pDstProfile->ChannelInfo.ChannelList )
status = eHAL_STATUS_FAILURE;
else
status = eHAL_STATUS_SUCCESS;
if(!HAL_STATUS_SUCCESS(status))
{
break;
}
pDstProfile->ChannelInfo.numOfChannels = 1;
pDstProfile->ChannelInfo.ChannelList[0] = pSrcProfile->operationChannel;
pDstProfile->AuthType.numEntries = 1;
pDstProfile->AuthType.authType[0] = pSrcProfile->AuthType;
pDstProfile->negotiatedAuthType = pSrcProfile->AuthType;
pDstProfile->EncryptionType.numEntries = 1;
pDstProfile->EncryptionType.encryptionType[0] = pSrcProfile->EncryptionType;
pDstProfile->negotiatedUCEncryptionType = pSrcProfile->EncryptionType;
pDstProfile->mcEncryptionType.numEntries = 1;
pDstProfile->mcEncryptionType.encryptionType[0] = pSrcProfile->mcEncryptionType;
pDstProfile->negotiatedMCEncryptionType = pSrcProfile->mcEncryptionType;
pDstProfile->BSSType = pSrcProfile->BSSType;
pDstProfile->CBMode = pSrcProfile->CBMode;
vos_mem_copy(&pDstProfile->Keys, &pSrcProfile->Keys,
sizeof(pDstProfile->Keys));
#ifdef WLAN_FEATURE_11W
pDstProfile->MFPEnabled = pSrcProfile->MFPEnabled;
pDstProfile->MFPRequired = pSrcProfile->MFPRequired;
pDstProfile->MFPCapable = pSrcProfile->MFPCapable;
#endif
#ifdef WLAN_FEATURE_VOWIFI_11R
if (pSrcProfile->MDID.mdiePresent)
{
pDstProfile->MDID.mdiePresent = 1;
pDstProfile->MDID.mobilityDomain = pSrcProfile->MDID.mobilityDomain;
}
#endif
}while(0);
if(!HAL_STATUS_SUCCESS(status))
{
csrReleaseProfile(pMac, pDstProfile);
pDstProfile = NULL;
}
return (status);
}
eHalStatus csrRoamIssueConnect(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfile *pProfile,
tScanResultHandle hBSSList,
eCsrRoamReason reason, tANI_U32 roamId, tANI_BOOLEAN fImediate,
tANI_BOOLEAN fClearScan)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tSmeCmd *pCommand;
pCommand = csrGetCommandBuffer(pMac);
if(NULL == pCommand)
{
smsLog( pMac, LOGE, FL(" fail to get command buffer") );
status = eHAL_STATUS_RESOURCES;
}
else
{
if( fClearScan )
{
csrScanCancelIdleScan(pMac);
csrScanAbortMacScanNotForConnect(pMac, sessionId);
}
pCommand->u.roamCmd.fReleaseProfile = eANI_BOOLEAN_FALSE;
if(NULL == pProfile)
{
//We can roam now
//Since pProfile is NULL, we need to build our own profile, set everything to default
//We can only support open and no encryption
pCommand->u.roamCmd.roamProfile.AuthType.numEntries = 1;
pCommand->u.roamCmd.roamProfile.AuthType.authType[0] = eCSR_AUTH_TYPE_OPEN_SYSTEM;
pCommand->u.roamCmd.roamProfile.EncryptionType.numEntries = 1;
pCommand->u.roamCmd.roamProfile.EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_NONE;
pCommand->u.roamCmd.roamProfile.csrPersona = VOS_STA_MODE;
}
else
{
//make a copy of the profile
status = csrRoamCopyProfile(pMac, &pCommand->u.roamCmd.roamProfile, pProfile);
if(HAL_STATUS_SUCCESS(status))
{
pCommand->u.roamCmd.fReleaseProfile = eANI_BOOLEAN_TRUE;
}
}
pCommand->command = eSmeCommandRoam;
pCommand->sessionId = (tANI_U8)sessionId;
pCommand->u.roamCmd.hBSSList = hBSSList;
pCommand->u.roamCmd.roamId = roamId;
pCommand->u.roamCmd.roamReason = reason;
//We need to free the BssList when the command is done
pCommand->u.roamCmd.fReleaseBssList = eANI_BOOLEAN_TRUE;
pCommand->u.roamCmd.fUpdateCurRoamProfile = eANI_BOOLEAN_TRUE;
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
FL("CSR PERSONA=%d"),
pCommand->u.roamCmd.roamProfile.csrPersona);
status = csrQueueSmeCommand(pMac, pCommand, fImediate);
if( !HAL_STATUS_SUCCESS( status ) )
{
smsLog( pMac, LOGE, FL(" fail to send message status = %d"), status );
csrReleaseCommandRoam( pMac, pCommand );
}
}
return (status);
}
eHalStatus csrRoamIssueReassoc(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfile *pProfile,
tCsrRoamModifyProfileFields *pMmodProfileFields,
eCsrRoamReason reason, tANI_U32 roamId, tANI_BOOLEAN fImediate)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tSmeCmd *pCommand;
pCommand = csrGetCommandBuffer(pMac);
if(NULL == pCommand)
{
smsLog( pMac, LOGE, FL(" fail to get command buffer") );
status = eHAL_STATUS_RESOURCES;
}
else
{
csrScanCancelIdleScan(pMac);
csrScanAbortMacScanNotForConnect(pMac, sessionId);
if(pProfile)
{
//This is likely trying to reassoc to different profile
pCommand->u.roamCmd.fReleaseProfile = eANI_BOOLEAN_FALSE;
//make a copy of the profile
status = csrRoamCopyProfile(pMac, &pCommand->u.roamCmd.roamProfile, pProfile);
pCommand->u.roamCmd.fUpdateCurRoamProfile = eANI_BOOLEAN_TRUE;
}
else
{
status = csrRoamCopyConnectedProfile(pMac, sessionId, &pCommand->u.roamCmd.roamProfile);
//how to update WPA/WPA2 info in roamProfile??
pCommand->u.roamCmd.roamProfile.uapsd_mask = pMmodProfileFields->uapsd_mask;
}
if(HAL_STATUS_SUCCESS(status))
{
pCommand->u.roamCmd.fReleaseProfile = eANI_BOOLEAN_TRUE;
}
pCommand->command = eSmeCommandRoam;
pCommand->sessionId = (tANI_U8)sessionId;
pCommand->u.roamCmd.roamId = roamId;
pCommand->u.roamCmd.roamReason = reason;
//We need to free the BssList when the command is done
//For reassoc there is no BSS list, so the boolean set to false
pCommand->u.roamCmd.hBSSList = CSR_INVALID_SCANRESULT_HANDLE;
pCommand->u.roamCmd.fReleaseBssList = eANI_BOOLEAN_FALSE;
pCommand->u.roamCmd.fReassoc = eANI_BOOLEAN_TRUE;
status = csrQueueSmeCommand(pMac, pCommand, fImediate);
if( !HAL_STATUS_SUCCESS( status ) )
{
smsLog( pMac, LOGE, FL(" fail to send message status = %d"), status );
csrRoamCompletion(pMac, sessionId, NULL, pCommand, eCSR_ROAM_RESULT_FAILURE, eANI_BOOLEAN_FALSE);
csrReleaseCommandRoam( pMac, pCommand );
}
}
return (status);
}
eHalStatus csrRoamEnqueuePreauth(tpAniSirGlobal pMac, tANI_U32 sessionId, tpSirBssDescription pBssDescription,
eCsrRoamReason reason, tANI_BOOLEAN fImmediate)
// , eCsrRoamReason reason, tANI_U32 roamId, tANI_BOOLEAN fImediate)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tSmeCmd *pCommand;
pCommand = csrGetCommandBuffer(pMac);
if(NULL == pCommand)
{
smsLog( pMac, LOGE, FL(" fail to get command buffer") );
status = eHAL_STATUS_RESOURCES;
}
else
{
if(pBssDescription)
{
//copy over the parameters we need later
pCommand->command = eSmeCommandRoam;
pCommand->sessionId = (tANI_U8)sessionId;
pCommand->u.roamCmd.roamReason = reason;
//this is the important parameter
//in this case we are using this field for the "next" BSS
pCommand->u.roamCmd.pLastRoamBss = pBssDescription;
status = csrQueueSmeCommand(pMac, pCommand, fImmediate);
if( !HAL_STATUS_SUCCESS( status ) )
{
smsLog( pMac, LOGE, FL(" fail to enqueue preauth command, status = %d"), status );
csrReleaseCommandPreauth( pMac, pCommand );
}
}
else
{
//Return failure
status = eHAL_STATUS_RESOURCES;
}
}
return (status);
}
eHalStatus csrRoamDequeuePreauth(tpAniSirGlobal pMac)
{
tListElem *pEntry;
tSmeCmd *pCommand;
pEntry = csrLLPeekHead( &pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK );
if ( pEntry )
{
pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link );
if ( (eSmeCommandRoam == pCommand->command) &&
(eCsrPerformPreauth == pCommand->u.roamCmd.roamReason))
{
smsLog( pMac, LOG1, FL("DQ-Command = %d, Reason = %d"),
pCommand->command, pCommand->u.roamCmd.roamReason);
if (csrLLRemoveEntry( &pMac->sme.smeCmdActiveList, pEntry, LL_ACCESS_LOCK )) {
csrReleaseCommandPreauth( pMac, pCommand );
}
} else {
smsLog( pMac, LOGE, FL("Command = %d, Reason = %d "),
pCommand->command, pCommand->u.roamCmd.roamReason);
}
}
else {
smsLog( pMac, LOGE, FL("pEntry NULL for eWNI_SME_FT_PRE_AUTH_RSP"));
}
smeProcessPendingQueue( pMac );
return eHAL_STATUS_SUCCESS;
}
eHalStatus csrRoamConnectWithBSSList(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfile *pProfile,
tScanResultHandle hBssListIn, tANI_U32 *pRoamId)
{
eHalStatus status = eHAL_STATUS_FAILURE;
tScanResultHandle hBSSList;
tANI_U32 roamId = 0;
status = csrScanCopyResultList(pMac, hBssListIn, &hBSSList);
if(HAL_STATUS_SUCCESS(status))
{
roamId = GET_NEXT_ROAM_ID(&pMac->roam);
if(pRoamId)
{
*pRoamId = roamId;
}
status = csrRoamIssueConnect(pMac, sessionId, pProfile, hBSSList, eCsrHddIssued,
roamId, eANI_BOOLEAN_FALSE, eANI_BOOLEAN_FALSE);
if(!HAL_STATUS_SUCCESS(status))
{
smsLog(pMac, LOGE, FL("failed to start a join process"));
csrScanResultPurge(pMac, hBSSList);
}
}
return (status);
}
eHalStatus csrRoamConnect(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfile *pProfile,
tScanResultHandle hBssListIn, tANI_U32 *pRoamId)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tScanResultHandle hBSSList;
tCsrScanResultFilter *pScanFilter;
tANI_U32 roamId = 0;
tANI_BOOLEAN fCallCallback = eANI_BOOLEAN_FALSE;
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
if (NULL == pProfile)
{
smsLog(pMac, LOGP, FL("No profile specified"));
return eHAL_STATUS_FAILURE;
}
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return eHAL_STATUS_FAILURE;
}
smsLog(pMac, LOG1, FL("called BSSType = %s (%d) authtype = %d "
"encryType = %d"),
lim_BssTypetoString(pProfile->BSSType),
pProfile->BSSType,
pProfile->AuthType.authType[0],
pProfile->EncryptionType.encryptionType[0]);
if( CSR_IS_WDS( pProfile ) &&
!HAL_STATUS_SUCCESS( status = csrIsBTAMPAllowed( pMac, pProfile->operationChannel ) ) )
{
smsLog(pMac, LOGE, FL("Request for BT AMP connection failed, channel requested is different than infra = %d"),
pProfile->operationChannel);
return status;
}
/* Reset abortConnection for the fresh connection */
pSession->abortConnection = FALSE;
csrRoamCancelRoaming(pMac, sessionId);
csrScanRemoveFreshScanCommand(pMac, sessionId);
csrScanCancelIdleScan(pMac);
//Only abort the scan if it is not used for other roam/connect purpose
csrScanAbortMacScan(pMac, sessionId, eCSR_SCAN_ABORT_DEFAULT);
if (!vos_concurrent_open_sessions_running() &&
(VOS_STA_SAP_MODE == pProfile->csrPersona))
{
/* In case of AP mode we do not want idle mode scan */
csrScanDisable(pMac);
}
csrRoamRemoveDuplicateCommand(pMac, sessionId, NULL, eCsrHddIssued);
//Check whether ssid changes
if(csrIsConnStateConnected(pMac, sessionId))
{
if(pProfile->SSIDs.numOfSSIDs && !csrIsSsidInList(pMac, &pSession->connectedProfile.SSID, &pProfile->SSIDs))
{
csrRoamIssueDisassociateCmd(pMac, sessionId, eCSR_DISCONNECT_REASON_UNSPECIFIED);
}
}
#ifdef FEATURE_WLAN_BTAMP_UT_RF
pSession->maxRetryCount = CSR_JOIN_MAX_RETRY_COUNT;
#endif
if(CSR_INVALID_SCANRESULT_HANDLE != hBssListIn)
{
smsLog(pMac, LOG1, FL("is called with BSSList"));
status = csrRoamConnectWithBSSList(pMac, sessionId, pProfile, hBssListIn, pRoamId);
if(pRoamId)
{
roamId = *pRoamId;
}
if(!HAL_STATUS_SUCCESS(status))
{
fCallCallback = eANI_BOOLEAN_TRUE;
}
}
else
{
pScanFilter = vos_mem_malloc(sizeof(tCsrScanResultFilter));
if ( NULL == pScanFilter )
status = eHAL_STATUS_FAILURE;
else
status = eHAL_STATUS_SUCCESS;
if(HAL_STATUS_SUCCESS(status))
{
vos_mem_set(pScanFilter, sizeof(tCsrScanResultFilter), 0);
//Try to connect to any BSS
if(NULL == pProfile)
{
//No encryption
pScanFilter->EncryptionType.numEntries = 1;
pScanFilter->EncryptionType.encryptionType[0] = eCSR_ENCRYPT_TYPE_NONE;
}//we don't have a profile
else
{
//Here is the profile we need to connect to
status = csrRoamPrepareFilterFromProfile(pMac, pProfile, pScanFilter);
}//We have a profile
roamId = GET_NEXT_ROAM_ID(&pMac->roam);
if(pRoamId)
{
*pRoamId = roamId;
}
if(HAL_STATUS_SUCCESS(status))
{
/*Save the WPS info*/
if(NULL != pProfile)
{
pScanFilter->bWPSAssociation = pProfile->bWPSAssociation;
pScanFilter->bOSENAssociation = pProfile->bOSENAssociation;
}
else
{
pScanFilter->bWPSAssociation = 0;
pScanFilter->bOSENAssociation = 0;
}
do
{
if( (pProfile && CSR_IS_WDS_AP( pProfile ) )
|| (pProfile && CSR_IS_INFRA_AP ( pProfile ))
)
{
//This can be started right away
status = csrRoamIssueConnect(pMac, sessionId, pProfile, NULL, eCsrHddIssued,
roamId, eANI_BOOLEAN_FALSE, eANI_BOOLEAN_FALSE);
if(!HAL_STATUS_SUCCESS(status))
{
smsLog(pMac, LOGE, FL(" CSR failed to issue start BSS command with status = 0x%08X"), status);
fCallCallback = eANI_BOOLEAN_TRUE;
}
else
{
smsLog(pMac, LOG1, FL("Connect request to proceed for AMP/SoftAP mode"));
}
break;
}
status = csrScanGetResult(pMac, pScanFilter, &hBSSList);
smsLog(pMac, LOG1, "************ csrScanGetResult Status ********* %d", status);
if(HAL_STATUS_SUCCESS(status))
{
status = csrRoamIssueConnect(pMac, sessionId, pProfile, hBSSList, eCsrHddIssued,
roamId, eANI_BOOLEAN_FALSE, eANI_BOOLEAN_FALSE);
if(!HAL_STATUS_SUCCESS(status))
{
smsLog(pMac, LOGE, FL(" CSR failed to issue connect command with status = 0x%08X"), status);
csrScanResultPurge(pMac, hBSSList);
fCallCallback = eANI_BOOLEAN_TRUE;
}
}//Have scan result
else if(NULL != pProfile)
{
//Check whether it is for start ibss
if(CSR_IS_START_IBSS(pProfile))
{
status = csrRoamIssueConnect(pMac, sessionId, pProfile, NULL, eCsrHddIssued,
roamId, eANI_BOOLEAN_FALSE, eANI_BOOLEAN_FALSE);
if(!HAL_STATUS_SUCCESS(status))
{
smsLog(pMac, LOGE, " CSR failed to issue startIBSS command with status = 0x%08X", status);
fCallCallback = eANI_BOOLEAN_TRUE;
}
}
else
{
//scan for this SSID
status = csrScanForSSID(pMac, sessionId, pProfile, roamId, TRUE);
if(!HAL_STATUS_SUCCESS(status))
{
smsLog(pMac, LOGE, FL(" CSR failed to issue SSID scan command with status = 0x%08X"), status);
fCallCallback = eANI_BOOLEAN_TRUE;
}
else
{
smsLog(pMac, LOG1, FL("SSID scan requested for Infra connect req"));
}
}
}
else
{
fCallCallback = eANI_BOOLEAN_TRUE;
}
} while (0);
if(NULL != pProfile)
{
//we need to free memory for filter if profile exists
csrFreeScanFilter(pMac, pScanFilter);
}
}//Got the scan filter from profile
vos_mem_free(pScanFilter);
}//allocated memory for pScanFilter
}//No Bsslist coming in
//tell the caller if we fail to trigger a join request
if( fCallCallback )
{
csrRoamCallCallback(pMac, sessionId, NULL, roamId, eCSR_ROAM_FAILED, eCSR_ROAM_RESULT_FAILURE);
}
return (status);
}
eHalStatus csrRoamReassoc(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfile *pProfile,
tCsrRoamModifyProfileFields modProfileFields,
tANI_U32 *pRoamId)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tANI_BOOLEAN fCallCallback = eANI_BOOLEAN_TRUE;
tANI_U32 roamId = 0;
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
if (NULL == pProfile)
{
smsLog(pMac, LOGP, FL("No profile specified"));
return eHAL_STATUS_FAILURE;
}
smsLog(pMac, LOG1, FL("called BSSType = %s (%d) authtype = %d "
"encryType = %d"),
lim_BssTypetoString(pProfile->BSSType),
pProfile->BSSType,
pProfile->AuthType.authType[0],
pProfile->EncryptionType.encryptionType[0]);
csrRoamCancelRoaming(pMac, sessionId);
csrScanRemoveFreshScanCommand(pMac, sessionId);
csrScanCancelIdleScan(pMac);
csrScanAbortMacScanNotForConnect(pMac, sessionId);
csrRoamRemoveDuplicateCommand(pMac, sessionId, NULL, eCsrHddIssuedReassocToSameAP);
if(csrIsConnStateConnected(pMac, sessionId))
{
if(pProfile)
{
if(pProfile->SSIDs.numOfSSIDs &&
csrIsSsidInList(pMac, &pSession->connectedProfile.SSID, &pProfile->SSIDs))
{
fCallCallback = eANI_BOOLEAN_FALSE;
}
else
{
smsLog(pMac, LOG1, FL("Not connected to the same SSID asked in the profile"));
}
}
else if (!vos_mem_compare(&modProfileFields,
&pSession->connectedProfile.modifyProfileFields,
sizeof(tCsrRoamModifyProfileFields)))
{
fCallCallback = eANI_BOOLEAN_FALSE;
}
else
{
smsLog(pMac, LOG1, FL("Either the profile is NULL or none of the fields "
"in tCsrRoamModifyProfileFields got modified"));
}
}
else
{
smsLog(pMac, LOG1, FL("Not connected! No need to reassoc"));
}
if(!fCallCallback)
{
roamId = GET_NEXT_ROAM_ID(&pMac->roam);
if(pRoamId)
{
*pRoamId = roamId;
}
status = csrRoamIssueReassoc(pMac, sessionId, pProfile, &modProfileFields,
eCsrHddIssuedReassocToSameAP, roamId, eANI_BOOLEAN_FALSE);
}
else
{
status = csrRoamCallCallback(pMac, sessionId, NULL, roamId,
eCSR_ROAM_FAILED, eCSR_ROAM_RESULT_FAILURE);
}
return status;
}
eHalStatus csrRoamJoinLastProfile(tpAniSirGlobal pMac, tANI_U32 sessionId)
{
eHalStatus status = eHAL_STATUS_FAILURE;
tScanResultHandle hBSSList = NULL;
tCsrScanResultFilter *pScanFilter = NULL;
tANI_U32 roamId;
tCsrRoamProfile *pProfile = NULL;
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return eHAL_STATUS_FAILURE;
}
do
{
if(pSession->pCurRoamProfile)
{
csrScanCancelIdleScan(pMac);
csrScanAbortMacScanNotForConnect(pMac, sessionId);
//We have to make a copy of pCurRoamProfile because it will be free inside csrRoamIssueConnect
pProfile = vos_mem_malloc(sizeof(tCsrRoamProfile));
if ( NULL == pProfile )
status = eHAL_STATUS_FAILURE;
else
status = eHAL_STATUS_SUCCESS;
if(!HAL_STATUS_SUCCESS(status))
break;
vos_mem_set(pProfile, sizeof(tCsrRoamProfile), 0);
status = csrRoamCopyProfile(pMac, pProfile, pSession->pCurRoamProfile);
if (!HAL_STATUS_SUCCESS(status))
break;
pScanFilter = vos_mem_malloc(sizeof(tCsrScanResultFilter));
if ( NULL == pScanFilter )
status = eHAL_STATUS_FAILURE;
else
status = eHAL_STATUS_SUCCESS;
if(!HAL_STATUS_SUCCESS(status))
{
break;
}
vos_mem_set(pScanFilter, sizeof(tCsrScanResultFilter), 0);
status = csrRoamPrepareFilterFromProfile(pMac, pProfile, pScanFilter);
if(!HAL_STATUS_SUCCESS(status))
{
break;
}
roamId = GET_NEXT_ROAM_ID(&pMac->roam);
status = csrScanGetResult(pMac, pScanFilter, &hBSSList);
if(HAL_STATUS_SUCCESS(status))
{
//we want to put the last connected BSS to the very beginning, if possible
csrMoveBssToHeadFromBSSID(pMac, &pSession->connectedProfile.bssid, hBSSList);
status = csrRoamIssueConnect(pMac, sessionId, pProfile, hBSSList, eCsrHddIssued,
roamId, eANI_BOOLEAN_FALSE, eANI_BOOLEAN_FALSE);
if(!HAL_STATUS_SUCCESS(status))
{
csrScanResultPurge(pMac, hBSSList);
break;
}
}
else
{
//Do a scan on this profile
//scan for this SSID only in case the AP suppresses SSID
status = csrScanForSSID(pMac, sessionId, pProfile, roamId, TRUE);
if(!HAL_STATUS_SUCCESS(status))
{
break;
}
}
}//We have a profile
else
{
smsLog(pMac, LOGW, FL("cannot find a roaming profile"));
break;
}
}while(0);
if(pScanFilter)
{
csrFreeScanFilter(pMac, pScanFilter);
vos_mem_free(pScanFilter);
}
if(NULL != pProfile)
{
csrReleaseProfile(pMac, pProfile);
vos_mem_free(pProfile);
}
return (status);
}
eHalStatus csrRoamReconnect(tpAniSirGlobal pMac, tANI_U32 sessionId)
{
eHalStatus status = eHAL_STATUS_FAILURE;
if(csrIsConnStateConnected(pMac, sessionId))
{
status = csrRoamIssueDisassociateCmd(pMac, sessionId, eCSR_DISCONNECT_REASON_UNSPECIFIED);
if(HAL_STATUS_SUCCESS(status))
{
status = csrRoamJoinLastProfile(pMac, sessionId);
}
}
return (status);
}
eHalStatus csrRoamConnectToLastProfile(tpAniSirGlobal pMac, tANI_U32 sessionId)
{
eHalStatus status = eHAL_STATUS_FAILURE;
smsLog(pMac, LOGW, FL("is called"));
csrRoamCancelRoaming(pMac, sessionId);
csrRoamRemoveDuplicateCommand(pMac, sessionId, NULL, eCsrHddIssued);
if(csrIsConnStateDisconnected(pMac, sessionId))
{
status = csrRoamJoinLastProfile(pMac, sessionId);
}
return (status);
}
eHalStatus csrRoamProcessDisassocDeauth( tpAniSirGlobal pMac, tSmeCmd *pCommand, tANI_BOOLEAN fDisassoc, tANI_BOOLEAN fMICFailure )
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tANI_BOOLEAN fComplete = eANI_BOOLEAN_FALSE;
eCsrRoamSubState NewSubstate;
tANI_U32 sessionId = pCommand->sessionId;
if( CSR_IS_WAIT_FOR_KEY( pMac, sessionId ) )
{
smsLog(pMac, LOG1, FL(" Stop Wait for key timer and change substate to"
" eCSR_ROAM_SUBSTATE_NONE"));
csrRoamStopWaitForKeyTimer( pMac );
csrRoamSubstateChange( pMac, eCSR_ROAM_SUBSTATE_NONE, sessionId);
}
// change state to 'Roaming'...
csrRoamStateChange( pMac, eCSR_ROAMING_STATE_JOINING, sessionId );
if ( csrIsConnStateIbss( pMac, sessionId ) )
{
// If we are in an IBSS, then stop the IBSS...
status = csrRoamIssueStopBss( pMac, sessionId, eCSR_ROAM_SUBSTATE_STOP_BSS_REQ );
fComplete = (!HAL_STATUS_SUCCESS(status));
}
else if ( csrIsConnStateInfra( pMac, sessionId ) )
{
smsLog(pMac, LOG1, FL(" restore AC weights (%d-%d-%d-%d)"), pMac->roam.ucACWeights[0], pMac->roam.ucACWeights[1],
pMac->roam.ucACWeights[2], pMac->roam.ucACWeights[3]);
//Restore AC weight in case we change it
WLANTL_SetACWeights(pMac->roam.gVosContext, pMac->roam.ucACWeights);
// in Infrasturcture, we need to disassociate from the Infrastructure network...
NewSubstate = eCSR_ROAM_SUBSTATE_DISASSOC_FORCED;
if(eCsrSmeIssuedDisassocForHandoff == pCommand->u.roamCmd.roamReason)
{
NewSubstate = eCSR_ROAM_SUBSTATE_DISASSOC_HANDOFF;
}
else
{
// If we are in neighbor preauth done state then on receiving
// disassoc or deauth we dont roam instead we just disassoc
// from current ap and then go to disconnected state
// This happens for ESE and 11r FT connections ONLY.
#ifdef WLAN_FEATURE_VOWIFI_11R
if (csrRoamIs11rAssoc(pMac) &&
(csrNeighborRoamStatePreauthDone(pMac)))
{
csrNeighborRoamTranistionPreauthDoneToDisconnected(pMac);
}
#endif
#ifdef FEATURE_WLAN_ESE
if (csrRoamIsESEAssoc(pMac) &&
(csrNeighborRoamStatePreauthDone(pMac)))
{
csrNeighborRoamTranistionPreauthDoneToDisconnected(pMac);
}
#endif
#ifdef FEATURE_WLAN_LFR
if (csrRoamIsFastRoamEnabled(pMac, sessionId) &&
(csrNeighborRoamStatePreauthDone(pMac)))
{
csrNeighborRoamTranistionPreauthDoneToDisconnected(pMac);
}
#endif
#ifdef WLAN_FEATURE_LFR_MBB
csr_stop_preauth_reassoc_mbb_timer(pMac);
#endif
}
if( fDisassoc )
{
status = csrRoamIssueDisassociate( pMac, sessionId, NewSubstate, fMICFailure );
if (pMac->roam.configParam.roamDelayStatsEnabled)
{
vos_record_roam_event(e_SME_DISASSOC_ISSUE, NULL, 0);
}
}
else
{
status = csrRoamIssueDeauth( pMac, sessionId, eCSR_ROAM_SUBSTATE_DEAUTH_REQ );
}
fComplete = (!HAL_STATUS_SUCCESS(status));
}
else if ( csrIsConnStateWds( pMac, sessionId ) )
{
if( CSR_IS_WDS_AP( &pMac->roam.roamSession[sessionId].connectedProfile ) )
{
status = csrRoamIssueStopBss( pMac, sessionId, eCSR_ROAM_SUBSTATE_STOP_BSS_REQ );
fComplete = (!HAL_STATUS_SUCCESS(status));
}
//This has to be WDS station
else if( csrIsConnStateConnectedWds( pMac, sessionId ) ) //This has to be WDS station
{
pCommand->u.roamCmd.fStopWds = eANI_BOOLEAN_TRUE;
if( fDisassoc )
{
status = csrRoamIssueDisassociate( pMac, sessionId,
eCSR_ROAM_SUBSTATE_DISCONNECT_CONTINUE_ROAMING, fMICFailure );
fComplete = (!HAL_STATUS_SUCCESS(status));
}
}
} else {
// we got a dis-assoc request while not connected to any peer
// just complete the command
fComplete = eANI_BOOLEAN_TRUE;
status = eHAL_STATUS_FAILURE;
}
if(fComplete)
{
csrRoamComplete( pMac, eCsrNothingToJoin, NULL );
}
if(HAL_STATUS_SUCCESS(status))
{
if ( csrIsConnStateInfra( pMac, sessionId ) )
{
//Set the state to disconnect here
pMac->roam.roamSession[sessionId].connectState = eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED;
#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
//we don't need to run this timer any more
if (VOS_TIMER_STATE_RUNNING ==
pMac->roam.neighborRoamInfo.forcedInitialRoamTo5GHTimer.state)
{
status = vos_timer_stop(&pMac->roam.neighborRoamInfo.forcedInitialRoamTo5GHTimer);
if (status != eHAL_STATUS_SUCCESS)
smsLog(pMac, LOGE, FL("Failed to Stop Forced 5G timer"));
}
#endif
}
}
else
{
smsLog(pMac, LOGW, FL(" failed with status %d"), status);
}
return (status);
}
/* This is been removed from latest code base */
/*
static eHalStatus csrRoamProcessStopBss( tpAniSirGlobal pMac, tSmeCmd *pCommand )
{
eHalStatus status;
tANI_U32 sessionId = pCommand->sessionId;
csrRoamStateChange( pMac, eCSR_ROAMING_STATE_JOINING );
status = csrRoamIssueStopBss( pMac, sessionId, eCSR_ROAM_SUBSTATE_STOP_BSS_REQ );
return ( status );
}
*/
eHalStatus csrRoamIssueDisassociateCmd( tpAniSirGlobal pMac, tANI_U32 sessionId, eCsrRoamDisconnectReason reason )
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tSmeCmd *pCommand;
do
{
pCommand = csrGetCommandBuffer( pMac );
if ( !pCommand )
{
smsLog( pMac, LOGE, FL(" fail to get command buffer") );
status = eHAL_STATUS_RESOURCES;
break;
}
//Change the substate in case it is wait-for-key
if( CSR_IS_WAIT_FOR_KEY( pMac, sessionId ) )
{
csrRoamStopWaitForKeyTimer( pMac );
csrRoamSubstateChange( pMac, eCSR_ROAM_SUBSTATE_NONE, sessionId);
}
pCommand->command = eSmeCommandRoam;
pCommand->sessionId = (tANI_U8)sessionId;
smsLog( pMac, LOG1, FL("Disassociate reason: %d, sessionId: %d"),
reason,sessionId);
switch ( reason )
{
case eCSR_DISCONNECT_REASON_MIC_ERROR:
pCommand->u.roamCmd.roamReason = eCsrForcedDisassocMICFailure;
break;
case eCSR_DISCONNECT_REASON_DEAUTH:
pCommand->u.roamCmd.roamReason = eCsrForcedDeauth;
break;
case eCSR_DISCONNECT_REASON_HANDOFF:
pCommand->u.roamCmd.roamReason = eCsrSmeIssuedDisassocForHandoff;
break;
case eCSR_DISCONNECT_REASON_UNSPECIFIED:
case eCSR_DISCONNECT_REASON_DISASSOC:
pCommand->u.roamCmd.roamReason = eCsrForcedDisassoc;
break;
case eCSR_DISCONNECT_REASON_IBSS_JOIN_FAILURE:
pCommand->u.roamCmd.roamReason = eCsrSmeIssuedIbssJoinFailure;
break;
case eCSR_DISCONNECT_REASON_IBSS_LEAVE:
pCommand->u.roamCmd.roamReason = eCsrForcedIbssLeave;
break;
default:
break;
}
status = csrQueueSmeCommand(pMac, pCommand, eANI_BOOLEAN_TRUE);
if( !HAL_STATUS_SUCCESS( status ) )
{
smsLog( pMac, LOGE, FL(" fail to send message status = %d"), status );
csrReleaseCommandRoam( pMac, pCommand );
}
} while( 0 );
return( status );
}
eHalStatus csrRoamIssueStopBssCmd( tpAniSirGlobal pMac, tANI_U32 sessionId, tANI_BOOLEAN fHighPriority )
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tSmeCmd *pCommand;
pCommand = csrGetCommandBuffer( pMac );
if ( NULL != pCommand )
{
//Change the substate in case it is wait-for-key
if( CSR_IS_WAIT_FOR_KEY( pMac, sessionId) )
{
csrRoamStopWaitForKeyTimer( pMac );
csrRoamSubstateChange( pMac, eCSR_ROAM_SUBSTATE_NONE, sessionId);
}
pCommand->command = eSmeCommandRoam;
pCommand->sessionId = (tANI_U8)sessionId;
pCommand->u.roamCmd.roamReason = eCsrStopBss;
status = csrQueueSmeCommand(pMac, pCommand, fHighPriority);
if( !HAL_STATUS_SUCCESS( status ) )
{
smsLog( pMac, LOGE, FL(" fail to send message status = %d"), status );
csrReleaseCommandRoam( pMac, pCommand );
}
}
else
{
smsLog( pMac, LOGE, FL(" fail to get command buffer") );
status = eHAL_STATUS_RESOURCES;
}
return ( status );
}
eHalStatus csrRoamDisconnectInternal(tpAniSirGlobal pMac, tANI_U32 sessionId, eCsrRoamDisconnectReason reason)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return eHAL_STATUS_FAILURE;
}
#ifdef FEATURE_WLAN_BTAMP_UT_RF
//Stop te retry
pSession->maxRetryCount = 0;
csrRoamStopJoinRetryTimer(pMac, sessionId);
#endif
//Not to call cancel roaming here
//Only issue disconnect when necessary
if(csrIsConnStateConnected(pMac, sessionId) || csrIsBssTypeIBSS(pSession->connectedProfile.BSSType)
|| csrIsBssTypeWDS(pSession->connectedProfile.BSSType)
|| csrIsRoamCommandWaitingForSession(pMac, sessionId) )
{
smsLog(pMac, LOG2, FL("called"));
status = csrRoamIssueDisassociateCmd(pMac, sessionId, reason);
}
else
{
csrScanAbortScanForSSID(pMac, sessionId);
csrScanStartIdleScan(pMac);
status = eHAL_STATUS_CMD_NOT_QUEUED;
smsLog(pMac, LOGE,
FL("Disconnect not queued, Abort Scan for SSID"));
}
return (status);
}
eHalStatus csrRoamDisconnect(tpAniSirGlobal pMac, tANI_U32 sessionId, eCsrRoamDisconnectReason reason)
{
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return eHAL_STATUS_FAILURE;
}
csrRoamCancelRoaming(pMac, sessionId);
csrRoamRemoveDuplicateCommand(pMac, sessionId, NULL, eCsrForcedDisassoc);
return (csrRoamDisconnectInternal(pMac, sessionId, reason));
}
void csr_abortConnection(tpAniSirGlobal pMac, tANI_U32 sessionId)
{
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return;
}
pSession->abortConnection = TRUE;
return;
}
eHalStatus csrRoamSaveConnectedInfomation(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfile *pProfile,
tSirBssDescription *pSirBssDesc, tDot11fBeaconIEs *pIes)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tDot11fBeaconIEs *pIesTemp = pIes;
tANI_U8 index;
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
tCsrRoamConnectedProfile *pConnectProfile = &pSession->connectedProfile;
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return eHAL_STATUS_FAILURE;
}
if(pConnectProfile->pAddIEAssoc)
{
vos_mem_free(pConnectProfile->pAddIEAssoc);
pConnectProfile->pAddIEAssoc = NULL;
}
vos_mem_set(&pSession->connectedProfile, sizeof(tCsrRoamConnectedProfile), 0);
pConnectProfile->AuthType = pProfile->negotiatedAuthType;
pConnectProfile->AuthInfo = pProfile->AuthType;
pConnectProfile->CBMode = pProfile->CBMode; //*** this may not be valid
pConnectProfile->EncryptionType = pProfile->negotiatedUCEncryptionType;
pConnectProfile->EncryptionInfo = pProfile->EncryptionType;
pConnectProfile->mcEncryptionType = pProfile->negotiatedMCEncryptionType;
pConnectProfile->mcEncryptionInfo = pProfile->mcEncryptionType;
pConnectProfile->BSSType = pProfile->BSSType;
pConnectProfile->modifyProfileFields.uapsd_mask = pProfile->uapsd_mask;
pConnectProfile->operationChannel = pSirBssDesc->channelId;
pConnectProfile->beaconInterval = pSirBssDesc->beaconInterval;
if (!pConnectProfile->beaconInterval)
{
smsLog(pMac, LOGW, FL("ERROR: Beacon interval is ZERO"));
}
vos_mem_copy(&pConnectProfile->Keys, &pProfile->Keys, sizeof(tCsrKeys));
/* saving the addional IE`s like Hot spot indication element and extended capabilities */
if(pProfile->nAddIEAssocLength)
{
pConnectProfile->pAddIEAssoc = vos_mem_malloc(pProfile->nAddIEAssocLength);
if ( NULL == pConnectProfile->pAddIEAssoc )
status = eHAL_STATUS_FAILURE;
else
status = eHAL_STATUS_SUCCESS;
if (!HAL_STATUS_SUCCESS(status))
{
smsLog(pMac, LOGE, FL("Failed to allocate memory for additional IEs")) ;
return eHAL_STATUS_FAILURE;
}
pConnectProfile->nAddIEAssocLength = pProfile->nAddIEAssocLength;
vos_mem_copy(pConnectProfile->pAddIEAssoc, pProfile->pAddIEAssoc,
pProfile->nAddIEAssocLength);
}
#ifdef WLAN_FEATURE_11W
pConnectProfile->MFPEnabled = pProfile->MFPEnabled;
pConnectProfile->MFPRequired = pProfile->MFPRequired;
pConnectProfile->MFPCapable = pProfile->MFPCapable;
#endif
//Save bssid
csrGetBssIdBssDesc(pMac, pSirBssDesc, &pConnectProfile->bssid);
#ifdef WLAN_FEATURE_VOWIFI_11R
if (pSirBssDesc->mdiePresent)
{
pConnectProfile->MDID.mdiePresent = 1;
pConnectProfile->MDID.mobilityDomain = (pSirBssDesc->mdie[1] << 8) | (pSirBssDesc->mdie[0]);
}
#endif
if( NULL == pIesTemp )
{
status = csrGetParsedBssDescriptionIEs(pMac, pSirBssDesc, &pIesTemp);
}
#ifdef FEATURE_WLAN_ESE
if ((csrIsProfileESE(pProfile) ||
((pIesTemp->ESEVersion.present)
&& ((pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_OPEN_SYSTEM)
|| (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_WPA)
|| (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_WPA_PSK)
|| (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_RSN)
#ifdef WLAN_FEATURE_11W
|| (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_RSN_PSK_SHA256)
|| (pProfile->negotiatedAuthType ==
eCSR_AUTH_TYPE_RSN_8021X_SHA256)
#endif
|| (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_RSN_PSK))))
&& (pMac->roam.configParam.isEseIniFeatureEnabled))
{
pConnectProfile->isESEAssoc = 1;
}
#endif
//save ssid
if(HAL_STATUS_SUCCESS(status))
{
if(pIesTemp->SSID.present)
{
pConnectProfile->SSID.length = pIesTemp->SSID.num_ssid;
vos_mem_copy(pConnectProfile->SSID.ssId, pIesTemp->SSID.ssid,
pIesTemp->SSID.num_ssid);
}
//Save the bss desc
status = csrRoamSaveConnectedBssDesc(pMac, sessionId, pSirBssDesc);
if( CSR_IS_QOS_BSS(pIesTemp) || pIesTemp->HTCaps.present)
{
//Some HT AP's dont send WMM IE so in that case we assume all HT Ap's are Qos Enabled AP's
pConnectProfile->qap = TRUE;
}
else
{
pConnectProfile->qap = FALSE;
}
if ( NULL == pIes )
{
//Free memory if it allocated locally
vos_mem_free(pIesTemp);
}
}
//Save Qos connection
pConnectProfile->qosConnection = pMac->roam.roamSession[sessionId].fWMMConnection;
if(!HAL_STATUS_SUCCESS(status))
{
csrFreeConnectBssDesc(pMac, sessionId);
}
for(index = 0; index < pProfile->SSIDs.numOfSSIDs; index++)
{
if ((pProfile->SSIDs.SSIDList[index].SSID.length == pConnectProfile->SSID.length) &&
vos_mem_compare(pProfile->SSIDs.SSIDList[index].SSID.ssId,
pConnectProfile->SSID.ssId,
pConnectProfile->SSID.length))
{
pConnectProfile->handoffPermitted = pProfile->SSIDs.SSIDList[index].handoffPermitted;
break;
}
pConnectProfile->handoffPermitted = FALSE;
}
return (status);
}
static void csrRoamJoinRspProcessor( tpAniSirGlobal pMac, tSirSmeJoinRsp *pSmeJoinRsp )
{
tListElem *pEntry = NULL;
tSmeCmd *pCommand = NULL;
tCsrRoamSession *pSession = NULL;
//The head of the active list is the request we sent
pEntry = csrLLPeekHead(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK);
if(pEntry)
{
pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
}
pSession = CSR_GET_SESSION( pMac, pSmeJoinRsp->sessionId );
if ( eSIR_SME_SUCCESS == pSmeJoinRsp->statusCode )
{
if(pCommand && eCsrSmeIssuedAssocToSimilarAP == pCommand->u.roamCmd.roamReason)
{
#ifndef WLAN_MDM_CODE_REDUCTION_OPT
sme_QosCsrEventInd(pMac, pSmeJoinRsp->sessionId, SME_QOS_CSR_HANDOFF_COMPLETE, NULL);
#endif
}
csrRoamComplete( pMac, eCsrJoinSuccess, (void *)pSmeJoinRsp );
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "),
pSmeJoinRsp->sessionId);
return;
}
pSession->abortConnection = FALSE;
}
else
{
tANI_U32 roamId = 0;
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "),
pSmeJoinRsp->sessionId);
return;
}
if (pSession->abortConnection)
{
smsLog(pMac, LOG1, FL("Disconnection in progess abort Join request"));
if (pSession->bRefAssocStartCnt)
pSession->bRefAssocStartCnt--;
csrRoamCallCallback(pMac, pSession->sessionId,
NULL, roamId,
eCSR_ROAM_ASSOCIATION_COMPLETION,
eCSR_ROAM_RESULT_NOT_ASSOCIATED);
csrRoamComplete( pMac, eCsrNothingToJoin, NULL );
pSession->abortConnection = FALSE;
return;
}
//The head of the active list is the request we sent
//Try to get back the same profile and roam again
if(pCommand)
{
roamId = pCommand->u.roamCmd.roamId;
}
pSession->joinFailStatusCode.statusCode = pSmeJoinRsp->statusCode;
pSession->joinFailStatusCode.reasonCode = pSmeJoinRsp->protStatusCode;
smsLog( pMac, LOGW, "SmeJoinReq failed with statusCode= 0x%08X [%d]", pSmeJoinRsp->statusCode, pSmeJoinRsp->statusCode );
#if defined WLAN_FEATURE_NEIGHBOR_ROAMING
/* If Join fails while Handoff is in progress, indicate disassociated event to supplicant to reconnect */
if (csrRoamIsHandoffInProgress(pMac))
{
csrRoamCallCallback(pMac, pSmeJoinRsp->sessionId, NULL, roamId, eCSR_ROAM_DISASSOCIATED, eCSR_ROAM_RESULT_FORCED);
/* Should indicate neighbor roam algorithm about the connect failure here */
csrNeighborRoamIndicateConnect(pMac, pSmeJoinRsp->sessionId, VOS_STATUS_E_FAILURE);
}
#endif
if (pCommand)
{
if(CSR_IS_WDS_STA( &pCommand->u.roamCmd.roamProfile ))
{
pCommand->u.roamCmd.fStopWds = eANI_BOOLEAN_TRUE;
pSession->connectedProfile.BSSType = eCSR_BSS_TYPE_WDS_STA;
csrRoamReissueRoamCommand(pMac);
}
else if( CSR_IS_WDS( &pCommand->u.roamCmd.roamProfile ) )
{
csrRoamComplete( pMac, eCsrNothingToJoin, NULL );
}
else
{
csrRoam(pMac, pCommand);
}
}
else
{
csrRoamComplete( pMac, eCsrNothingToJoin, NULL );
}
} /*else: ( eSIR_SME_SUCCESS == pSmeJoinRsp->statusCode ) */
}
eHalStatus csrRoamIssueJoin( tpAniSirGlobal pMac, tANI_U32 sessionId, tSirBssDescription *pSirBssDesc,
tDot11fBeaconIEs *pIes,
tCsrRoamProfile *pProfile, tANI_U32 roamId )
{
eHalStatus status;
smsLog( pMac, LOG1, "Attempting to Join Bssid= "MAC_ADDRESS_STR,
MAC_ADDR_ARRAY(pSirBssDesc->bssId));
// Set the roaming substate to 'join attempt'...
csrRoamSubstateChange( pMac, eCSR_ROAM_SUBSTATE_JOIN_REQ, sessionId);
// attempt to Join this BSS...
status = csrSendJoinReqMsg( pMac, sessionId, pSirBssDesc, pProfile, pIes, eWNI_SME_JOIN_REQ );
return (status);
}
static eHalStatus csrRoamIssueReassociate( tpAniSirGlobal pMac, tANI_U32 sessionId, tSirBssDescription *pSirBssDesc,
tDot11fBeaconIEs *pIes, tCsrRoamProfile *pProfile)
{
csrRoamStateChange( pMac, eCSR_ROAMING_STATE_JOINING, sessionId);
// Set the roaming substate to 'join attempt'...
csrRoamSubstateChange( pMac, eCSR_ROAM_SUBSTATE_REASSOC_REQ, sessionId );
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
FL(" calling csrSendJoinReqMsg (eWNI_SME_REASSOC_REQ)"));
if (pMac->roam.configParam.roamDelayStatsEnabled)
{
vos_record_roam_event(e_SME_ISSUE_REASSOC_REQ, NULL, pProfile->negotiatedAuthType);
vos_record_roam_event(e_CACHE_ROAM_PEER_MAC, (void *)pSirBssDesc->bssId, 6);
}
// attempt to Join this BSS...
return csrSendJoinReqMsg( pMac, sessionId, pSirBssDesc, pProfile, pIes, eWNI_SME_REASSOC_REQ);
}
void csrRoamReissueRoamCommand(tpAniSirGlobal pMac)
{
tListElem *pEntry;
tSmeCmd *pCommand;
tCsrRoamInfo roamInfo;
tANI_U32 sessionId;
tCsrRoamSession *pSession = NULL;
pEntry = csrLLPeekHead(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK);
if(pEntry)
{
pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
if ( eSmeCommandRoam == pCommand->command )
{
sessionId = pCommand->sessionId;
pSession = CSR_GET_SESSION( pMac, sessionId );
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return;
}
/* While switching between two AP, csr will reissue roam command again
to the nextbss if it was interrupted by the dissconnect req for the
previous bss.During this csr is incrementing bRefAssocStartCnt twice.
so reset the bRefAssocStartCnt.
*/
if(pSession->bRefAssocStartCnt > 0)
{
pSession->bRefAssocStartCnt--;
}
if( pCommand->u.roamCmd.fStopWds )
{
vos_mem_set(&roamInfo, sizeof(tCsrRoamInfo), 0);
roamInfo.pBssDesc = pCommand->u.roamCmd.pLastRoamBss;
roamInfo.statusCode = pSession->joinFailStatusCode.statusCode;
roamInfo.reasonCode = pSession->joinFailStatusCode.reasonCode;
if (CSR_IS_WDS(&pSession->connectedProfile)){
pSession->connectState = eCSR_ASSOC_STATE_TYPE_WDS_DISCONNECTED;
csrRoamCallCallback(pMac, sessionId, &roamInfo, pCommand->u.roamCmd.roamId,
eCSR_ROAM_WDS_IND,
eCSR_ROAM_RESULT_WDS_DISASSOCIATED);
}else if (CSR_IS_INFRA_AP(&pSession->connectedProfile)){
pSession->connectState = eCSR_ASSOC_STATE_TYPE_INFRA_DISCONNECTED;
csrRoamCallCallback(pMac, sessionId, &roamInfo, pCommand->u.roamCmd.roamId,
eCSR_ROAM_INFRA_IND,
eCSR_ROAM_RESULT_INFRA_DISASSOCIATED);
}
if( !HAL_STATUS_SUCCESS( csrRoamIssueStopBss( pMac, sessionId, eCSR_ROAM_SUBSTATE_STOP_BSS_REQ ) ) )
{
smsLog(pMac, LOGE, " Failed to reissue stop_bss command for WDS after disassociated");
csrRoamComplete( pMac, eCsrNothingToJoin, NULL );
}
}
else if(eCsrStopRoaming == csrRoamJoinNextBss(pMac, pCommand, eANI_BOOLEAN_TRUE))
{
smsLog(pMac, LOGW, " Failed to reissue join command after disassociated");
csrRoamComplete( pMac, eCsrNothingToJoin, NULL );
}
}
else
{
smsLog(pMac, LOGW, " Command is not roaming after disassociated");
}
}
else
{
smsLog(pMac, LOGE, " Disassoc rsp cannot continue because no command is available");
}
}
tANI_BOOLEAN csrIsRoamCommandWaitingForSession(tpAniSirGlobal pMac, tANI_U32 sessionId)
{
tANI_BOOLEAN fRet = eANI_BOOLEAN_FALSE;
tListElem *pEntry;
tSmeCmd *pCommand = NULL;
//alwasy lock active list before locking pending list
csrLLLock( &pMac->sme.smeCmdActiveList );
pEntry = csrLLPeekHead(&pMac->sme.smeCmdActiveList, LL_ACCESS_NOLOCK);
if(pEntry)
{
pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
if( ( eSmeCommandRoam == pCommand->command ) && ( sessionId == pCommand->sessionId ) )
{
fRet = eANI_BOOLEAN_TRUE;
}
}
if(eANI_BOOLEAN_FALSE == fRet)
{
csrLLLock(&pMac->sme.smeCmdPendingList);
pEntry = csrLLPeekHead(&pMac->sme.smeCmdPendingList, LL_ACCESS_NOLOCK);
while(pEntry)
{
pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
if( ( eSmeCommandRoam == pCommand->command ) && ( sessionId == pCommand->sessionId ) )
{
fRet = eANI_BOOLEAN_TRUE;
break;
}
pEntry = csrLLNext(&pMac->sme.smeCmdPendingList, pEntry, LL_ACCESS_NOLOCK);
}
csrLLUnlock(&pMac->sme.smeCmdPendingList);
}
if (eANI_BOOLEAN_FALSE == fRet)
{
csrLLLock(&pMac->roam.roamCmdPendingList);
pEntry = csrLLPeekHead(&pMac->roam.roamCmdPendingList, LL_ACCESS_NOLOCK);
while (pEntry)
{
pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
if (( eSmeCommandRoam == pCommand->command ) && ( sessionId == pCommand->sessionId ) )
{
fRet = eANI_BOOLEAN_TRUE;
break;
}
pEntry = csrLLNext(&pMac->roam.roamCmdPendingList, pEntry, LL_ACCESS_NOLOCK);
}
csrLLUnlock(&pMac->roam.roamCmdPendingList);
}
csrLLUnlock( &pMac->sme.smeCmdActiveList );
return (fRet);
}
tANI_BOOLEAN csrIsRoamCommandWaiting(tpAniSirGlobal pMac)
{
tANI_BOOLEAN fRet = eANI_BOOLEAN_FALSE;
tANI_U32 i;
for( i = 0; i < CSR_ROAM_SESSION_MAX; i++ )
{
if( CSR_IS_SESSION_VALID( pMac, i ) && ( fRet = csrIsRoamCommandWaitingForSession( pMac, i ) ) )
{
break;
}
}
return ( fRet );
}
tANI_BOOLEAN csrIsCommandWaiting(tpAniSirGlobal pMac)
{
tANI_BOOLEAN fRet = eANI_BOOLEAN_FALSE;
//alwasy lock active list before locking pending list
csrLLLock( &pMac->sme.smeCmdActiveList );
fRet = csrLLIsListEmpty(&pMac->sme.smeCmdActiveList, LL_ACCESS_NOLOCK);
if(eANI_BOOLEAN_FALSE == fRet)
{
fRet = csrLLIsListEmpty(&pMac->sme.smeCmdPendingList, LL_ACCESS_LOCK);
}
csrLLUnlock( &pMac->sme.smeCmdActiveList );
return (fRet);
}
tANI_BOOLEAN csrIsScanForRoamCommandActive( tpAniSirGlobal pMac )
{
tANI_BOOLEAN fRet = eANI_BOOLEAN_FALSE;
tListElem *pEntry;
tCsrCmd *pCommand;
//alwasy lock active list before locking pending list
csrLLLock( &pMac->sme.smeCmdActiveList );
pEntry = csrLLPeekHead(&pMac->sme.smeCmdActiveList, LL_ACCESS_NOLOCK);
if( pEntry )
{
pCommand = GET_BASE_ADDR(pEntry, tCsrCmd, Link);
if( ( eCsrRoamCommandScan == pCommand->command ) &&
( ( eCsrScanForSsid == pCommand->u.scanCmd.reason ) ||
( eCsrScanForCapsChange == pCommand->u.scanCmd.reason ) ||
( eCsrScanP2PFindPeer == pCommand->u.scanCmd.reason ) ) )
{
fRet = eANI_BOOLEAN_TRUE;
}
}
csrLLUnlock( &pMac->sme.smeCmdActiveList );
return (fRet);
}
eHalStatus csrRoamIssueReassociateCmd( tpAniSirGlobal pMac, tANI_U32 sessionId )
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tSmeCmd *pCommand = NULL;
tANI_BOOLEAN fHighPriority = eANI_BOOLEAN_TRUE;
tANI_BOOLEAN fRemoveCmd = FALSE;
tListElem *pEntry;
// Delete the old assoc command. All is setup for reassoc to be serialized
pEntry = csrLLPeekHead( &pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK );
if ( pEntry )
{
pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link );
if ( !pCommand )
{
smsLog( pMac, LOGE, FL(" fail to get command buffer") );
return eHAL_STATUS_RESOURCES;
}
if ( eSmeCommandRoam == pCommand->command )
{
if (pCommand->u.roamCmd.roamReason == eCsrSmeIssuedAssocToSimilarAP)
{
fRemoveCmd = csrLLRemoveEntry( &pMac->sme.smeCmdActiveList, pEntry, LL_ACCESS_LOCK );
}
else
{
smsLog( pMac, LOGE, FL(" Unexpected active roam command present ") );
}
if (fRemoveCmd == FALSE)
{
// Implies we did not get the serialized assoc command we
// were expecting
pCommand = NULL;
}
}
}
if(NULL == pCommand)
{
smsLog( pMac, LOGE, FL(" fail to get command buffer as expected based on previous connect roam command") );
return eHAL_STATUS_RESOURCES;
}
do
{
//Change the substate in case it is wait-for-key
if( CSR_IS_WAIT_FOR_KEY( pMac, sessionId ) )
{
csrRoamStopWaitForKeyTimer( pMac );
csrRoamSubstateChange( pMac, eCSR_ROAM_SUBSTATE_NONE, sessionId );
}
pCommand->command = eSmeCommandRoam;
pCommand->sessionId = (tANI_U8)sessionId;
pCommand->u.roamCmd.roamReason = eCsrSmeIssuedFTReassoc;
status = csrQueueSmeCommand(pMac, pCommand, fHighPriority);
if( !HAL_STATUS_SUCCESS( status ) )
{
smsLog( pMac, LOGE, FL(" fail to send message status = %d"), status );
csrReleaseCommandRoam( pMac, pCommand );
}
} while( 0 );
return( status );
}
static void csrRoamingStateConfigCnfProcessor( tpAniSirGlobal pMac, tANI_U32 result )
{
tListElem *pEntry = csrLLPeekHead(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK);
tCsrScanResult *pScanResult = NULL;
tSirBssDescription *pBssDesc = NULL;
tSmeCmd *pCommand = NULL;
tANI_U32 sessionId;
tCsrRoamSession *pSession = NULL;
if(NULL == pEntry)
{
smsLog(pMac, LOGE, " CFG_CNF with active list empty");
return;
}
pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
sessionId = pCommand->sessionId;
pSession = CSR_GET_SESSION( pMac, sessionId );
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return;
}
smsLog(pMac, LOG1, FL("CFG return value is %d "
" current state is : %d substate is : %d "),
result, pMac->roam.curState[sessionId],
pMac->roam.curSubState[sessionId]);
if(CSR_IS_ROAMING(pSession) && pSession->fCancelRoaming)
{
//the roaming is cancelled. Simply complete the command
smsLog(pMac, LOGW, FL(" Roam command cancelled"));
csrRoamComplete(pMac, eCsrNothingToJoin, NULL);
}
/* If the roaming has stopped, not to continue the roaming command*/
else if ( !CSR_IS_ROAMING(pSession) && CSR_IS_ROAMING_COMMAND(pCommand) )
{
//No need to complete roaming here as it already completes
smsLog(pMac, LOGW, FL(" Roam command (reason %d) aborted due to roaming completed\n"),
pCommand->u.roamCmd.roamReason);
csrSetAbortRoamingCommand( pMac, pCommand );
csrRoamComplete(pMac, eCsrNothingToJoin, NULL);
}
else
{
if ( CCM_IS_RESULT_SUCCESS(result) )
{
smsLog(pMac, LOG1, "Cfg sequence complete");
// Successfully set the configuration parameters for the new Bss. Attempt to
// join the roaming Bss.
if(pCommand->u.roamCmd.pRoamBssEntry)
{
pScanResult = GET_BASE_ADDR(pCommand->u.roamCmd.pRoamBssEntry, tCsrScanResult, Link);
if (!pScanResult)
{
smsLog(pMac, LOGE,
FL("Failed to get base address for pScanResult"));
return;
}
pBssDesc = &pScanResult->Result.BssDescriptor;
}
if ( csrIsBssTypeIBSS( pCommand->u.roamCmd.roamProfile.BSSType ) ||
CSR_IS_WDS( &pCommand->u.roamCmd.roamProfile )
|| CSR_IS_INFRA_AP(&pCommand->u.roamCmd.roamProfile)
)
{
if(!HAL_STATUS_SUCCESS(csrRoamIssueStartBss( pMac, sessionId,
&pSession->bssParams, &pCommand->u.roamCmd.roamProfile,
pBssDesc, pCommand->u.roamCmd.roamId )))
{
smsLog(pMac, LOGE, " CSR start BSS failed");
//We need to complete the command
csrRoamComplete(pMac, eCsrStartBssFailure, NULL);
}
}
else
{
if (!pCommand->u.roamCmd.pRoamBssEntry)
{
smsLog(pMac, LOGE, " pRoamBssEntry is NULL");
//We need to complete the command
csrRoamComplete(pMac, eCsrJoinFailure, NULL);
return;
}
// If we are roaming TO an Infrastructure BSS...
VOS_ASSERT(pScanResult != NULL);
if( !pScanResult->Result.pvIes )
{
smsLog(pMac, LOGE, FL(" pvIes is NULL"));
return;
}
if ( csrIsInfraBssDesc( pBssDesc ) )
{
tDot11fBeaconIEs *pIesLocal = (tDot11fBeaconIEs *)pScanResult->Result.pvIes;
smsLog(pMac, LOG1, " Roaming in a Infra BSS");
if(pIesLocal || (HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, pBssDesc, &pIesLocal))) )
{
// ..and currently in an Infrastructure connection....
if( csrIsConnStateConnectedInfra( pMac, sessionId ) )
{
smsLog(pMac, LOG1, " Connected to infra BSS");
// ...and the SSIDs are equal, then we Reassoc.
if ( csrIsSsidEqual( pMac, pSession->pConnectBssDesc, pBssDesc,
pIesLocal ) )
// ..and currently in an infrastructure connection
{
// then issue a Reassoc.
pCommand->u.roamCmd.fReassoc = eANI_BOOLEAN_TRUE;
csrRoamIssueReassociate( pMac, sessionId, pBssDesc, pIesLocal,
&pCommand->u.roamCmd.roamProfile );
}
else
{
// otherwise, we have to issue a new Join request to LIM because we disassociated from the
// previously associated AP.
if(!HAL_STATUS_SUCCESS(csrRoamIssueJoin( pMac, sessionId, pBssDesc,
pIesLocal,
&pCommand->u.roamCmd.roamProfile, pCommand->u.roamCmd.roamId )))
{
//try something else
csrRoam( pMac, pCommand );
}
}
}
else
{
eHalStatus status = eHAL_STATUS_SUCCESS;
/* We need to come with other way to figure out that this is because of HO in BMP
The below API will be only available for Android as it uses a different HO algorithm */
/* Reassoc request will be used only for ESE and 11r handoff whereas other legacy roaming should
* use join request */
#ifdef WLAN_FEATURE_VOWIFI_11R
if (csrRoamIsHandoffInProgress(pMac) &&
csrRoamIs11rAssoc(pMac))
{
smsLog(pMac, LOG1, " HandoffInProgress with 11r enabled");
status = csrRoamIssueReassociate(pMac, sessionId, pBssDesc,
(tDot11fBeaconIEs *)( pScanResult->Result.pvIes ), &pCommand->u.roamCmd.roamProfile);
}
else
#endif
#ifdef FEATURE_WLAN_ESE
if (csrRoamIsHandoffInProgress(pMac) &&
csrRoamIsESEAssoc(pMac))
{
smsLog(pMac, LOG1, " HandoffInProgress with ESE enabled");
// Now serialize the reassoc command.
status = csrRoamIssueReassociateCmd(pMac, sessionId);
}
else
#endif
#ifdef FEATURE_WLAN_LFR
if (csrRoamIsHandoffInProgress(pMac) &&
csrRoamIsFastRoamEnabled(pMac, sessionId))
{
smsLog(pMac, LOG1, " HandoffInProgress with LFR enabled");
// Now serialize the reassoc command.
status = csrRoamIssueReassociateCmd(pMac, sessionId);
}
else
#endif
// else we are not connected and attempting to Join. Issue the
// Join request.
{
smsLog(pMac, LOG1, " Not connected, Attempting to Join");
status = csrRoamIssueJoin( pMac, sessionId, pBssDesc,
(tDot11fBeaconIEs *)( pScanResult->Result.pvIes ),
&pCommand->u.roamCmd.roamProfile, pCommand->u.roamCmd.roamId );
}
if(!HAL_STATUS_SUCCESS(status))
{
//try something else
csrRoam( pMac, pCommand );
}
}
if( !pScanResult->Result.pvIes )
{
//Locally allocated
vos_mem_free(pIesLocal);
}
}
}//if ( csrIsInfraBssDesc( pBssDesc ) )
else
{
smsLog(pMac, LOGW, FL(" found BSSType mismatching the one in BSS description"));
}
}//else
}//if ( WNI_CFG_SUCCESS == result )
else
{
// In the event the configuration failed, for infra let the roam processor
//attempt to join something else...
if( pCommand->u.roamCmd.pRoamBssEntry && CSR_IS_INFRASTRUCTURE( &pCommand->u.roamCmd.roamProfile ) )
{
csrRoam(pMac, pCommand);
}
else
{
//We need to complete the command
if ( csrIsBssTypeIBSS( pCommand->u.roamCmd.roamProfile.BSSType ) )
{
csrRoamComplete(pMac, eCsrStartBssFailure, NULL);
}
else
{
csrRoamComplete( pMac, eCsrNothingToJoin, NULL );
}
}
}
}//we have active entry
}
static void csrRoamRoamingStateAuthRspProcessor( tpAniSirGlobal pMac, tSirSmeAuthRsp *pSmeAuthRsp )
{
if ( eSIR_SME_SUCCESS == pSmeAuthRsp->statusCode )
{
smsLog( pMac, LOGW, "CSR SmeAuthReq Successful" );
// Successfully authenticated with a new Bss. Attempt to stop the current Bss and
// join the new one...
/***pBssDesc = profGetRoamingBssDesc( pAdapter, &pHddProfile );
roamStopNetwork( pAdapter, &pBssDesc->SirBssDescription );***/
}
else {
smsLog( pMac, LOGW, "CSR SmeAuthReq failed with statusCode= 0x%08X [%d]", pSmeAuthRsp->statusCode, pSmeAuthRsp->statusCode );
/***profHandleLostLinkAfterReset(pAdapter);
// In the event the authenticate fails, let the roam processor attempt to join something else...
roamRoam( pAdapter );***/
}
}
static void csrRoamRoamingStateReassocRspProcessor( tpAniSirGlobal pMac, tpSirSmeJoinRsp pSmeJoinRsp )
{
eCsrRoamCompleteResult result;
tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo;
tCsrRoamInfo roamInfo;
tANI_U32 roamId = 0;
tANI_U32 current_timestamp, max_time = -1;
tANI_U32 candidateApCnt, oldestIndex = 0;
tANI_U8 nilMac[6] = {0};
if (eSIR_SME_SUCCESS == pSmeJoinRsp->statusCode)
{
smsLog( pMac, LOGW, "CSR SmeReassocReq Successful" );
result = eCsrReassocSuccess;
/* Defeaturize this part later if needed */
#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
/* Since the neighbor roam algorithm uses reassoc req for handoff instead of join,
* we need the response contents while processing the result in csrRoamProcessResults() */
if (csrRoamIsHandoffInProgress(pMac))
{
/* Need to dig more on indicating events to SME QoS module */
sme_QosCsrEventInd(pMac, pSmeJoinRsp->sessionId, SME_QOS_CSR_HANDOFF_COMPLETE, NULL);
csrRoamComplete( pMac, result, pSmeJoinRsp);
#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
/* Add previous BSSID to blacklist ; this will be in blacklised for
* some period and score of this AP will be reduced if black listed
* to avoid ping pong */
if (pMac->PERroamCandidatesCnt)
{
current_timestamp = jiffies_to_msecs(jiffies);
for (candidateApCnt = 0; candidateApCnt <
SIR_PER_ROAM_MAX_CANDIDATE_CNT; candidateApCnt++)
{
/* Find one blank entry */
if (sirCompareMacAddr(nilMac,
pMac->previousRoamApInfo[candidateApCnt].bssAddr))
{
vos_mem_copy(pMac->previousRoamApInfo[candidateApCnt].
bssAddr,
pNeighborRoamInfo->prevConnProfile.bssid,
sizeof(tSirMacAddr));
pMac->previousRoamApInfo[candidateApCnt].timeStamp =
current_timestamp;
smsLog(pMac, LOG1, FL("added bssid=" MAC_ADDRESS_STR " at index %d"),
MAC_ADDR_ARRAY(
pNeighborRoamInfo->prevConnProfile.bssid),
candidateApCnt);
break;
}
/* if already in the list */
if (sirCompareMacAddr(pMac->previousRoamApInfo
[candidateApCnt].bssAddr,
pNeighborRoamInfo->prevConnProfile.bssid) &&
((current_timestamp -
pMac->previousRoamApInfo[candidateApCnt].timeStamp) >
pMac->PERroamTimeout))
{
vos_mem_copy(pMac->previousRoamApInfo[candidateApCnt].
bssAddr,
pNeighborRoamInfo->prevConnProfile.bssid,
sizeof(tSirMacAddr));
pMac->previousRoamApInfo[candidateApCnt].timeStamp =
current_timestamp;
break;
} else
{
/* find oldest BSSID entry in the blacklist */
if (max_time <
pMac->previousRoamApInfo[candidateApCnt].timeStamp)
{
max_time =
pMac->previousRoamApInfo[candidateApCnt].timeStamp;
oldestIndex = candidateApCnt;
}
}
}
if (candidateApCnt == SIR_PER_ROAM_MAX_CANDIDATE_CNT)
{
smsLog(pMac, LOGW,
"%s: Clearing out oldest roam results bssid="
MAC_ADDRESS_STR,
__func__,
MAC_ADDR_ARRAY(pMac->previousRoamApInfo[oldestIndex].bssAddr));
pMac->previousRoamApInfo[oldestIndex].timeStamp = current_timestamp;
vos_mem_copy(pMac->previousRoamApInfo[oldestIndex].bssAddr,
pNeighborRoamInfo->prevConnProfile.bssid,
sizeof(tSirMacAddr));
}
}
#endif
}
else
#endif
{
csrRoamComplete( pMac, result, NULL );
}
}
/* Should we handle this similar to handling the join failure? Is it ok
* to call csrRoamComplete() with state as CsrJoinFailure */
else
{
smsLog( pMac, LOGW, "CSR SmeReassocReq failed with statusCode= 0x%08X [%d]", pSmeJoinRsp->statusCode, pSmeJoinRsp->statusCode );
result = eCsrReassocFailure;
vos_fatal_event_logs_req(WLAN_LOG_TYPE_FATAL,
WLAN_LOG_INDICATOR_HOST_DRIVER,
WLAN_LOG_REASON_ROAM_FAIL,
FALSE, TRUE);
#ifdef WLAN_FEATURE_VOWIFI_11R
if ((eSIR_SME_FT_REASSOC_TIMEOUT_FAILURE == pSmeJoinRsp->statusCode) ||
(eSIR_SME_FT_REASSOC_FAILURE == pSmeJoinRsp->statusCode) ||
(eSIR_SME_JOIN_DEAUTH_FROM_AP_DURING_ADD_STA == pSmeJoinRsp->statusCode))
{
// Inform HDD to turn off FT flag in HDD
if (pNeighborRoamInfo)
{
vos_mem_zero(&roamInfo, sizeof(tCsrRoamInfo));
csrRoamCallCallback(pMac, pNeighborRoamInfo->csrSessionId,
&roamInfo, roamId, eCSR_ROAM_FT_REASSOC_FAILED, eSIR_SME_SUCCESS);
/*
* Since the above callback sends a disconnect
* to HDD, we should clean-up our state
* machine as well to be in sync with the upper
* layers. There is no need to send a disassoc
* since: 1) we will never reassoc to the current
* AP in LFR, and 2) there is no need to issue a
* disassoc to the AP with which we were trying
* to reassoc.
*/
csrRoamComplete( pMac, eCsrJoinFailure, NULL );
return;
}
}
#endif
// In the event that the Reassociation fails, then we need to Disassociate the current association and keep
// roaming. Note that we will attempt to Join the AP instead of a Reassoc since we may have attempted a
// 'Reassoc to self', which AP's that don't support Reassoc will force a Disassoc.
//The disassoc rsp message will remove the command from active list
if(!HAL_STATUS_SUCCESS(csrRoamIssueDisassociate( pMac, pSmeJoinRsp->sessionId,
eCSR_ROAM_SUBSTATE_DISASSOC_REASSOC_FAILURE, FALSE )))
{
csrRoamComplete( pMac, eCsrJoinFailure, NULL );
}
}
}
static void csrRoamRoamingStateStopBssRspProcessor(tpAniSirGlobal pMac, tSirSmeRsp *pSmeRsp)
{
#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
{
vos_log_ibss_pkt_type *pIbssLog;
WLAN_VOS_DIAG_LOG_ALLOC(pIbssLog, vos_log_ibss_pkt_type, LOG_WLAN_IBSS_C);
if(pIbssLog)
{
pIbssLog->eventId = WLAN_IBSS_EVENT_STOP_RSP;
if(eSIR_SME_SUCCESS != pSmeRsp->statusCode)
{
pIbssLog->status = WLAN_IBSS_STATUS_FAILURE;
}
WLAN_VOS_DIAG_LOG_REPORT(pIbssLog);
}
}
#endif //FEATURE_WLAN_DIAG_SUPPORT_CSR
pMac->roam.roamSession[pSmeRsp->sessionId].connectState = eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED;
if(CSR_IS_ROAM_SUBSTATE_STOP_BSS_REQ( pMac, pSmeRsp->sessionId))
{
csrRoamComplete( pMac, eCsrNothingToJoin, NULL );
}
else if(CSR_IS_ROAM_SUBSTATE_DISCONNECT_CONTINUE( pMac, pSmeRsp->sessionId))
{
csrRoamReissueRoamCommand(pMac);
}
}
void csrRoamRoamingStateDisassocRspProcessor( tpAniSirGlobal pMac, tSirSmeDisassocRsp *pSmeRsp )
{
tSirResultCodes statusCode;
#if defined WLAN_FEATURE_NEIGHBOR_ROAMING
tScanResultHandle hBSSList;
tANI_BOOLEAN fCallCallback, fRemoveCmd;
eHalStatus status;
tCsrRoamInfo roamInfo;
tCsrScanResultFilter *pScanFilter = NULL;
tANI_U32 roamId = 0;
tCsrRoamProfile *pCurRoamProfile = NULL;
tListElem *pEntry = NULL;
tSmeCmd *pCommand = NULL;
#endif
tANI_U32 sessionId;
tCsrRoamSession *pSession = NULL;
tSirSmeDisassocRsp SmeDisassocRsp;
csrSerDesUnpackDiassocRsp((tANI_U8 *)pSmeRsp, &SmeDisassocRsp);
sessionId = SmeDisassocRsp.sessionId;
statusCode = SmeDisassocRsp.statusCode;
smsLog( pMac, LOG2, "csrRoamRoamingStateDisassocRspProcessor sessionId %d", sessionId);
if ( csrIsConnStateInfra( pMac, sessionId ) )
{
pMac->roam.roamSession[sessionId].connectState = eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED;
}
pSession = CSR_GET_SESSION( pMac, sessionId );
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return;
}
if ( CSR_IS_ROAM_SUBSTATE_DISASSOC_NO_JOIN( pMac, sessionId ) )
{
smsLog( pMac, LOG2, "***eCsrNothingToJoin***");
csrRoamComplete( pMac, eCsrNothingToJoin, NULL );
}
else if ( CSR_IS_ROAM_SUBSTATE_DISASSOC_FORCED( pMac, sessionId ) ||
CSR_IS_ROAM_SUBSTATE_DISASSOC_REQ( pMac, sessionId ) )
{
if ( eSIR_SME_SUCCESS == statusCode )
{
smsLog( pMac, LOG2, "CSR SmeDisassocReq force disassociated Successfully" );
//A callback to HDD will be issued from csrRoamComplete so no need to do anything here
}
csrRoamComplete( pMac, eCsrNothingToJoin, NULL );
}
else if ( CSR_IS_ROAM_SUBSTATE_DISASSOC_HO( pMac, sessionId ) )
{
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_HIGH,
"CSR SmeDisassocReq due to HO on session %d", sessionId );
#if defined (WLAN_FEATURE_NEIGHBOR_ROAMING)
/*
* First ensure if the roam profile is in the scan cache.
* If not, post a reassoc failure and disconnect.
*/
pScanFilter = vos_mem_malloc(sizeof(tCsrScanResultFilter));
if ( NULL == pScanFilter )
status = eHAL_STATUS_FAILURE;
else
status = eHAL_STATUS_SUCCESS;
if(HAL_STATUS_SUCCESS(status))
{
vos_mem_set(pScanFilter, sizeof(tCsrScanResultFilter), 0);
status = csrRoamPrepareFilterFromProfile(pMac,
&pMac->roam.neighborRoamInfo.csrNeighborRoamProfile, pScanFilter);
if(!HAL_STATUS_SUCCESS(status))
{
smsLog(pMac, LOGE, "%s: failed to prepare scan filter with status %d",
__func__, status);
goto POST_ROAM_FAILURE;
}
else
{
status = csrScanGetResult(pMac, pScanFilter, &hBSSList);
if (!HAL_STATUS_SUCCESS(status))
{
smsLog( pMac, LOGE,"%s: csrScanGetResult failed with status %d",
__func__, status);
goto POST_ROAM_FAILURE;
}
}
}
else
{
smsLog( pMac, LOGE,"%s: alloc for pScanFilter failed with status %d",
__func__, status);
goto POST_ROAM_FAILURE;
}
/*
* After ensuring that the roam profile is in the scan result list,
* dequeue the command from the active list.
*/
pEntry = csrLLPeekHead( &pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK );
if ( pEntry )
{
pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link );
/* If the head of the queue is Active and it is a ROAM command, remove
* and put this on the Free queue.
*/
if ( eSmeCommandRoam == pCommand->command )
{
/*
* we need to process the result first before removing it from active list
* because state changes still happening insides roamQProcessRoamResults so
* no other roam command should be issued.
*/
fRemoveCmd = csrLLRemoveEntry( &pMac->sme.smeCmdActiveList, pEntry, LL_ACCESS_LOCK );
if(pCommand->u.roamCmd.fReleaseProfile)
{
csrReleaseProfile(pMac, &pCommand->u.roamCmd.roamProfile);
pCommand->u.roamCmd.fReleaseProfile = eANI_BOOLEAN_FALSE;
}
if( fRemoveCmd )
csrReleaseCommandRoam( pMac, pCommand );
else
{
smsLog( pMac, LOGE, "%s: fail to remove cmd reason %d",
__func__, pCommand->u.roamCmd.roamReason );
}
}
else
{
smsLog( pMac, LOGE, "%s: roam command not active", __func__ );
}
}
else
{
smsLog( pMac, LOGE, "%s: NO commands are active", __func__ );
}
/* Notify HDD about handoff and provide the BSSID too */
roamInfo.reasonCode = eCsrRoamReasonBetterAP;
vos_mem_copy(roamInfo.bssid,
pMac->roam.neighborRoamInfo.csrNeighborRoamProfile.BSSIDs.bssid,
sizeof(tSirMacAddr));
csrRoamCallCallback(pMac,sessionId, &roamInfo, 0,
eCSR_ROAM_ROAMING_START, eCSR_ROAM_RESULT_NONE);
/* Copy the connected profile to apply the same for this connection as well */
pCurRoamProfile = vos_mem_malloc(sizeof(tCsrRoamProfile));
if ( pCurRoamProfile != NULL )
{
vos_mem_set(pCurRoamProfile, sizeof(tCsrRoamProfile), 0);
csrRoamCopyProfile(pMac, pCurRoamProfile, pSession->pCurRoamProfile);
//make sure to put it at the head of the cmd queue
status = csrRoamIssueConnect(pMac, sessionId, pCurRoamProfile,
hBSSList, eCsrSmeIssuedAssocToSimilarAP,
roamId, eANI_BOOLEAN_TRUE, eANI_BOOLEAN_FALSE);
if(!HAL_STATUS_SUCCESS(status))
{
smsLog( pMac, LOGE,"%s: csrRoamIssueConnect failed with status %d",
__func__, status);
fCallCallback = eANI_BOOLEAN_TRUE;
}
/* Notify sub-modules like QoS etc. that handoff happening */
sme_QosCsrEventInd(pMac, sessionId, SME_QOS_CSR_HANDOFF_ASSOC_REQ, NULL);
pmcStopTrafficTimer(pMac);
csrReleaseProfile(pMac, pCurRoamProfile);
vos_mem_free(pCurRoamProfile);
csrFreeScanFilter(pMac, pScanFilter);
vos_mem_free(pScanFilter);
return;
}
POST_ROAM_FAILURE:
if (pScanFilter)
{
csrFreeScanFilter(pMac, pScanFilter);
vos_mem_free(pScanFilter);
}
if (pCurRoamProfile)
vos_mem_free(pCurRoamProfile);
/* Inform the upper layers that the reassoc failed */
vos_mem_zero(&roamInfo, sizeof(tCsrRoamInfo));
csrRoamCallCallback(pMac, sessionId,
&roamInfo, 0, eCSR_ROAM_FT_REASSOC_FAILED, eSIR_SME_SUCCESS);
/*
* Issue a disassoc request so that PE/LIM uses this to clean-up the FT session.
* Upon success, we would re-enter this routine after receiving the disassoc
* response and will fall into the reassoc fail sub-state. And, eventually
* call csrRoamComplete which would remove the roam command from SME active
* queue.
*/
if (!HAL_STATUS_SUCCESS(csrRoamIssueDisassociate(pMac, sessionId,
eCSR_ROAM_SUBSTATE_DISASSOC_REASSOC_FAILURE, FALSE)))
{
smsLog( pMac, LOGE,"%s: csrRoamIssueDisassociate failed with status %d",
__func__, status);
csrRoamComplete( pMac, eCsrJoinFailure, NULL );
}
#endif
} //else if ( CSR_IS_ROAM_SUBSTATE_DISASSOC_HO( pMac ) )
else if ( CSR_IS_ROAM_SUBSTATE_REASSOC_FAIL( pMac, sessionId ) )
{
// Disassoc due to Reassoc failure falls into this codepath....
csrRoamComplete( pMac, eCsrJoinFailure, NULL );
}
else
{
if ( eSIR_SME_SUCCESS == statusCode )
{
// Successfully disassociated from the 'old' Bss...
//
// We get Disassociate response in three conditions.
// - First is the case where we are disasociating from an Infra Bss to start an IBSS.
// - Second is the when we are disassociating from an Infra Bss to join an IBSS or a new
// Infrastructure network.
// - Third is where we are doing an Infra to Infra roam between networks with different
// SSIDs. In all cases, we set the new Bss configuration here and attempt to join
smsLog( pMac, LOG2, "CSR SmeDisassocReq disassociated Successfully" );
}
else
{
smsLog( pMac, LOGE, "SmeDisassocReq failed with statusCode= 0x%08X", statusCode );
}
//We are not done yet. Get the data and continue roaming
csrRoamReissueRoamCommand(pMac);
}
}
static void csrRoamRoamingStateDeauthRspProcessor( tpAniSirGlobal pMac, tSirSmeDeauthRsp *pSmeRsp )
{
tSirResultCodes statusCode;
statusCode = csrGetDeAuthRspStatusCode( pSmeRsp );
pMac->roam.deauthRspStatus = statusCode;
if ( CSR_IS_ROAM_SUBSTATE_DEAUTH_REQ( pMac, pSmeRsp->sessionId) )
{
csrRoamComplete( pMac, eCsrNothingToJoin, NULL );
}
else
{
if ( eSIR_SME_SUCCESS == statusCode )
{
// Successfully deauth from the 'old' Bss...
//
smsLog( pMac, LOG2, "CSR SmeDeauthReq disassociated Successfully" );
}
else
{
smsLog( pMac, LOGW, "SmeDeauthReq failed with statusCode= 0x%08X", statusCode );
}
//We are not done yet. Get the data and continue roaming
csrRoamReissueRoamCommand(pMac);
}
}
static void csrRoamRoamingStateStartBssRspProcessor( tpAniSirGlobal pMac, tSirSmeStartBssRsp *pSmeStartBssRsp )
{
eCsrRoamCompleteResult result;
if ( eSIR_SME_SUCCESS == pSmeStartBssRsp->statusCode )
{
smsLog( pMac, LOGW, "SmeStartBssReq Successful" );
result = eCsrStartBssSuccess;
}
else
{
smsLog( pMac, LOGW, "SmeStartBssReq failed with statusCode= 0x%08X", pSmeStartBssRsp->statusCode );
//Let csrRoamComplete decide what to do
result = eCsrStartBssFailure;
}
csrRoamComplete( pMac, result, pSmeStartBssRsp);
}
/*
We need to be careful on whether to cast pMsgBuf (pSmeRsp) to other type of strucutres.
It depends on how the message is constructed. If the message is sent by limSendSmeRsp,
the pMsgBuf is only a generic response and can only be used as pointer to tSirSmeRsp.
For the messages where sender allocates memory for specific structures, then it can be
cast accordingly.
*/
void csrRoamingStateMsgProcessor( tpAniSirGlobal pMac, void *pMsgBuf )
{
tSirSmeRsp *pSmeRsp;
tSmeIbssPeerInd *pIbssPeerInd;
tCsrRoamInfo roamInfo;
// TODO Session Id need to be acquired in this function
tANI_U32 sessionId = 0;
pSmeRsp = (tSirSmeRsp *)pMsgBuf;
smsLog(pMac, LOG2, FL("Message %d[0x%04X] received in substate %s"),
pSmeRsp->messageType, pSmeRsp->messageType,
macTraceGetcsrRoamSubState(
pMac->roam.curSubState[pSmeRsp->sessionId]));
pSmeRsp->messageType = (pSmeRsp->messageType);
pSmeRsp->length = (pSmeRsp->length);
pSmeRsp->statusCode = (pSmeRsp->statusCode);
switch (pSmeRsp->messageType)
{
case eWNI_SME_JOIN_RSP: // in Roaming state, process the Join response message...
if (CSR_IS_ROAM_SUBSTATE_JOIN_REQ(pMac, pSmeRsp->sessionId))
{
//We sent a JOIN_REQ
csrRoamJoinRspProcessor( pMac, (tSirSmeJoinRsp *)pSmeRsp );
}
break;
case eWNI_SME_AUTH_RSP: // or the Authenticate response message...
if (CSR_IS_ROAM_SUBSTATE_AUTH_REQ( pMac, pSmeRsp->sessionId) )
{
//We sent a AUTH_REQ
csrRoamRoamingStateAuthRspProcessor( pMac, (tSirSmeAuthRsp *)pSmeRsp );
}
break;
case eWNI_SME_REASSOC_RSP: // or the Reassociation response message...
if (CSR_IS_ROAM_SUBSTATE_REASSOC_REQ( pMac, pSmeRsp->sessionId) )
{
csrRoamRoamingStateReassocRspProcessor( pMac, (tpSirSmeJoinRsp )pSmeRsp );
}
break;
case eWNI_SME_STOP_BSS_RSP: // or the Stop Bss response message...
{
csrRoamRoamingStateStopBssRspProcessor(pMac, pSmeRsp);
}
break;
case eWNI_SME_DISASSOC_RSP: // or the Disassociate response message...
if ( CSR_IS_ROAM_SUBSTATE_DISASSOC_REQ( pMac, pSmeRsp->sessionId ) ||
CSR_IS_ROAM_SUBSTATE_DISASSOC_NO_JOIN( pMac, pSmeRsp->sessionId ) ||
CSR_IS_ROAM_SUBSTATE_REASSOC_FAIL( pMac, pSmeRsp->sessionId ) ||
CSR_IS_ROAM_SUBSTATE_DISASSOC_FORCED( pMac, pSmeRsp->sessionId ) ||
CSR_IS_ROAM_SUBSTATE_DISCONNECT_CONTINUE( pMac, pSmeRsp->sessionId ) ||
//HO
CSR_IS_ROAM_SUBSTATE_DISASSOC_HO( pMac, pSmeRsp->sessionId ) )
{
smsLog(pMac, LOG1, FL("eWNI_SME_DISASSOC_RSP subState = %s"),
macTraceGetcsrRoamSubState(
pMac->roam.curSubState[pSmeRsp->sessionId]));
csrRoamRoamingStateDisassocRspProcessor( pMac, (tSirSmeDisassocRsp *)pSmeRsp );
if (pMac->roam.configParam.roamDelayStatsEnabled)
{
vos_record_roam_event(e_SME_DISASSOC_COMPLETE, NULL, 0);
}
}
break;
case eWNI_SME_DEAUTH_RSP: // or the Deauthentication response message...
if ( CSR_IS_ROAM_SUBSTATE_DEAUTH_REQ( pMac, pSmeRsp->sessionId ) )
{
csrRoamRoamingStateDeauthRspProcessor( pMac, (tSirSmeDeauthRsp *)pSmeRsp );
}
break;
case eWNI_SME_START_BSS_RSP: // or the Start BSS response message...
if (CSR_IS_ROAM_SUBSTATE_START_BSS_REQ( pMac, pSmeRsp->sessionId ) )
{
csrRoamRoamingStateStartBssRspProcessor( pMac, (tSirSmeStartBssRsp *)pSmeRsp );
}
break;
case WNI_CFG_SET_CNF: // process the Config Confirm messages when we are in 'Config' substate...
if ( CSR_IS_ROAM_SUBSTATE_CONFIG( pMac, pSmeRsp->sessionId ) )
{
csrRoamingStateConfigCnfProcessor( pMac, ((tCsrCfgSetRsp *)pSmeRsp)->respStatus );
}
break;
//In case CSR issues STOP_BSS, we need to tell HDD about peer departed becasue PE is removing them
case eWNI_SME_IBSS_PEER_DEPARTED_IND:
pIbssPeerInd = (tSmeIbssPeerInd*)pSmeRsp;
smsLog(pMac, LOGE, "CSR: Peer departed notification from LIM in joining state");
vos_mem_set(&roamInfo, sizeof(tCsrRoamInfo), 0);
roamInfo.staId = (tANI_U8)pIbssPeerInd->staId;
roamInfo.ucastSig = (tANI_U8)pIbssPeerInd->ucastSig;
roamInfo.bcastSig = (tANI_U8)pIbssPeerInd->bcastSig;
vos_mem_copy(&roamInfo.peerMac, pIbssPeerInd->peerAddr,
sizeof(tCsrBssid));
csrRoamCallCallback(pMac, sessionId, &roamInfo, 0,
eCSR_ROAM_CONNECT_STATUS_UPDATE,
eCSR_ROAM_RESULT_IBSS_PEER_DEPARTED);
break;
case eWNI_SME_LOST_LINK_PARAMS_IND:
{
tpSirSmeLostLinkParamsInd pLostLinkParamsInd = (tpSirSmeLostLinkParamsInd)pSmeRsp;
tCsrRoamInfo roamInfo, *pRoamInfo = NULL;
eCsrRoamResult result = eCSR_ROAM_RESULT_NONE;
vos_mem_set(&roamInfo, sizeof(tCsrRoamInfo), 0);
roamInfo.u.pLostLinkParams = &pLostLinkParamsInd->info;
pRoamInfo = &roamInfo;
csrRoamCallCallback(pMac, pLostLinkParamsInd->sessionId,
pRoamInfo, 0, eCSR_ROAM_LOST_LINK_PARAMS_IND, result);
break;
}
case eWNI_SME_TRIGGER_SAE:
smsLog(pMac, LOG1, FL("Invoke SAE callback"));
csr_sae_callback(pMac, pSmeRsp);
break;
default:
smsLog(pMac, LOG1,
FL("Unexpected message type = %d[0x%X] received in substate %s"),
pSmeRsp->messageType, pSmeRsp->messageType,
macTraceGetcsrRoamSubState(
pMac->roam.curSubState[pSmeRsp->sessionId]));
//If we are connected, check the link status change
if(!csrIsConnStateDisconnected(pMac, sessionId))
{
csrRoamCheckForLinkStatusChange( pMac, pSmeRsp );
}
break;
}
}
void csrRoamJoinedStateMsgProcessor( tpAniSirGlobal pMac, void *pMsgBuf )
{
tSirSmeRsp *pSirMsg = (tSirSmeRsp *)pMsgBuf;
switch (pSirMsg->messageType)
{
case eWNI_SME_GET_STATISTICS_RSP:
smsLog( pMac, LOG2, FL("Stats rsp from PE"));
csrRoamStatsRspProcessor( pMac, pSirMsg );
break;
case eWNI_SME_UPPER_LAYER_ASSOC_CNF:
{
tCsrRoamSession *pSession = NULL;
tSirSmeAssocIndToUpperLayerCnf *pUpperLayerAssocCnf;
tCsrRoamInfo roamInfo;
tCsrRoamInfo *pRoamInfo = NULL;
tANI_U32 sessionId;
eHalStatus status;
smsLog( pMac, LOG1, FL("ASSOCIATION confirmation can be given to upper layer "));
vos_mem_set(&roamInfo, sizeof(tCsrRoamInfo), 0);
pRoamInfo = &roamInfo;
pUpperLayerAssocCnf = (tSirSmeAssocIndToUpperLayerCnf *)pMsgBuf;
status = csrRoamGetSessionIdFromBSSID( pMac, (tCsrBssid *)pUpperLayerAssocCnf->bssId, &sessionId );
pSession = CSR_GET_SESSION(pMac, sessionId);
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return;
}
pRoamInfo->statusCode = eSIR_SME_SUCCESS; //send the status code as Success
pRoamInfo->u.pConnectedProfile = &pSession->connectedProfile;
pRoamInfo->staId = (tANI_U8)pUpperLayerAssocCnf->aid;
pRoamInfo->rsnIELen = (tANI_U8)pUpperLayerAssocCnf->rsnIE.length;
pRoamInfo->prsnIE = pUpperLayerAssocCnf->rsnIE.rsnIEdata;
pRoamInfo->addIELen = (tANI_U8)pUpperLayerAssocCnf->addIE.length;
pRoamInfo->paddIE = pUpperLayerAssocCnf->addIE.addIEdata;
vos_mem_copy(pRoamInfo->peerMac, pUpperLayerAssocCnf->peerMacAddr,
sizeof(tSirMacAddr));
vos_mem_copy(&pRoamInfo->bssid, pUpperLayerAssocCnf->bssId,
sizeof(tCsrBssid));
pRoamInfo->wmmEnabledSta = pUpperLayerAssocCnf->wmmEnabledSta;
#ifdef WLAN_FEATURE_AP_HT40_24G
pRoamInfo->HT40MHzIntoEnabledSta =
pUpperLayerAssocCnf->HT40MHzIntoEnabledSta;
smsLog( pMac, LOGW, FL("HT40MHzIntoEnabledSta: %d \n"),
pRoamInfo->HT40MHzIntoEnabledSta);
#endif
pRoamInfo->maxRateFlags = pUpperLayerAssocCnf->rate_flags;
pRoamInfo->ch_width = pUpperLayerAssocCnf->ch_width;
pRoamInfo->chan_info = pUpperLayerAssocCnf->chan_info;
if (pUpperLayerAssocCnf->HTCaps.present)
pRoamInfo->ht_caps = pUpperLayerAssocCnf->HTCaps;
if (pUpperLayerAssocCnf->VHTCaps.present)
pRoamInfo->vht_caps = pUpperLayerAssocCnf->VHTCaps;
if(CSR_IS_INFRA_AP(pRoamInfo->u.pConnectedProfile) )
{
pMac->roam.roamSession[sessionId].connectState = eCSR_ASSOC_STATE_TYPE_INFRA_CONNECTED;
pRoamInfo->fReassocReq = pUpperLayerAssocCnf->reassocReq;
status = csrRoamCallCallback(pMac, sessionId, pRoamInfo, 0, eCSR_ROAM_INFRA_IND, eCSR_ROAM_RESULT_INFRA_ASSOCIATION_CNF);
}
if(CSR_IS_WDS_AP( pRoamInfo->u.pConnectedProfile))
{
vos_sleep( 100 );
pMac->roam.roamSession[sessionId].connectState = eCSR_ASSOC_STATE_TYPE_WDS_CONNECTED;//Sta
status = csrRoamCallCallback(pMac, sessionId, pRoamInfo, 0, eCSR_ROAM_WDS_IND, eCSR_ROAM_RESULT_WDS_ASSOCIATION_IND);//Sta
}
}
break;
default:
csrRoamCheckForLinkStatusChange( pMac, pSirMsg );
break;
}
}
eHalStatus csrRoamIssueSetContextReq( tpAniSirGlobal pMac, tANI_U32 sessionId, eCsrEncryptionType EncryptType,
tSirBssDescription *pBssDescription,
tSirMacAddr *bssId, tANI_BOOLEAN addKey,
tANI_BOOLEAN fUnicast, tAniKeyDirection aniKeyDirection,
tANI_U8 keyId, tANI_U16 keyLength,
tANI_U8 *pKey, tANI_U8 paeRole )
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tAniEdType edType;
if(eCSR_ENCRYPT_TYPE_UNKNOWN == EncryptType)
{
EncryptType = eCSR_ENCRYPT_TYPE_NONE; //***
}
edType = csrTranslateEncryptTypeToEdType( EncryptType );
// Allow 0 keys to be set for the non-WPA encrypt types... For WPA encrypt types, the num keys must be non-zero
// or LIM will reject the set context (assumes the SET_CONTEXT does not occur until the keys are distrubuted).
if ( CSR_IS_ENC_TYPE_STATIC( EncryptType ) ||
addKey )
{
tCsrRoamSetKey setKey;
setKey.encType = EncryptType;
setKey.keyDirection = aniKeyDirection; //Tx, Rx or Tx-and-Rx
vos_mem_copy(&setKey.peerMac, bssId, sizeof(tCsrBssid));
setKey.paeRole = paeRole; //0 for supplicant
setKey.keyId = keyId; // Kye index
setKey.keyLength = keyLength;
if( keyLength )
{
vos_mem_copy(setKey.Key, pKey, keyLength);
}
status = csrRoamIssueSetKeyCommand( pMac, sessionId, &setKey, 0 );
}
return (status);
}
static eHalStatus csrRoamIssueSetKeyCommand( tpAniSirGlobal pMac, tANI_U32 sessionId,
tCsrRoamSetKey *pSetKey, tANI_U32 roamId )
{
eHalStatus status = eHAL_STATUS_INVALID_PARAMETER;
tSmeCmd *pCommand = NULL;
#ifdef FEATURE_WLAN_ESE
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
#endif /* FEATURE_WLAN_ESE */
do
{
pCommand = csrGetCommandBuffer(pMac);
if(NULL == pCommand)
{
smsLog( pMac, LOGE, FL(" fail to get command buffer") );
status = eHAL_STATUS_RESOURCES;
break;
}
vos_mem_zero(pCommand, sizeof(tSmeCmd));
pCommand->command = eSmeCommandSetKey;
pCommand->sessionId = (tANI_U8)sessionId;
// validate the key length, Adjust if too long...
// for static WEP the keys are not set thru' SetContextReq
if ( ( eCSR_ENCRYPT_TYPE_WEP40 == pSetKey->encType ) ||
( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == pSetKey->encType ) )
{
//KeyLength maybe 0 for static WEP
if( pSetKey->keyLength )
{
if ( pSetKey->keyLength < CSR_WEP40_KEY_LEN )
{
smsLog( pMac, LOGW, "Invalid WEP40 keylength [= %d] in SetContext call", pSetKey->keyLength );
break;
}
pCommand->u.setKeyCmd.keyLength = CSR_WEP40_KEY_LEN;
vos_mem_copy(pCommand->u.setKeyCmd.Key, pSetKey->Key,
CSR_WEP40_KEY_LEN);
}
}
else if ( ( eCSR_ENCRYPT_TYPE_WEP104 == pSetKey->encType ) ||
( eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == pSetKey->encType ) )
{
//KeyLength maybe 0 for static WEP
if( pSetKey->keyLength )
{
if ( pSetKey->keyLength < CSR_WEP104_KEY_LEN )
{
smsLog( pMac, LOGW, "Invalid WEP104 keylength [= %d] in SetContext call", pSetKey->keyLength );
break;
}
pCommand->u.setKeyCmd.keyLength = CSR_WEP104_KEY_LEN;
vos_mem_copy(pCommand->u.setKeyCmd.Key, pSetKey->Key,
CSR_WEP104_KEY_LEN);
}
}
else if ( eCSR_ENCRYPT_TYPE_TKIP == pSetKey->encType )
{
if ( pSetKey->keyLength < CSR_TKIP_KEY_LEN )
{
smsLog( pMac, LOGW, "Invalid TKIP keylength [= %d] in SetContext call", pSetKey->keyLength );
break;
}
pCommand->u.setKeyCmd.keyLength = CSR_TKIP_KEY_LEN;
vos_mem_copy(pCommand->u.setKeyCmd.Key, pSetKey->Key,
CSR_TKIP_KEY_LEN);
}
else if ( eCSR_ENCRYPT_TYPE_AES == pSetKey->encType )
{
if ( pSetKey->keyLength < CSR_AES_KEY_LEN )
{
smsLog( pMac, LOGW, "Invalid AES/CCMP keylength [= %d] in SetContext call", pSetKey->keyLength );
break;
}
pCommand->u.setKeyCmd.keyLength = CSR_AES_KEY_LEN;
vos_mem_copy(pCommand->u.setKeyCmd.Key, pSetKey->Key,
CSR_AES_KEY_LEN);
}
#ifdef FEATURE_WLAN_WAPI
else if ( eCSR_ENCRYPT_TYPE_WPI == pSetKey->encType )
{
if ( pSetKey->keyLength < CSR_WAPI_KEY_LEN )
{
smsLog( pMac, LOGW, "Invalid WAPI keylength [= %d] in SetContext call", pSetKey->keyLength );
break;
}
pCommand->u.setKeyCmd.keyLength = CSR_WAPI_KEY_LEN;
vos_mem_copy(pCommand->u.setKeyCmd.Key, pSetKey->Key,
CSR_WAPI_KEY_LEN);
}
#endif /* FEATURE_WLAN_WAPI */
#ifdef FEATURE_WLAN_ESE
else if ( eCSR_ENCRYPT_TYPE_KRK == pSetKey->encType )
{
if ( pSetKey->keyLength < CSR_KRK_KEY_LEN )
{
smsLog( pMac, LOGW, "Invalid KRK keylength [= %d] in SetContext call", pSetKey->keyLength );
break;
}
vos_mem_copy(pSession->eseCckmInfo.krk, pSetKey->Key,
CSR_KRK_KEY_LEN);
pSession->eseCckmInfo.reassoc_req_num=1;
pSession->eseCckmInfo.krk_plumbed = eANI_BOOLEAN_TRUE;
status = eHAL_STATUS_SUCCESS;
break;
}
#endif /* FEATURE_WLAN_ESE */
#ifdef WLAN_FEATURE_11W
//Check for 11w BIP
else if (eCSR_ENCRYPT_TYPE_AES_CMAC == pSetKey->encType)
{
if (pSetKey->keyLength < CSR_AES_KEY_LEN)
{
smsLog(pMac, LOGW, "Invalid AES/CCMP keylength [= %d] in SetContext call", pSetKey->keyLength);
break;
}
pCommand->u.setKeyCmd.keyLength = CSR_AES_KEY_LEN;
vos_mem_copy(pCommand->u.setKeyCmd.Key, pSetKey->Key, CSR_AES_KEY_LEN);
}
#endif
status = eHAL_STATUS_SUCCESS;
pCommand->u.setKeyCmd.roamId = roamId;
pCommand->u.setKeyCmd.encType = pSetKey->encType;
pCommand->u.setKeyCmd.keyDirection = pSetKey->keyDirection; //Tx, Rx or Tx-and-Rx
vos_mem_copy(&pCommand->u.setKeyCmd.peerMac, &pSetKey->peerMac,
sizeof(tCsrBssid));
pCommand->u.setKeyCmd.paeRole = pSetKey->paeRole; //0 for supplicant
pCommand->u.setKeyCmd.keyId = pSetKey->keyId;
vos_mem_copy(pCommand->u.setKeyCmd.keyRsc, pSetKey->keyRsc, CSR_MAX_RSC_LEN);
//Always put set key to the head of the Q because it is the only thing to get executed in case of WT_KEY state
status = csrQueueSmeCommand(pMac, pCommand, eANI_BOOLEAN_TRUE);
if( !HAL_STATUS_SUCCESS( status ) )
{
smsLog( pMac, LOGE, FL(" fail to send message status = %d"), status );
}
} while (0);
// Free the command if there has been a failure, or it is a
// "local" operation like the set ESE CCKM KRK key.
if ( ( NULL != pCommand ) &&
( (!HAL_STATUS_SUCCESS( status ) )
#ifdef FEATURE_WLAN_ESE
|| ( eCSR_ENCRYPT_TYPE_KRK == pSetKey->encType )
#endif /* FEATURE_WLAN_ESE */
) )
{
csrReleaseCommandSetKey( pMac, pCommand );
}
return( status );
}
eHalStatus csrRoamIssueRemoveKeyCommand( tpAniSirGlobal pMac, tANI_U32 sessionId,
tCsrRoamRemoveKey *pRemoveKey, tANI_U32 roamId )
{
eHalStatus status = eHAL_STATUS_INVALID_PARAMETER;
tSmeCmd *pCommand = NULL;
tANI_BOOLEAN fImediate = eANI_BOOLEAN_TRUE;
do
{
if( !csrIsSetKeyAllowed(pMac, sessionId) )
{
smsLog( pMac, LOGW, FL(" wrong state not allowed to set key") );
status = eHAL_STATUS_CSR_WRONG_STATE;
break;
}
pCommand = csrGetCommandBuffer(pMac);
if(NULL == pCommand)
{
smsLog( pMac, LOGE, FL(" fail to get command buffer") );
status = eHAL_STATUS_RESOURCES;
break;
}
pCommand->command = eSmeCommandRemoveKey;
pCommand->sessionId = (tANI_U8)sessionId;
pCommand->u.removeKeyCmd.roamId = roamId;
pCommand->u.removeKeyCmd.encType = pRemoveKey->encType;
vos_mem_copy(&pCommand->u.removeKeyCmd.peerMac, &pRemoveKey->peerMac,
sizeof(tSirMacAddr));
pCommand->u.removeKeyCmd.keyId = pRemoveKey->keyId;
if( CSR_IS_WAIT_FOR_KEY( pMac, sessionId ) )
{
//in this case, put it to the end of the Q incase there is a set key pending.
fImediate = eANI_BOOLEAN_FALSE;
}
smsLog( pMac, LOGE, FL("keyType=%d, keyId=%d, PeerMac="MAC_ADDRESS_STR),
pRemoveKey->encType, pRemoveKey->keyId,
MAC_ADDR_ARRAY(pCommand->u.removeKeyCmd.peerMac));
status = csrQueueSmeCommand(pMac, pCommand, fImediate);
if( !HAL_STATUS_SUCCESS( status ) )
{
smsLog( pMac, LOGE, FL(" fail to send message status = %d"), status );
break;
}
} while (0);
if( !HAL_STATUS_SUCCESS( status ) && ( NULL != pCommand ) )
{
csrReleaseCommandRemoveKey( pMac, pCommand );
}
return (status );
}
eHalStatus csrRoamProcessSetKeyCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand )
{
eHalStatus status;
tANI_U8 numKeys = ( pCommand->u.setKeyCmd.keyLength ) ? 1 : 0;
tAniEdType edType = csrTranslateEncryptTypeToEdType( pCommand->u.setKeyCmd.encType );
tANI_BOOLEAN fUnicast = ( pCommand->u.setKeyCmd.peerMac[0] == 0xFF ) ? eANI_BOOLEAN_FALSE : eANI_BOOLEAN_TRUE;
tANI_U32 sessionId = pCommand->sessionId;
#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
WLAN_VOS_DIAG_EVENT_DEF(setKeyEvent, vos_event_wlan_security_payload_type);
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return eHAL_STATUS_FAILURE;
}
if(eSIR_ED_NONE != edType)
{
vos_mem_set(&setKeyEvent,
sizeof(vos_event_wlan_security_payload_type), 0);
if( *(( tANI_U8 *)&pCommand->u.setKeyCmd.peerMac) & 0x01 )
{
setKeyEvent.eventId = WLAN_SECURITY_EVENT_SET_BCAST_REQ;
setKeyEvent.encryptionModeMulticast = (v_U8_t)diagEncTypeFromCSRType(pCommand->u.setKeyCmd.encType);
setKeyEvent.encryptionModeUnicast = (v_U8_t)diagEncTypeFromCSRType(pSession->connectedProfile.EncryptionType);
}
else
{
setKeyEvent.eventId = WLAN_SECURITY_EVENT_SET_UNICAST_REQ;
setKeyEvent.encryptionModeUnicast = (v_U8_t)diagEncTypeFromCSRType(pCommand->u.setKeyCmd.encType);
setKeyEvent.encryptionModeMulticast = (v_U8_t)diagEncTypeFromCSRType(pSession->connectedProfile.mcEncryptionType);
}
vos_mem_copy(setKeyEvent.bssid, pSession->connectedProfile.bssid, 6);
if(CSR_IS_ENC_TYPE_STATIC(pCommand->u.setKeyCmd.encType))
{
tANI_U32 defKeyId;
//It has to be static WEP here
if(HAL_STATUS_SUCCESS(ccmCfgGetInt(pMac, WNI_CFG_WEP_DEFAULT_KEYID, &defKeyId)))
{
setKeyEvent.keyId = (v_U8_t)defKeyId;
}
}
else
{
setKeyEvent.keyId = pCommand->u.setKeyCmd.keyId;
}
setKeyEvent.authMode = (v_U8_t)diagAuthTypeFromCSRType(pSession->connectedProfile.AuthType);
WLAN_VOS_DIAG_EVENT_REPORT(&setKeyEvent, EVENT_WLAN_SECURITY);
}
#endif //FEATURE_WLAN_DIAG_SUPPORT_CSR
if( csrIsSetKeyAllowed(pMac, sessionId) )
{
status = csrSendMBSetContextReqMsg( pMac, sessionId,
( tANI_U8 *)&pCommand->u.setKeyCmd.peerMac,
numKeys, edType, fUnicast, pCommand->u.setKeyCmd.keyDirection,
pCommand->u.setKeyCmd.keyId, pCommand->u.setKeyCmd.keyLength,
pCommand->u.setKeyCmd.Key, pCommand->u.setKeyCmd.paeRole,
pCommand->u.setKeyCmd.keyRsc);
}
else
{
smsLog( pMac, LOGW, FL(" cannot process not connected") );
//Set this status so the error handling take care of the case.
status = eHAL_STATUS_CSR_WRONG_STATE;
}
if( !HAL_STATUS_SUCCESS(status) )
{
smsLog( pMac, LOGE, FL(" error status %d"), status );
csrRoamCallCallback( pMac, sessionId, NULL, pCommand->u.setKeyCmd.roamId, eCSR_ROAM_SET_KEY_COMPLETE, eCSR_ROAM_RESULT_FAILURE);
#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
if(eSIR_ED_NONE != edType)
{
if( *(( tANI_U8 *)&pCommand->u.setKeyCmd.peerMac) & 0x01 )
{
setKeyEvent.eventId = WLAN_SECURITY_EVENT_SET_BCAST_RSP;
}
else
{
setKeyEvent.eventId = WLAN_SECURITY_EVENT_SET_UNICAST_RSP;
}
setKeyEvent.status = WLAN_SECURITY_STATUS_FAILURE;
WLAN_VOS_DIAG_EVENT_REPORT(&setKeyEvent, EVENT_WLAN_SECURITY);
}
#endif //FEATURE_WLAN_DIAG_SUPPORT_CSR
}
return ( status );
}
eHalStatus csrRoamProcessRemoveKeyCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand )
{
eHalStatus status;
tpSirSmeRemoveKeyReq pMsg = NULL;
tANI_U16 wMsgLen = sizeof(tSirSmeRemoveKeyReq);
tANI_U8 *p;
tANI_U32 sessionId = pCommand->sessionId;
#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
WLAN_VOS_DIAG_EVENT_DEF(removeKeyEvent, vos_event_wlan_security_payload_type);
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return eHAL_STATUS_FAILURE;
}
vos_mem_set(&removeKeyEvent,
sizeof(vos_event_wlan_security_payload_type),0);
removeKeyEvent.eventId = WLAN_SECURITY_EVENT_REMOVE_KEY_REQ;
removeKeyEvent.encryptionModeMulticast = (v_U8_t)diagEncTypeFromCSRType(pSession->connectedProfile.mcEncryptionType);
removeKeyEvent.encryptionModeUnicast = (v_U8_t)diagEncTypeFromCSRType(pSession->connectedProfile.EncryptionType);
vos_mem_copy(removeKeyEvent.bssid, pSession->connectedProfile.bssid, 6);
removeKeyEvent.keyId = pCommand->u.removeKeyCmd.keyId;
removeKeyEvent.authMode = (v_U8_t)diagAuthTypeFromCSRType(pSession->connectedProfile.AuthType);
WLAN_VOS_DIAG_EVENT_REPORT(&removeKeyEvent, EVENT_WLAN_SECURITY);
#endif //FEATURE_WLAN_DIAG_SUPPORT_CSR
if( csrIsSetKeyAllowed(pMac, sessionId) )
{
pMsg = vos_mem_malloc(wMsgLen);
if ( NULL == pMsg )
status = eHAL_STATUS_FAILURE;
else
status = eHAL_STATUS_SUCCESS;
}
else
{
smsLog( pMac, LOGW, FL(" wrong state not allowed to set key") );
//Set the error status so error handling kicks in below
status = eHAL_STATUS_CSR_WRONG_STATE;
}
if( HAL_STATUS_SUCCESS( status ) )
{
vos_mem_set(pMsg, wMsgLen ,0);
pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_REMOVEKEY_REQ);
pMsg->length = pal_cpu_to_be16(wMsgLen);
pMsg->sessionId = (tANI_U8)sessionId;
pMsg->transactionId = 0;
p = (tANI_U8 *)pMsg + sizeof(pMsg->messageType) + sizeof(pMsg->length) +
sizeof(pMsg->sessionId) + sizeof(pMsg->transactionId);
// bssId - copy from session Info
vos_mem_copy(p,
&pMac->roam.roamSession[sessionId].connectedProfile.bssid,
sizeof(tSirMacAddr));
p += sizeof(tSirMacAddr);
// peerMacAddr
vos_mem_copy(p, pCommand->u.removeKeyCmd.peerMac, sizeof(tSirMacAddr));
p += sizeof(tSirMacAddr);
// edType
*p = (tANI_U8)csrTranslateEncryptTypeToEdType( pCommand->u.removeKeyCmd.encType );
p++;
// weptype
if( ( eCSR_ENCRYPT_TYPE_WEP40_STATICKEY == pCommand->u.removeKeyCmd.encType ) ||
( eCSR_ENCRYPT_TYPE_WEP104_STATICKEY == pCommand->u.removeKeyCmd.encType ) )
{
*p = (tANI_U8)eSIR_WEP_STATIC;
}
else
{
*p = (tANI_U8)eSIR_WEP_DYNAMIC;
}
p++;
//keyid
*p = pCommand->u.removeKeyCmd.keyId;
p++;
*p = (pCommand->u.removeKeyCmd.peerMac[0] == 0xFF ) ? 0 : 1;
status = palSendMBMessage(pMac->hHdd, pMsg);
}
if( !HAL_STATUS_SUCCESS( status ) )
{
smsLog( pMac, LOGE, FL(" error status %d"), status );
#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
removeKeyEvent.eventId = WLAN_SECURITY_EVENT_REMOVE_KEY_RSP;
removeKeyEvent.status = WLAN_SECURITY_STATUS_FAILURE;
WLAN_VOS_DIAG_EVENT_REPORT(&removeKeyEvent, EVENT_WLAN_SECURITY);
#endif //FEATURE_WLAN_DIAG_SUPPORT_CSR
csrRoamCallCallback( pMac, sessionId, NULL, pCommand->u.removeKeyCmd.roamId, eCSR_ROAM_REMOVE_KEY_COMPLETE, eCSR_ROAM_RESULT_FAILURE);
}
return ( status );
}
eHalStatus csrRoamSetKey( tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamSetKey *pSetKey, tANI_U32 roamId )
{
eHalStatus status;
if( !csrIsSetKeyAllowed(pMac, sessionId) )
{
status = eHAL_STATUS_CSR_WRONG_STATE;
}
else
{
status = csrRoamIssueSetKeyCommand( pMac, sessionId, pSetKey, roamId );
}
return ( status );
}
/*
Prepare a filter base on a profile for parsing the scan results.
Upon successful return, caller MUST call csrFreeScanFilter on
pScanFilter when it is done with the filter.
*/
eHalStatus csrRoamPrepareFilterFromProfile(tpAniSirGlobal pMac, tCsrRoamProfile *pProfile,
tCsrScanResultFilter *pScanFilter)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tANI_U32 size = 0;
tANI_U8 index = 0;
uint8_t i;
do
{
if(pProfile->BSSIDs.numOfBSSIDs)
{
size = sizeof(tCsrBssid) * pProfile->BSSIDs.numOfBSSIDs;
pScanFilter->BSSIDs.bssid = vos_mem_malloc(size);
if ( NULL == pScanFilter->BSSIDs.bssid )
status = eHAL_STATUS_FAILURE;
else
status = eHAL_STATUS_SUCCESS;
if(!HAL_STATUS_SUCCESS(status))
{
break;
}
pScanFilter->BSSIDs.numOfBSSIDs = pProfile->BSSIDs.numOfBSSIDs;
vos_mem_copy(pScanFilter->BSSIDs.bssid, pProfile->BSSIDs.bssid, size);
}
if(pProfile->SSIDs.numOfSSIDs)
{
if( !CSR_IS_WDS_STA( pProfile ) )
{
pScanFilter->SSIDs.numOfSSIDs = pProfile->SSIDs.numOfSSIDs;
}
else
{
//For WDS station
//We always use index 1 for self SSID. Index 0 for peer's SSID that we want to join
pScanFilter->SSIDs.numOfSSIDs = 1;
}
size = sizeof(tCsrSSIDInfo) * pProfile->SSIDs.numOfSSIDs;
pScanFilter->SSIDs.SSIDList = vos_mem_malloc(size);
if ( NULL == pScanFilter->SSIDs.SSIDList )
status = eHAL_STATUS_FAILURE;
else
status = eHAL_STATUS_SUCCESS;
if(!HAL_STATUS_SUCCESS(status))
{
break;
}
vos_mem_copy(pScanFilter->SSIDs.SSIDList, pProfile->SSIDs.SSIDList,
size);
}
if(!pProfile->ChannelInfo.ChannelList || (pProfile->ChannelInfo.ChannelList[0] == 0) )
{
pScanFilter->ChannelInfo.numOfChannels = 0;
pScanFilter->ChannelInfo.ChannelList = NULL;
}
else if(pProfile->ChannelInfo.numOfChannels)
{
pScanFilter->ChannelInfo.ChannelList = vos_mem_malloc(
sizeof(*pScanFilter->ChannelInfo.ChannelList) *
pProfile->ChannelInfo.numOfChannels);
if ( NULL == pScanFilter->ChannelInfo.ChannelList )
status = eHAL_STATUS_FAILURE;
else
status = eHAL_STATUS_SUCCESS;
pScanFilter->ChannelInfo.numOfChannels = 0;
if(HAL_STATUS_SUCCESS(status))
{
for(index = 0; index < pProfile->ChannelInfo.numOfChannels; index++)
{
if(csrRoamIsChannelValid(pMac, pProfile->ChannelInfo.ChannelList[index]))
{
pScanFilter->ChannelInfo.ChannelList[pScanFilter->ChannelInfo.numOfChannels]
= pProfile->ChannelInfo.ChannelList[index];
pScanFilter->ChannelInfo.numOfChannels++;
}
else
{
smsLog(pMac, LOG1, FL("process a channel (%d) that is invalid"), pProfile->ChannelInfo.ChannelList[index]);
}
}
}
else
{
break;
}
}
else
{
smsLog(pMac, LOGE, FL("Channel list empty"));
status = eHAL_STATUS_FAILURE;
break;
}
pScanFilter->uapsd_mask = pProfile->uapsd_mask;
if (pProfile->force_rsne_override) {
smsLog(pMac, LOG1, FL("force_rsne_override enabled fill all auth type and enctype"));
pScanFilter->authType.numEntries = eCSR_NUM_OF_SUPPORT_AUTH_TYPE;
for (i = 0; i < pScanFilter->authType.numEntries; i++)
pScanFilter->authType.authType[i] = i;
index = 0;
for (i = 0; i < eCSR_NUM_OF_ENCRYPT_TYPE; i++) {
if (i == eCSR_ENCRYPT_TYPE_TKIP ||
i == eCSR_ENCRYPT_TYPE_AES) {
pScanFilter->
EncryptionType.encryptionType[index] = i;
pScanFilter->
mcEncryptionType.encryptionType[index] = i;
index++;
}
}
pScanFilter->EncryptionType.numEntries = index;
pScanFilter->mcEncryptionType.numEntries = index;
pScanFilter->ignore_pmf_cap = true;
} else {
pScanFilter->authType = pProfile->AuthType;
pScanFilter->EncryptionType = pProfile->EncryptionType;
pScanFilter->mcEncryptionType = pProfile->mcEncryptionType;
}
pScanFilter->BSSType = pProfile->BSSType;
pScanFilter->phyMode = pProfile->phyMode;
#ifdef FEATURE_WLAN_WAPI
//check if user asked for WAPI with 11n or auto mode, in that case modify
//the phymode to 11g
if(csrIsProfileWapi(pProfile))
{
if(pScanFilter->phyMode & eCSR_DOT11_MODE_11n)
{
pScanFilter->phyMode &= ~eCSR_DOT11_MODE_11n;
}
if(pScanFilter->phyMode & eCSR_DOT11_MODE_AUTO)
{
pScanFilter->phyMode &= ~eCSR_DOT11_MODE_AUTO;
}
if(!pScanFilter->phyMode)
{
pScanFilter->phyMode = eCSR_DOT11_MODE_11g;
}
}
#endif /* FEATURE_WLAN_WAPI */
/*Save the WPS info*/
pScanFilter->bWPSAssociation = pProfile->bWPSAssociation;
pScanFilter->bOSENAssociation = pProfile->bOSENAssociation;
if( pProfile->countryCode[0] )
{
//This causes the matching function to use countryCode as one of the criteria.
vos_mem_copy(pScanFilter->countryCode, pProfile->countryCode,
WNI_CFG_COUNTRY_CODE_LEN);
}
#ifdef WLAN_FEATURE_VOWIFI_11R
if (pProfile->MDID.mdiePresent)
{
pScanFilter->MDID.mdiePresent = 1;
pScanFilter->MDID.mobilityDomain = pProfile->MDID.mobilityDomain;
}
#endif
vos_mem_copy(pScanFilter->bssid_hint,
pProfile->bssid_hint, VOS_MAC_ADDR_SIZE);
#ifdef WLAN_FEATURE_11W
// Management Frame Protection
pScanFilter->MFPEnabled = pProfile->MFPEnabled;
pScanFilter->MFPRequired = pProfile->MFPRequired;
pScanFilter->MFPCapable = pProfile->MFPCapable;
#endif
}while(0);
if(!HAL_STATUS_SUCCESS(status))
{
csrFreeScanFilter(pMac, pScanFilter);
}
return(status);
}
tANI_BOOLEAN csrRoamIssueWmStatusChange( tpAniSirGlobal pMac, tANI_U32 sessionId,
eCsrRoamWmStatusChangeTypes Type, tSirSmeRsp *pSmeRsp )
{
tANI_BOOLEAN fCommandQueued = eANI_BOOLEAN_FALSE;
tSmeCmd *pCommand;
do
{
// Validate the type is ok...
if ( ( eCsrDisassociated != Type ) && ( eCsrDeauthenticated != Type ) ) break;
pCommand = csrGetCommandBuffer( pMac );
if ( !pCommand )
{
smsLog( pMac, LOGE, FL(" fail to get command buffer") );
break;
}
//Change the substate in case it is waiting for key
if( CSR_IS_WAIT_FOR_KEY( pMac, sessionId ) )
{
csrRoamStopWaitForKeyTimer( pMac );
csrRoamSubstateChange( pMac, eCSR_ROAM_SUBSTATE_NONE, sessionId);
}
pCommand->command = eSmeCommandWmStatusChange;
pCommand->sessionId = (tANI_U8)sessionId;
pCommand->u.wmStatusChangeCmd.Type = Type;
if ( eCsrDisassociated == Type )
{
vos_mem_copy(&pCommand->u.wmStatusChangeCmd.u.DisassocIndMsg,
pSmeRsp,
sizeof( pCommand->u.wmStatusChangeCmd.u.DisassocIndMsg ));
}
else
{
vos_mem_copy(&pCommand->u.wmStatusChangeCmd.u.DeauthIndMsg,
pSmeRsp,
sizeof( pCommand->u.wmStatusChangeCmd.u.DeauthIndMsg ));
}
if( HAL_STATUS_SUCCESS( csrQueueSmeCommand(pMac, pCommand, eANI_BOOLEAN_TRUE) ) )
{
fCommandQueued = eANI_BOOLEAN_TRUE;
}
else
{
smsLog( pMac, LOGE, FL(" fail to send message ") );
csrReleaseCommandWmStatusChange( pMac, pCommand );
}
/* AP has issued Dissac/Deauth, Set the operating mode value to configured value */
csrSetDefaultDot11Mode( pMac );
} while( 0 );
return( fCommandQueued );
}
static void csrUpdateRssi(tpAniSirGlobal pMac, void* pMsg)
{
v_S7_t rssi = 0;
tAniGetRssiReq *pGetRssiReq = (tAniGetRssiReq*)pMsg;
if(pGetRssiReq)
{
if(NULL != pGetRssiReq->pVosContext)
{
WLANTL_GetRssi(pGetRssiReq->pVosContext, pGetRssiReq->staId, &rssi);
}
else
{
smsLog( pMac, LOGE, FL("pGetRssiReq->pVosContext is NULL"));
return;
}
if(NULL != pGetRssiReq->rssiCallback)
{
((tCsrRssiCallback)(pGetRssiReq->rssiCallback))(rssi, pGetRssiReq->staId, pGetRssiReq->pDevContext);
}
else
{
smsLog( pMac, LOGE, FL("pGetRssiReq->rssiCallback is NULL"));
return;
}
}
else
{
smsLog( pMac, LOGE, FL("pGetRssiReq is NULL"));
}
return;
}
static void csrUpdateSnr(tpAniSirGlobal pMac, void* pMsg)
{
tANI_S8 snr = 0;
tAniGetSnrReq *pGetSnrReq = (tAniGetSnrReq*)pMsg;
if (pGetSnrReq)
{
if (VOS_STATUS_SUCCESS !=
WDA_GetSnr(pGetSnrReq->staId, &snr))
{
smsLog(pMac, LOGE, FL("Error in WLANTL_GetSnr"));
return;
}
if (pGetSnrReq->snrCallback)
{
((tCsrSnrCallback)(pGetSnrReq->snrCallback))(snr, pGetSnrReq->staId,
pGetSnrReq->pDevContext);
}
else
{
smsLog(pMac, LOGE, FL("pGetSnrReq->snrCallback is NULL"));
return;
}
}
else
{
smsLog(pMac, LOGE, FL("pGetSnrReq is NULL"));
}
return;
}
#if defined WLAN_FEATURE_VOWIFI_11R || defined FEATURE_WLAN_ESE || defined(FEATURE_WLAN_LFR)
void csrRoamRssiRspProcessor(tpAniSirGlobal pMac, void* pMsg)
{
tAniGetRoamRssiRsp* pRoamRssiRsp = (tAniGetRoamRssiRsp*)pMsg;
if (NULL != pRoamRssiRsp)
{
/* Get roam Rssi request is backed up and passed back to the response,
Extract the request message to fetch callback */
tpAniGetRssiReq reqBkp = (tAniGetRssiReq*)pRoamRssiRsp->rssiReq;
v_S7_t rssi = pRoamRssiRsp->rssi;
if ((NULL != reqBkp) && (NULL != reqBkp->rssiCallback))
{
((tCsrRssiCallback)(reqBkp->rssiCallback))(rssi, pRoamRssiRsp->staId, reqBkp->pDevContext);
reqBkp->rssiCallback = NULL;
vos_mem_free(reqBkp);
pRoamRssiRsp->rssiReq = NULL;
}
else
{
smsLog( pMac, LOGE, FL("reqBkp->rssiCallback is NULL"));
if (NULL != reqBkp)
{
vos_mem_free(reqBkp);
pRoamRssiRsp->rssiReq = NULL;
}
}
}
else
{
smsLog( pMac, LOGE, FL("pRoamRssiRsp is NULL"));
}
return;
}
#endif
#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
void csrTsmStatsRspProcessor(tpAniSirGlobal pMac, void* pMsg)
{
tAniGetTsmStatsRsp* pTsmStatsRsp = (tAniGetTsmStatsRsp*)pMsg;
if (NULL != pTsmStatsRsp)
{
/* Get roam Rssi request is backed up and passed back to the response,
Extract the request message to fetch callback */
tpAniGetTsmStatsReq reqBkp = (tAniGetTsmStatsReq*)pTsmStatsRsp->tsmStatsReq;
if (NULL != reqBkp)
{
if (NULL != reqBkp->tsmStatsCallback)
{
((tCsrTsmStatsCallback)(reqBkp->tsmStatsCallback))(pTsmStatsRsp->tsmMetrics,
pTsmStatsRsp->staId, reqBkp->pDevContext);
reqBkp->tsmStatsCallback = NULL;
}
vos_mem_free(reqBkp);
pTsmStatsRsp->tsmStatsReq = NULL;
}
else
{
smsLog( pMac, LOGE, FL("reqBkp is NULL"));
if (NULL != reqBkp)
{
vos_mem_free(reqBkp);
pTsmStatsRsp->tsmStatsReq = NULL;
}
}
}
else
{
smsLog( pMac, LOGE, FL("pTsmStatsRsp is NULL"));
}
return;
}
void csrSendEseAdjacentApRepInd(tpAniSirGlobal pMac, tCsrRoamSession *pSession)
{
tANI_U32 roamTS2 = 0;
tCsrRoamInfo roamInfo;
tpPESession pSessionEntry = NULL;
tANI_U8 sessionId = CSR_SESSION_ID_INVALID;
if (NULL == pSession)
{
smsLog(pMac, LOGE, FL("pSession is NULL"));
return;
}
roamTS2 = vos_timer_get_system_time();
roamInfo.tsmRoamDelay = roamTS2 - pSession->roamTS1;
smsLog(pMac, LOG1, "Bssid("MAC_ADDRESS_STR") Roaming Delay(%u ms)",
MAC_ADDR_ARRAY(pSession->connectedProfile.bssid),
roamInfo.tsmRoamDelay);
pSessionEntry = peFindSessionByBssid(pMac, pSession->connectedProfile.bssid, &sessionId);
if (NULL == pSessionEntry)
{
smsLog(pMac, LOGE, FL("session %d not found"), sessionId);
return;
}
pSessionEntry->eseContext.tsm.tsmMetrics.RoamingDly = roamInfo.tsmRoamDelay;
csrRoamCallCallback(pMac, pSession->sessionId, &roamInfo,
0, eCSR_ROAM_ESE_ADJ_AP_REPORT_IND, 0);
}
#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
static void csrRoamRssiIndHdlr(tpAniSirGlobal pMac, void* pMsg)
{
WLANTL_TlIndicationReq *pTlRssiInd = (WLANTL_TlIndicationReq*)pMsg;
if(pTlRssiInd)
{
if(NULL != pTlRssiInd->tlCallback)
{
((WLANTL_RSSICrossThresholdCBType)(pTlRssiInd->tlCallback))
(pTlRssiInd->pAdapter, pTlRssiInd->rssiNotification, pTlRssiInd->pUserCtxt, pTlRssiInd->avgRssi);
}
else
{
smsLog( pMac, LOGE, FL("pTlRssiInd->tlCallback is NULL"));
}
}
else
{
smsLog( pMac, LOGE, FL("pTlRssiInd is NULL"));
}
return;
}
eHalStatus csrSendResetApCapsChanged(tpAniSirGlobal pMac, tSirMacAddr *bssId)
{
tpSirResetAPCapsChange pMsg;
tANI_U16 len;
eHalStatus status = eHAL_STATUS_SUCCESS;
/* Create the message and send to lim */
len = sizeof(tSirResetAPCapsChange);
pMsg = vos_mem_malloc(len);
if ( NULL == pMsg )
status = eHAL_STATUS_FAILURE;
else
status = eHAL_STATUS_SUCCESS;
if (HAL_STATUS_SUCCESS(status))
{
vos_mem_set(pMsg, sizeof(tSirResetAPCapsChange), 0);
pMsg->messageType = eWNI_SME_RESET_AP_CAPS_CHANGED;
pMsg->length = len;
vos_mem_copy(pMsg->bssId, bssId, sizeof(tSirMacAddr));
smsLog( pMac, LOG1, FL("CSR reset caps change for Bssid= "MAC_ADDRESS_STR),
MAC_ADDR_ARRAY(pMsg->bssId));
status = palSendMBMessage(pMac->hHdd, pMsg);
}
else
{
smsLog( pMac, LOGE, FL("Memory allocation failed\n"));
}
return status;
}
void csrRoamCheckForLinkStatusChange( tpAniSirGlobal pMac, tSirSmeRsp *pSirMsg )
{
tSirSmeAssocInd *pAssocInd;
tSirSmeDisassocInd *pDisassocInd;
tSirSmeDeauthInd *pDeauthInd;
tSirSmeDisConDoneInd *pDisConDoneInd;
tSirSmeWmStatusChangeNtf *pStatusChangeMsg;
tSirSmeNewBssInfo *pNewBss;
tSmeIbssPeerInd *pIbssPeerInd;
tSirMacAddr Broadcastaddr = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
tSirSmeApNewCaps *pApNewCaps;
eCsrRoamResult result = eCSR_ROAM_RESULT_NONE;
eRoamCmdStatus roamStatus = eCSR_ROAM_FAILED;
tCsrRoamInfo *pRoamInfo = NULL;
tCsrRoamInfo roamInfo;
eHalStatus status;
tANI_U32 sessionId = CSR_SESSION_ID_INVALID;
tCsrRoamSession *pSession = NULL;
tpSirSmeSwitchChannelInd pSwitchChnInd;
tSmeMaxAssocInd *pSmeMaxAssocInd;
vos_mem_set(&roamInfo, sizeof(roamInfo), 0);
if (NULL == pSirMsg)
{ smsLog(pMac, LOGE, FL("pSirMsg is NULL"));
return;
}
switch( pSirMsg->messageType )
{
case eWNI_SME_ASSOC_IND:
{
tCsrRoamSession *pSession = NULL;
smsLog( pMac, LOG1, FL("Receive WNI_SME_ASSOC_IND from SME"));
pAssocInd = (tSirSmeAssocInd *)pSirMsg;
status = csrRoamGetSessionIdFromBSSID( pMac, (tCsrBssid *)pAssocInd->bssId, &sessionId );
if( HAL_STATUS_SUCCESS( status ) )
{
pSession = CSR_GET_SESSION(pMac, sessionId);
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return;
}
pRoamInfo = &roamInfo;
// Required for indicating the frames to upper layer
pRoamInfo->assocReqLength = pAssocInd->assocReqLength;
pRoamInfo->assocReqPtr = pAssocInd->assocReqPtr;
pRoamInfo->beaconPtr = pAssocInd->beaconPtr;
pRoamInfo->beaconLength = pAssocInd->beaconLength;
pRoamInfo->statusCode = eSIR_SME_SUCCESS; //send the status code as Success
pRoamInfo->u.pConnectedProfile = &pSession->connectedProfile;
pRoamInfo->staId = (tANI_U8)pAssocInd->staId;
pRoamInfo->rsnIELen = (tANI_U8)pAssocInd->rsnIE.length;
pRoamInfo->prsnIE = pAssocInd->rsnIE.rsnIEdata;
pRoamInfo->addIELen = (tANI_U8)pAssocInd->addIE.length;
pRoamInfo->paddIE = pAssocInd->addIE.addIEdata;
vos_mem_copy(pRoamInfo->peerMac, pAssocInd->peerMacAddr,
sizeof(tSirMacAddr));
vos_mem_copy(&pRoamInfo->bssid, pAssocInd->bssId,
sizeof(tCsrBssid));
pRoamInfo->wmmEnabledSta = pAssocInd->wmmEnabledSta;
pRoamInfo->maxRateFlags = pAssocInd->rate_flags;
#ifdef WLAN_FEATURE_AP_HT40_24G
pRoamInfo->HT40MHzIntoEnabledSta =
pAssocInd->HT40MHzIntoEnabledSta;
smsLog(pMac, LOGW, FL("HT40MHzIntoEnabledSta: %d \n"),
pRoamInfo->HT40MHzIntoEnabledSta);
#endif
if(CSR_IS_WDS_AP( pRoamInfo->u.pConnectedProfile))
status = csrRoamCallCallback(pMac, sessionId, pRoamInfo, 0, eCSR_ROAM_WDS_IND, eCSR_ROAM_RESULT_WDS_ASSOCIATION_IND);//Sta
if(CSR_IS_INFRA_AP(pRoamInfo->u.pConnectedProfile))
{
#ifdef SAP_AUTH_OFFLOAD
if (pMac->sap_auth_offload)
{
smsLog(pMac, LOGW, FL(" Auth is not required to set in Auth offload case \n"));
pRoamInfo->fAuthRequired = FALSE;
}
else
{
#endif
if( CSR_IS_ENC_TYPE_STATIC( pSession->pCurRoamProfile->negotiatedUCEncryptionType ))
{
csrRoamIssueSetContextReq( pMac, sessionId, pSession->pCurRoamProfile->negotiatedUCEncryptionType,
pSession->pConnectBssDesc,
&(pRoamInfo->peerMac),
FALSE, TRUE, eSIR_TX_RX, 0, 0, NULL, 0 ); // NO keys... these key parameters don't matter.
pRoamInfo->fAuthRequired = FALSE;
}
else
{
pRoamInfo->fAuthRequired = TRUE;
}
#ifdef SAP_AUTH_OFFLOAD
}
#endif
status = csrRoamCallCallback(pMac, sessionId, pRoamInfo, 0, eCSR_ROAM_INFRA_IND, eCSR_ROAM_RESULT_INFRA_ASSOCIATION_IND);
if (!HAL_STATUS_SUCCESS(status))
pRoamInfo->statusCode = eSIR_SME_ASSOC_REFUSED;// Refused due to Mac filtering
}
/* Send Association completion message to PE */
status = csrSendAssocCnfMsg( pMac, pAssocInd, status );//Sta
/* send a message to CSR itself just to avoid the EAPOL frames going
* OTA before association response */
if(CSR_IS_WDS_AP( pRoamInfo->u.pConnectedProfile))
{
status = csrSendAssocIndToUpperLayerCnfMsg(pMac, pAssocInd, status, sessionId);
}
else if(CSR_IS_INFRA_AP(pRoamInfo->u.pConnectedProfile) && (pRoamInfo->statusCode != eSIR_SME_ASSOC_REFUSED))
{
pRoamInfo->fReassocReq = pAssocInd->reassocReq;
//status = csrRoamCallCallback(pMac, sessionId, pRoamInfo, 0, eCSR_ROAM_INFRA_IND, eCSR_ROAM_RESULT_INFRA_ASSOCIATION_CNF);
status = csrSendAssocIndToUpperLayerCnfMsg(pMac, pAssocInd, status, sessionId);
}
}
}
break;
case eWNI_SME_DISASSOC_IND:
{
// Check if AP dis-associated us because of MIC failure. If so,
// then we need to take action immediately and not wait till the
// the WmStatusChange requests is pushed and processed
tSmeCmd *pCommand;
pDisassocInd = (tSirSmeDisassocInd *)pSirMsg;
status = csrRoamGetSessionIdFromBSSID( pMac,
(tCsrBssid *)pDisassocInd->bssId, &sessionId );
if( HAL_STATUS_SUCCESS( status ) )
{
smsLog( pMac, LOGE, FL("DISASSOCIATION Indication from MAC"
" for session %d "), sessionId);
smsLog( pMac, LOGE, FL("DISASSOCIATION from peer ="
MAC_ADDRESS_STR " "
" reason = %d status = %d "),
MAC_ADDR_ARRAY(pDisassocInd->peerMacAddr),
pDisassocInd->reasonCode,
pDisassocInd->statusCode);
// If we are in neighbor preauth done state then on receiving
// disassoc or deauth we dont roam instead we just disassoc
// from current ap and then go to disconnected state
// This happens for ESE and 11r FT connections ONLY.
#ifdef WLAN_FEATURE_VOWIFI_11R
if (csrRoamIs11rAssoc(pMac) && (csrNeighborRoamStatePreauthDone(pMac)))
{
csrNeighborRoamTranistionPreauthDoneToDisconnected(pMac);
}
#endif
#ifdef FEATURE_WLAN_ESE
if (csrRoamIsESEAssoc(pMac) && (csrNeighborRoamStatePreauthDone(pMac)))
{
csrNeighborRoamTranistionPreauthDoneToDisconnected(pMac);
}
#endif
#ifdef FEATURE_WLAN_LFR
if (csrRoamIsFastRoamEnabled(pMac, sessionId) && (csrNeighborRoamStatePreauthDone(pMac)))
{
csrNeighborRoamTranistionPreauthDoneToDisconnected(pMac);
}
#endif
#ifdef WLAN_FEATURE_LFR_MBB
csr_stop_preauth_reassoc_mbb_timer(pMac);
#endif
pSession = CSR_GET_SESSION( pMac, sessionId );
if (!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return;
}
if ( csrIsConnStateInfra( pMac, sessionId ) )
{
pSession->connectState = eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED;
}
#ifndef WLAN_MDM_CODE_REDUCTION_OPT
sme_QosCsrEventInd(pMac, (v_U8_t)sessionId, SME_QOS_CSR_DISCONNECT_IND, NULL);
#endif
csrRoamLinkDown(pMac, sessionId);
csrRoamIssueWmStatusChange( pMac, sessionId, eCsrDisassociated, pSirMsg );
if (CSR_IS_INFRA_AP(&pSession->connectedProfile))
{
/*
* STA/P2P client got disassociated so remove any pending deauth
* commands in sme pending list
*/
pCommand = csrGetCommandBuffer(pMac);
if (NULL == pCommand)
{
smsLog( pMac, LOGE, FL(" fail to get command buffer") );
status = eHAL_STATUS_RESOURCES;
return;
}
pCommand->command = eSmeCommandRoam;
pCommand->sessionId = (tANI_U8)sessionId;
pCommand->u.roamCmd.roamReason = eCsrForcedDeauthSta;
vos_mem_copy(pCommand->u.roamCmd.peerMac,
pDisassocInd->peerMacAddr,
sizeof(tSirMacAddr));
csrRoamRemoveDuplicateCommand(pMac, sessionId, pCommand, eCsrForcedDeauthSta);
csrReleaseCommand( pMac, pCommand );
}
}
else
{
smsLog(pMac, LOGE, FL(" Session Id not found for BSSID " MAC_ADDRESS_STR),
MAC_ADDR_ARRAY(pDisassocInd->bssId));
}
}
break;
case eWNI_SME_DEAUTH_IND:
smsLog( pMac, LOG1, FL("DEAUTHENTICATION Indication from MAC"));
pDeauthInd = (tpSirSmeDeauthInd)pSirMsg;
status = csrRoamGetSessionIdFromBSSID( pMac, (tCsrBssid *)pDeauthInd->bssId, &sessionId );
if( HAL_STATUS_SUCCESS( status ) )
{
// If we are in neighbor preauth done state then on receiving
// disassoc or deauth we dont roam instead we just disassoc
// from current ap and then go to disconnected state
// This happens for ESE and 11r FT connections ONLY.
#ifdef WLAN_FEATURE_VOWIFI_11R
if (csrRoamIs11rAssoc(pMac) && (csrNeighborRoamStatePreauthDone(pMac)))
{
csrNeighborRoamTranistionPreauthDoneToDisconnected(pMac);
}
#endif
#ifdef FEATURE_WLAN_ESE
if (csrRoamIsESEAssoc(pMac) && (csrNeighborRoamStatePreauthDone(pMac)))
{
csrNeighborRoamTranistionPreauthDoneToDisconnected(pMac);
}
#endif
#ifdef FEATURE_WLAN_LFR
if (csrRoamIsFastRoamEnabled(pMac, sessionId) && (csrNeighborRoamStatePreauthDone(pMac)))
{
csrNeighborRoamTranistionPreauthDoneToDisconnected(pMac);
}
#endif
#ifdef WLAN_FEATURE_LFR_MBB
csr_stop_preauth_reassoc_mbb_timer(pMac);
#endif
pSession = CSR_GET_SESSION( pMac, sessionId );
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return;
}
if ( csrIsConnStateInfra( pMac, sessionId ) )
{
pSession->connectState = eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED;
}
#ifndef WLAN_MDM_CODE_REDUCTION_OPT
sme_QosCsrEventInd(pMac, (v_U8_t)sessionId, SME_QOS_CSR_DISCONNECT_IND, NULL);
#endif
#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
csrRemoveNeighbourRoamPreauthCommand(pMac);
#endif
csrRoamLinkDown(pMac, sessionId);
csrRoamIssueWmStatusChange( pMac, sessionId, eCsrDeauthenticated, pSirMsg );
}
break;
case eWNI_SME_DISCONNECT_DONE_IND:
pDisConDoneInd = (tSirSmeDisConDoneInd *)(pSirMsg);
smsLog( pMac, LOG1,
FL("eWNI_SME_DISCONNECT_DONE_IND RC:%d"),
pDisConDoneInd->reasonCode);
if( CSR_IS_SESSION_VALID(pMac, pDisConDoneInd->sessionId))
{
roamInfo.reasonCode = pDisConDoneInd->reasonCode;
roamInfo.statusCode = eSIR_SME_STA_DISASSOCIATED;
vos_mem_copy(roamInfo.peerMac, pDisConDoneInd->peerMacAddr,
sizeof(tSirMacAddr));
status = csrRoamCallCallback(pMac,
pDisConDoneInd->sessionId,
&roamInfo, 0,
eCSR_ROAM_LOSTLINK,
eCSR_ROAM_RESULT_DISASSOC_IND);
pSession = CSR_GET_SESSION(pMac,
pDisConDoneInd->sessionId);
if (pSession &&
!CSR_IS_INFRA_AP(&pSession->connectedProfile))
csrRoamStateChange(pMac,
eCSR_ROAMING_STATE_IDLE,
pDisConDoneInd->sessionId);
}
else
{
smsLog(pMac, LOGE, FL("Inactive session %d"),
pDisConDoneInd->sessionId);
}
break;
case eWNI_SME_SWITCH_CHL_REQ: // in case of STA, the SWITCH_CHANNEL originates from its AP
smsLog( pMac, LOGW, FL("eWNI_SME_SWITCH_CHL_REQ from SME"));
pSwitchChnInd = (tpSirSmeSwitchChannelInd)pSirMsg;
//Update with the new channel id.
//The channel id is hidden in the statusCode.
status = csrRoamGetSessionIdFromBSSID( pMac, (tCsrBssid *)pSwitchChnInd->bssId, &sessionId );
if( HAL_STATUS_SUCCESS( status ) )
{
pRoamInfo = &roamInfo;
pSession = CSR_GET_SESSION( pMac, sessionId );
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return;
}
pSession->connectedProfile.operationChannel = (tANI_U8)pSwitchChnInd->newChannelId;
if(pSession->pConnectBssDesc)
{
pSession->pConnectBssDesc->channelId = (tANI_U8)pSwitchChnInd->newChannelId;
}
pRoamInfo->chan_info.chan_id =
(tANI_U8)pSwitchChnInd->newChannelId;
csrRoamCallCallback(pMac, sessionId, pRoamInfo, 0,
eCSR_ROAM_STA_CHANNEL_SWITCH,
eCSR_ROAM_RESULT_NONE);
}
break;
case eWNI_SME_DEAUTH_RSP:
smsLog( pMac, LOGW, FL("eWNI_SME_DEAUTH_RSP from SME"));
{
tSirSmeDeauthRsp* pDeauthRsp = (tSirSmeDeauthRsp *)pSirMsg;
sessionId = pDeauthRsp->sessionId;
if( CSR_IS_SESSION_VALID(pMac, sessionId) )
{
pSession = CSR_GET_SESSION(pMac, sessionId);
if ( CSR_IS_INFRA_AP(&pSession->connectedProfile) )
{
pRoamInfo = &roamInfo;
pRoamInfo->u.pConnectedProfile = &pSession->connectedProfile;
vos_mem_copy(pRoamInfo->peerMac, pDeauthRsp->peerMacAddr,
sizeof(tSirMacAddr));
pRoamInfo->reasonCode = eCSR_ROAM_RESULT_FORCED;
pRoamInfo->statusCode = pDeauthRsp->statusCode;
status = csrRoamCallCallback(pMac, sessionId, pRoamInfo, 0, eCSR_ROAM_LOSTLINK, eCSR_ROAM_RESULT_FORCED);
}
}
}
break;
case eWNI_SME_DISASSOC_RSP:
/* session id is invalid here so cant use it to access the array curSubstate as index */
smsLog( pMac, LOGW, FL("eWNI_SME_DISASSOC_RSP from SME "));
{
tSirSmeDisassocRsp *pDisassocRsp = (tSirSmeDisassocRsp *)pSirMsg;
sessionId = pDisassocRsp->sessionId;
if( CSR_IS_SESSION_VALID(pMac, sessionId) )
{
pSession = CSR_GET_SESSION(pMac, sessionId);
if ( CSR_IS_INFRA_AP(&pSession->connectedProfile) )
{
pRoamInfo = &roamInfo;
pRoamInfo->u.pConnectedProfile = &pSession->connectedProfile;
vos_mem_copy(pRoamInfo->peerMac, pDisassocRsp->peerMacAddr,
sizeof(tSirMacAddr));
pRoamInfo->reasonCode = eCSR_ROAM_RESULT_FORCED;
pRoamInfo->statusCode = pDisassocRsp->statusCode;
status = csrRoamCallCallback(pMac, sessionId, pRoamInfo, 0, eCSR_ROAM_LOSTLINK, eCSR_ROAM_RESULT_FORCED);
}
}
}
break;
case eWNI_SME_LOST_LINK_PARAMS_IND:
{
tpSirSmeLostLinkParamsInd pLostLinkParamsInd = (tpSirSmeLostLinkParamsInd)pSirMsg;
tCsrRoamInfo roamInfo, *pRoamInfo = NULL;
eCsrRoamResult result = eCSR_ROAM_RESULT_NONE;
vos_mem_set(&roamInfo, sizeof(tCsrRoamInfo), 0);
roamInfo.u.pLostLinkParams = &pLostLinkParamsInd->info;
pRoamInfo = &roamInfo;
csrRoamCallCallback(pMac, pLostLinkParamsInd->sessionId,
pRoamInfo, 0, eCSR_ROAM_LOST_LINK_PARAMS_IND, result);
break;
}
case eWNI_SME_MIC_FAILURE_IND:
{
tpSirSmeMicFailureInd pMicInd = (tpSirSmeMicFailureInd)pSirMsg;
tCsrRoamInfo roamInfo, *pRoamInfo = NULL;
eCsrRoamResult result = eCSR_ROAM_RESULT_MIC_ERROR_UNICAST;
status = csrRoamGetSessionIdFromBSSID( pMac, (tCsrBssid *)pMicInd->bssId, &sessionId );
if( HAL_STATUS_SUCCESS( status ) )
{
vos_mem_set(&roamInfo, sizeof(tCsrRoamInfo), 0);
roamInfo.u.pMICFailureInfo = &pMicInd->info;
pRoamInfo = &roamInfo;
if(pMicInd->info.multicast)
{
result = eCSR_ROAM_RESULT_MIC_ERROR_GROUP;
}
else
{
result = eCSR_ROAM_RESULT_MIC_ERROR_UNICAST;
}
csrRoamCallCallback(pMac, sessionId, pRoamInfo, 0, eCSR_ROAM_MIC_ERROR_IND, result);
}
#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
{
WLAN_VOS_DIAG_EVENT_DEF(secEvent, vos_event_wlan_security_payload_type);
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return;
}
vos_mem_set(&secEvent, sizeof(vos_event_wlan_security_payload_type), 0);
secEvent.eventId = WLAN_SECURITY_EVENT_MIC_ERROR;
secEvent.encryptionModeMulticast =
(v_U8_t)diagEncTypeFromCSRType(pSession->connectedProfile.mcEncryptionType);
secEvent.encryptionModeUnicast =
(v_U8_t)diagEncTypeFromCSRType(pSession->connectedProfile.EncryptionType);
secEvent.authMode =
(v_U8_t)diagAuthTypeFromCSRType(pSession->connectedProfile.AuthType);
vos_mem_copy(secEvent.bssid,
pSession->connectedProfile.bssid, 6);
WLAN_VOS_DIAG_EVENT_REPORT(&secEvent, EVENT_WLAN_SECURITY);
}
#endif//FEATURE_WLAN_DIAG_SUPPORT_CSR
}
break;
case eWNI_SME_WPS_PBC_PROBE_REQ_IND:
{
tpSirSmeProbeReqInd pProbeReqInd = (tpSirSmeProbeReqInd)pSirMsg;
tCsrRoamInfo roamInfo;
smsLog( pMac, LOG1, FL("WPS PBC Probe request Indication from SME"));
status = csrRoamGetSessionIdFromBSSID( pMac, (tCsrBssid *)pProbeReqInd->bssId, &sessionId );
if( HAL_STATUS_SUCCESS( status ) )
{
vos_mem_set(&roamInfo, sizeof(tCsrRoamInfo), 0);
roamInfo.u.pWPSPBCProbeReq = &pProbeReqInd->WPSPBCProbeReq;
csrRoamCallCallback(pMac, sessionId, &roamInfo, 0, eCSR_ROAM_WPS_PBC_PROBE_REQ_IND,
eCSR_ROAM_RESULT_WPS_PBC_PROBE_REQ_IND);
}
}
break;
case eWNI_SME_WM_STATUS_CHANGE_NTF:
pStatusChangeMsg = (tSirSmeWmStatusChangeNtf *)pSirMsg;
switch( pStatusChangeMsg->statusChangeCode )
{
case eSIR_SME_IBSS_ACTIVE:
sessionId = csrFindIbssSession( pMac );
if( CSR_SESSION_ID_INVALID != sessionId )
{
pSession = CSR_GET_SESSION( pMac, sessionId );
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return;
}
pSession->connectState = eCSR_ASSOC_STATE_TYPE_IBSS_CONNECTED;
if(pSession->pConnectBssDesc)
{
vos_mem_copy(&roamInfo.bssid,
pSession->pConnectBssDesc->bssId,
sizeof(tCsrBssid));
roamInfo.u.pConnectedProfile = &pSession->connectedProfile;
pRoamInfo = &roamInfo;
}
else
{
smsLog(pMac, LOGE, " CSR eSIR_SME_IBSS_NEW_PEER connected BSS is empty");
}
result = eCSR_ROAM_RESULT_IBSS_CONNECT;
roamStatus = eCSR_ROAM_CONNECT_STATUS_UPDATE;
}
break;
case eSIR_SME_IBSS_INACTIVE:
sessionId = csrFindIbssSession( pMac );
if( CSR_SESSION_ID_INVALID != sessionId )
{
pSession = CSR_GET_SESSION( pMac, sessionId );
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return;
}
pSession->connectState = eCSR_ASSOC_STATE_TYPE_IBSS_DISCONNECTED;
result = eCSR_ROAM_RESULT_IBSS_INACTIVE;
roamStatus = eCSR_ROAM_CONNECT_STATUS_UPDATE;
}
break;
case eSIR_SME_JOINED_NEW_BSS: // IBSS coalescing.
sessionId = csrFindIbssSession( pMac );
if( CSR_SESSION_ID_INVALID != sessionId )
{
pSession = CSR_GET_SESSION( pMac, sessionId );
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return;
}
// update the connection state information
pNewBss = &pStatusChangeMsg->statusChangeInfo.newBssInfo;
#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
{
vos_log_ibss_pkt_type *pIbssLog;
tANI_U32 bi;
WLAN_VOS_DIAG_LOG_ALLOC(pIbssLog, vos_log_ibss_pkt_type, LOG_WLAN_IBSS_C);
if(pIbssLog)
{
pIbssLog->eventId = WLAN_IBSS_EVENT_COALESCING;
if(pNewBss)
{
vos_mem_copy(pIbssLog->bssid, pNewBss->bssId, 6);
if(pNewBss->ssId.length >
VOS_LOG_MAX_SSID_SIZE)
pNewBss->ssId.length =
VOS_LOG_MAX_SSID_SIZE;
vos_mem_copy(pIbssLog->ssid,
pNewBss->ssId.ssId,
pNewBss->ssId.length);
pIbssLog->operatingChannel = pNewBss->channelNumber;
}
if(HAL_STATUS_SUCCESS(ccmCfgGetInt(pMac, WNI_CFG_BEACON_INTERVAL, &bi)))
{
//***U8 is not enough for beacon interval
pIbssLog->beaconInterval = (v_U8_t)bi;
}
WLAN_VOS_DIAG_LOG_REPORT(pIbssLog);
}
}
#endif //FEATURE_WLAN_DIAG_SUPPORT_CSR
csrRoamUpdateConnectedProfileFromNewBss( pMac, sessionId, pNewBss );
if ((eCSR_ENCRYPT_TYPE_NONE ==
pSession->connectedProfile.EncryptionType ))
{
csrRoamIssueSetContextReq( pMac, sessionId,
pSession->connectedProfile.EncryptionType,
pSession->pConnectBssDesc,
&Broadcastaddr,
FALSE, FALSE, eSIR_TX_RX, 0, 0, NULL, 0 );
}
result = eCSR_ROAM_RESULT_IBSS_COALESCED;
roamStatus = eCSR_ROAM_IBSS_IND;
vos_mem_copy(&roamInfo.bssid, &pNewBss->bssId,
sizeof(tCsrBssid));
pRoamInfo = &roamInfo;
//This BSSID is th ereal BSSID, let's save it
if(pSession->pConnectBssDesc)
{
vos_mem_copy(pSession->pConnectBssDesc->bssId,
&pNewBss->bssId, sizeof(tCsrBssid));
}
}
smsLog(pMac, LOGW, "CSR: eSIR_SME_JOINED_NEW_BSS received from PE");
break;
// detection by LIM that the capabilities of the associated AP have changed.
case eSIR_SME_AP_CAPS_CHANGED:
pApNewCaps = &pStatusChangeMsg->statusChangeInfo.apNewCaps;
smsLog(pMac, LOGW, "CSR handling eSIR_SME_AP_CAPS_CHANGED");
status = csrRoamGetSessionIdFromBSSID( pMac, (tCsrBssid *)pApNewCaps->bssId, &sessionId );
if( HAL_STATUS_SUCCESS( status ) )
{
if ((eCSR_ROAMING_STATE_JOINED == pMac->roam.curState[sessionId]) &&
((eCSR_ROAM_SUBSTATE_JOINED_REALTIME_TRAFFIC == pMac->roam.curSubState[sessionId]) ||
(eCSR_ROAM_SUBSTATE_NONE == pMac->roam.curSubState[sessionId]) ||
(eCSR_ROAM_SUBSTATE_JOINED_NON_REALTIME_TRAFFIC == pMac->roam.curSubState[sessionId]) ||
(eCSR_ROAM_SUBSTATE_JOINED_NO_TRAFFIC == pMac->roam.curSubState[sessionId]))
)
{
smsLog(pMac, LOGW, "Calling csrRoamDisconnectInternal");
csrRoamDisconnectInternal(pMac, sessionId, eCSR_DISCONNECT_REASON_UNSPECIFIED);
}
else
{
smsLog(pMac, LOGW,
FL("Skipping csrScanForCapabilityChange as "
"CSR is in state %s and sub-state %s"),
macTraceGetcsrRoamState(
pMac->roam.curState[sessionId]),
macTraceGetcsrRoamSubState(
pMac->roam.curSubState[sessionId]));
/* We ignore the caps change event if CSR is not in full connected state.
* Send one event to PE to reset limSentCapsChangeNtf
* Once limSentCapsChangeNtf set 0, lim can send sub sequent CAPS change event
* otherwise lim cannot send any CAPS change events to SME */
csrSendResetApCapsChanged(pMac, &pApNewCaps->bssId);
}
}
break;
default:
roamStatus = eCSR_ROAM_FAILED;
result = eCSR_ROAM_RESULT_NONE;
break;
} // end switch on statusChangeCode
if(eCSR_ROAM_RESULT_NONE != result)
{
csrRoamCallCallback(pMac, sessionId, pRoamInfo, 0, roamStatus, result);
}
break;
case eWNI_SME_IBSS_NEW_PEER_IND:
pIbssPeerInd = (tSmeIbssPeerInd *)pSirMsg;
#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
{
vos_log_ibss_pkt_type *pIbssLog;
WLAN_VOS_DIAG_LOG_ALLOC(pIbssLog, vos_log_ibss_pkt_type, LOG_WLAN_IBSS_C);
if(pIbssLog)
{
pIbssLog->eventId = WLAN_IBSS_EVENT_PEER_JOIN;
vos_mem_copy(pIbssLog->peerMacAddr, &pIbssPeerInd->peerAddr, 6);
WLAN_VOS_DIAG_LOG_REPORT(pIbssLog);
}
}
#endif //FEATURE_WLAN_DIAG_SUPPORT_CSR
sessionId = csrFindIbssSession( pMac );
if( CSR_SESSION_ID_INVALID != sessionId )
{
pSession = CSR_GET_SESSION( pMac, sessionId );
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return;
}
// Issue the set Context request to LIM to establish the Unicast STA context for the new peer...
if(pSession->pConnectBssDesc)
{
vos_mem_copy(&roamInfo.peerMac, pIbssPeerInd->peerAddr,
sizeof(tCsrBssid));
vos_mem_copy(&roamInfo.bssid, pSession->pConnectBssDesc->bssId,
sizeof(tCsrBssid));
if(pIbssPeerInd->mesgLen > sizeof(tSmeIbssPeerInd))
{
roamInfo.pbFrames = vos_mem_malloc((pIbssPeerInd->mesgLen
- sizeof(tSmeIbssPeerInd)));
if ( NULL == roamInfo.pbFrames )
status = eHAL_STATUS_FAILURE;
else
status = eHAL_STATUS_SUCCESS;
if (HAL_STATUS_SUCCESS(status))
{
roamInfo.nBeaconLength = (pIbssPeerInd->mesgLen - sizeof(tSmeIbssPeerInd));
vos_mem_copy(roamInfo.pbFrames,
((tANI_U8 *)pIbssPeerInd) + sizeof(tSmeIbssPeerInd),
roamInfo.nBeaconLength);
}
roamInfo.staId = (tANI_U8)pIbssPeerInd->staId;
roamInfo.ucastSig = (tANI_U8)pIbssPeerInd->ucastSig;
roamInfo.bcastSig = (tANI_U8)pIbssPeerInd->bcastSig;
roamInfo.pBssDesc = vos_mem_malloc(pSession->pConnectBssDesc->length);
if ( NULL == roamInfo.pBssDesc )
status = eHAL_STATUS_FAILURE;
else
status = eHAL_STATUS_SUCCESS;
if (HAL_STATUS_SUCCESS(status))
{
vos_mem_copy(roamInfo.pBssDesc,
pSession->pConnectBssDesc,
pSession->pConnectBssDesc->length);
}
if(HAL_STATUS_SUCCESS(status))
{
pRoamInfo = &roamInfo;
}
else
{
if(roamInfo.pbFrames)
{
vos_mem_free(roamInfo.pbFrames);
}
if(roamInfo.pBssDesc)
{
vos_mem_free(roamInfo.pBssDesc);
}
}
}
else
{
pRoamInfo = &roamInfo;
}
if ((eCSR_ENCRYPT_TYPE_NONE ==
pSession->connectedProfile.EncryptionType ))
{
csrRoamIssueSetContextReq( pMac, sessionId,
pSession->connectedProfile.EncryptionType,
pSession->pConnectBssDesc,
&(pIbssPeerInd->peerAddr),
FALSE, TRUE, eSIR_TX_RX, 0, 0, NULL, 0 ); // NO keys... these key parameters don't matter.
}
}
else
{
smsLog(pMac, LOGW, " CSR eSIR_SME_IBSS_NEW_PEER connected BSS is empty");
}
//send up the sec type for the new peer
if (pRoamInfo)
{
pRoamInfo->u.pConnectedProfile = &pSession->connectedProfile;
}
csrRoamCallCallback(pMac, sessionId, pRoamInfo, 0,
eCSR_ROAM_CONNECT_STATUS_UPDATE, eCSR_ROAM_RESULT_IBSS_NEW_PEER);
if(pRoamInfo)
{
if(roamInfo.pbFrames)
{
vos_mem_free(roamInfo.pbFrames);
}
if(roamInfo.pBssDesc)
{
vos_mem_free(roamInfo.pBssDesc);
}
}
}
break;
case eWNI_SME_IBSS_PEER_DEPARTED_IND:
pIbssPeerInd = (tSmeIbssPeerInd*)pSirMsg;
sessionId = csrFindIbssSession( pMac );
if( CSR_SESSION_ID_INVALID != sessionId )
{
#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
{
vos_log_ibss_pkt_type *pIbssLog;
WLAN_VOS_DIAG_LOG_ALLOC(pIbssLog, vos_log_ibss_pkt_type, LOG_WLAN_IBSS_C);
if(pIbssLog)
{
pIbssLog->eventId = WLAN_IBSS_EVENT_PEER_LEAVE;
if(pIbssPeerInd)
{
vos_mem_copy(pIbssLog->peerMacAddr,
&pIbssPeerInd->peerAddr, 6);
}
WLAN_VOS_DIAG_LOG_REPORT(pIbssLog);
}
}
#endif //FEATURE_WLAN_DIAG_SUPPORT_CSR
smsLog(pMac, LOGW, "CSR: Peer departed notification from LIM");
roamInfo.staId = (tANI_U8)pIbssPeerInd->staId;
roamInfo.ucastSig = (tANI_U8)pIbssPeerInd->ucastSig;
roamInfo.bcastSig = (tANI_U8)pIbssPeerInd->bcastSig;
vos_mem_copy(&roamInfo.peerMac, pIbssPeerInd->peerAddr,
sizeof(tCsrBssid));
csrRoamCallCallback(pMac, sessionId, &roamInfo, 0,
eCSR_ROAM_CONNECT_STATUS_UPDATE, eCSR_ROAM_RESULT_IBSS_PEER_DEPARTED);
}
break;
case eWNI_SME_SETCONTEXT_RSP:
{
tSirSmeSetContextRsp *pRsp = (tSirSmeSetContextRsp *)pSirMsg;
tListElem *pEntry;
tSmeCmd *pCommand;
pEntry = csrLLPeekHead( &pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK );
if ( pEntry )
{
pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link );
if ( eSmeCommandSetKey == pCommand->command )
{
sessionId = pCommand->sessionId;
pSession = CSR_GET_SESSION( pMac, sessionId );
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return;
}
#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
if(eCSR_ENCRYPT_TYPE_NONE != pSession->connectedProfile.EncryptionType)
{
WLAN_VOS_DIAG_EVENT_DEF(setKeyEvent, vos_event_wlan_security_payload_type);
vos_mem_set(&setKeyEvent,
sizeof(vos_event_wlan_security_payload_type), 0);
if( pRsp->peerMacAddr[0] & 0x01 )
{
setKeyEvent.eventId =
WLAN_SECURITY_EVENT_SET_BCAST_RSP;
}
else
{
setKeyEvent.eventId =
WLAN_SECURITY_EVENT_SET_UNICAST_RSP;
}
if( pRsp->peerMacAddr[0] & 0x01 )
{
pMac->pmc.full_power_till_set_key = false;
smsLog(pMac, LOG1, FL("Reset full_power_till_set_key to allow BMPS"));
}
setKeyEvent.encryptionModeMulticast =
(v_U8_t)diagEncTypeFromCSRType(pSession->connectedProfile.mcEncryptionType);
setKeyEvent.encryptionModeUnicast =
(v_U8_t)diagEncTypeFromCSRType(pSession->connectedProfile.EncryptionType);
vos_mem_copy(setKeyEvent.bssid,
pSession->connectedProfile.bssid, 6);
setKeyEvent.authMode =
(v_U8_t)diagAuthTypeFromCSRType(pSession->connectedProfile.AuthType);
if( eSIR_SME_SUCCESS != pRsp->statusCode )
{
setKeyEvent.status = WLAN_SECURITY_STATUS_FAILURE;
}
WLAN_VOS_DIAG_EVENT_REPORT(&setKeyEvent, EVENT_WLAN_SECURITY);
}
#endif //FEATURE_WLAN_DIAG_SUPPORT_CSR
if( CSR_IS_WAIT_FOR_KEY( pMac, sessionId) )
{
csrRoamStopWaitForKeyTimer( pMac );
//We are done with authentication, whethere succeed or not
csrRoamSubstateChange( pMac, eCSR_ROAM_SUBSTATE_NONE, sessionId);
//We do it here because this linkup function is not called after association
//when a key needs to be set.
if( csrIsConnStateConnectedInfra(pMac, sessionId) )
{
csrRoamLinkUp(pMac, pSession->connectedProfile.bssid);
}
}
if( eSIR_SME_SUCCESS == pRsp->statusCode )
{
vos_mem_copy(&roamInfo.peerMac,
&pRsp->peerMacAddr, sizeof(tCsrBssid));
//Make sure we install the GTK before indicating to HDD as authenticated
//This is to prevent broadcast packets go out after PTK and before GTK.
if ( vos_mem_compare( &Broadcastaddr, pRsp->peerMacAddr,
sizeof(tSirMacAddr) ) )
{
#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
if(IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE)
{
tpSirSetActiveModeSetBncFilterReq pMsg;
pMsg = vos_mem_malloc(sizeof(tSirSetActiveModeSetBncFilterReq));
if (NULL == pMsg)
{
smsLog(pMac, LOGE, FL("vos_mem_malloc failed"));
return;
}
pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_SET_BCN_FILTER_REQ);
pMsg->length = pal_cpu_to_be16(sizeof(
tSirSetActiveModeSetBncFilterReq));
pMsg->seesionId = sessionId;
vos_mem_copy(pMsg->bssid,
pSession->connectedProfile.bssid,
sizeof(tSirMacAddr));
status = palSendMBMessage(pMac->hHdd, pMsg );
}
#endif
/* OBSS SCAN Indication will be sent to Firmware to start OBSS Scan */
if( CSR_IS_CHANNEL_24GHZ(pSession->connectedProfile.operationChannel)
&& IS_HT40_OBSS_SCAN_FEATURE_ENABLE
&& (pSession->connectState ==
eCSR_ASSOC_STATE_TYPE_INFRA_ASSOCIATED)
&& pSession->pCurRoamProfile
&& (VOS_P2P_GO_MODE !=
pSession->pCurRoamProfile->csrPersona
&& VOS_STA_SAP_MODE !=
pSession->pCurRoamProfile->csrPersona))
{
tpSirSmeHT40OBSSScanInd pMsg;
pMsg = vos_mem_malloc(sizeof(tSirSmeHT40OBSSScanInd));
if (NULL == pMsg)
{
smsLog(pMac, LOGE, FL("vos_mem_malloc failed"));
return;
}
pMsg->messageType =
pal_cpu_to_be16((tANI_U16)eWNI_SME_HT40_OBSS_SCAN_IND);
pMsg->length =
pal_cpu_to_be16(sizeof( tSirSmeHT40OBSSScanInd));
vos_mem_copy(pMsg->peerMacAddr,
pSession->connectedProfile.bssid,
sizeof(tSirMacAddr));
status = palSendMBMessage(pMac->hHdd,
pMsg );
}
else
{
smsLog( pMac, LOG1,FL("OBSS SCAN"
"Indication not sent to FW"
"channel %d OBSS_SCAN: %d"),
pSession->connectedProfile.
operationChannel,
IS_HT40_OBSS_SCAN_FEATURE_ENABLE);
smsLog( pMac, LOG1,FL("connectState %d"
"pCurRoamProfile %pK"),
pSession->connectState,
pSession->pCurRoamProfile);
}
result = eCSR_ROAM_RESULT_AUTHENTICATED;
}
else
{
result = eCSR_ROAM_RESULT_NONE;
}
pRoamInfo = &roamInfo;
}
else
{
result = eCSR_ROAM_RESULT_FAILURE;
smsLog(pMac, LOGE, "CSR: Roam Completion setkey "
"command failed(%d) PeerMac "MAC_ADDRESS_STR,
pRsp->statusCode, MAC_ADDR_ARRAY(pRsp->peerMacAddr));
}
roamInfo.is11rAssoc = csrRoamIs11rAssoc(pMac);
csrRoamCallCallback(pMac, sessionId, &roamInfo, pCommand->u.setKeyCmd.roamId,
eCSR_ROAM_SET_KEY_COMPLETE, result);
// Indicate SME_QOS that the SET_KEY is completed, so that SME_QOS
// can go ahead and initiate the TSPEC if any are pending
sme_QosCsrEventInd(pMac, (v_U8_t)sessionId, SME_QOS_CSR_SET_KEY_SUCCESS_IND, NULL);
#ifdef FEATURE_WLAN_ESE
//Send Adjacent AP repot to new AP.
if (result == eCSR_ROAM_RESULT_AUTHENTICATED &&
pSession->isPrevApInfoValid &&
pSession->connectedProfile.isESEAssoc)
{
#ifdef FEATURE_WLAN_ESE_UPLOAD
csrSendEseAdjacentApRepInd(pMac, pSession);
#else
csrEseSendAdjacentApRepMsg(pMac, pSession);
#endif
pSession->isPrevApInfoValid = FALSE;
}
#endif
if( csrLLRemoveEntry( &pMac->sme.smeCmdActiveList, pEntry, LL_ACCESS_LOCK ) )
{
csrReleaseCommandSetKey( pMac, pCommand );
}
}
else
{
smsLog( pMac, LOGE, "CSR: Roam Completion called but setkey command is not ACTIVE ..." );
}
}
else
{
smsLog( pMac, LOGE, "CSR: SetKey Completion called but NO commands are ACTIVE ..." );
}
smeProcessPendingQueue( pMac );
}
break;
case eWNI_SME_REMOVEKEY_RSP:
{
tSirSmeRemoveKeyRsp *pRsp = (tSirSmeRemoveKeyRsp *)pSirMsg;
tListElem *pEntry;
tSmeCmd *pCommand;
pEntry = csrLLPeekHead( &pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK );
if ( pEntry )
{
pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link );
if ( eSmeCommandRemoveKey == pCommand->command )
{
sessionId = pCommand->sessionId;
pSession = CSR_GET_SESSION( pMac, sessionId );
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return;
}
#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
{
WLAN_VOS_DIAG_EVENT_DEF(removeKeyEvent, vos_event_wlan_security_payload_type);
vos_mem_set(&removeKeyEvent,
sizeof(vos_event_wlan_security_payload_type), 0);
removeKeyEvent.eventId = WLAN_SECURITY_EVENT_REMOVE_KEY_RSP;
removeKeyEvent.encryptionModeMulticast =
(v_U8_t)diagEncTypeFromCSRType(pSession->connectedProfile.mcEncryptionType);
removeKeyEvent.encryptionModeUnicast =
(v_U8_t)diagEncTypeFromCSRType(pSession->connectedProfile.EncryptionType);
vos_mem_copy( removeKeyEvent.bssid,
pSession->connectedProfile.bssid, 6);
removeKeyEvent.authMode =
(v_U8_t)diagAuthTypeFromCSRType(pSession->connectedProfile.AuthType);
if( eSIR_SME_SUCCESS != pRsp->statusCode )
{
removeKeyEvent.status = WLAN_SECURITY_STATUS_FAILURE;
}
WLAN_VOS_DIAG_EVENT_REPORT(&removeKeyEvent, EVENT_WLAN_SECURITY);
}
#endif //FEATURE_WLAN_DIAG_SUPPORT_CSR
if( eSIR_SME_SUCCESS == pRsp->statusCode )
{
vos_mem_copy(&roamInfo.peerMac, &pRsp->peerMacAddr,
sizeof(tCsrBssid));
result = eCSR_ROAM_RESULT_NONE;
pRoamInfo = &roamInfo;
}
else
{
result = eCSR_ROAM_RESULT_FAILURE;
}
csrRoamCallCallback(pMac, sessionId, &roamInfo, pCommand->u.setKeyCmd.roamId,
eCSR_ROAM_REMOVE_KEY_COMPLETE, result);
if( csrLLRemoveEntry( &pMac->sme.smeCmdActiveList, pEntry, LL_ACCESS_LOCK ) )
{
csrReleaseCommandRemoveKey( pMac, pCommand );
}
}
else
{
smsLog( pMac, LOGW, "CSR: Roam Completion called but setkey command is not ACTIVE ..." );
}
}
else
{
smsLog( pMac, LOGW, "CSR: SetKey Completion called but NO commands are ACTIVE ..." );
}
smeProcessPendingQueue( pMac );
}
break;
case eWNI_SME_GET_STATISTICS_RSP:
smsLog( pMac, LOG2, FL("Stats rsp from PE"));
csrRoamStatsRspProcessor( pMac, pSirMsg );
break;
#if defined WLAN_FEATURE_VOWIFI_11R || defined FEATURE_WLAN_ESE || defined(FEATURE_WLAN_LFR)
case eWNI_SME_GET_ROAM_RSSI_RSP:
smsLog( pMac, LOG2, FL("Stats rsp from PE"));
csrRoamRssiRspProcessor( pMac, pSirMsg );
break;
#endif
#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
case eWNI_SME_GET_TSM_STATS_RSP:
smsLog( pMac, LOG2, FL("TSM Stats rsp from PE"));
csrTsmStatsRspProcessor( pMac, pSirMsg );
break;
#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
case eWNI_SME_GET_RSSI_REQ:
smsLog( pMac, LOG2, FL("GetRssiReq from self"));
csrUpdateRssi( pMac, pSirMsg );
break;
case eWNI_SME_GET_SNR_REQ:
smsLog( pMac, LOG2, FL("GetSnrReq from self"));
csrUpdateSnr(pMac, pSirMsg);
break;
#ifdef WLAN_FEATURE_VOWIFI_11R
case eWNI_SME_FT_PRE_AUTH_RSP:
csrRoamFTPreAuthRspProcessor( pMac, (tpSirFTPreAuthRsp)pSirMsg );
break;
#endif
#ifdef WLAN_FEATURE_LFR_MBB
case eWNI_SME_MBB_PRE_AUTH_REASSOC_RSP:
csr_roam_preauth_rsp_mbb_processor(pMac,
(tpSirFTPreAuthRsp)pSirMsg);
break;
#endif
case eWNI_SME_MAX_ASSOC_EXCEEDED:
pSmeMaxAssocInd = (tSmeMaxAssocInd*)pSirMsg;
smsLog( pMac, LOG1, FL("send indication that max assoc have been reached and the new peer cannot be accepted"));
sessionId = pSmeMaxAssocInd->sessionId;
roamInfo.sessionId = sessionId;
vos_mem_copy(&roamInfo.peerMac, pSmeMaxAssocInd->peerMac,
sizeof(tCsrBssid));
csrRoamCallCallback(pMac, sessionId, &roamInfo, 0,
eCSR_ROAM_INFRA_IND, eCSR_ROAM_RESULT_MAX_ASSOC_EXCEEDED);
break;
case eWNI_SME_BTAMP_LOG_LINK_IND:
smsLog( pMac, LOG1, FL("Establish logical link req from HCI serialized through MC thread"));
#ifdef WLAN_BTAMP_FEATURE
btampEstablishLogLinkHdlr( pSirMsg );
#endif
break;
case eWNI_SME_RSSI_IND:
smsLog( pMac, LOG1, FL("RSSI indication from TL serialized through MC thread"));
csrRoamRssiIndHdlr( pMac, pSirMsg );
break;
#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
case eWNI_SME_CANDIDATE_FOUND_IND:
smsLog( pMac, LOG2, FL("Candidate found indication from PE"));
csrNeighborRoamCandidateFoundIndHdlr( pMac, pSirMsg );
break;
case eWNI_SME_HANDOFF_REQ:
smsLog( pMac, LOG2, FL("Handoff Req from self"));
csrNeighborRoamHandoffReqHdlr( pMac, pSirMsg );
break;
#endif
default:
break;
} // end switch on message type
}
void csrCallRoamingCompletionCallback(tpAniSirGlobal pMac, tCsrRoamSession *pSession,
tCsrRoamInfo *pRoamInfo, tANI_U32 roamId, eCsrRoamResult roamResult)
{
if(pSession)
{
if(pSession->bRefAssocStartCnt)
{
pSession->bRefAssocStartCnt--;
VOS_ASSERT( pSession->bRefAssocStartCnt == 0);
//Need to call association_completion because there is an assoc_start pending.
csrRoamCallCallback(pMac, pSession->sessionId, NULL, roamId,
eCSR_ROAM_ASSOCIATION_COMPLETION,
eCSR_ROAM_RESULT_FAILURE);
}
csrRoamCallCallback(pMac, pSession->sessionId, pRoamInfo, roamId, eCSR_ROAM_ROAMING_COMPLETION, roamResult);
}
else
{
smsLog(pMac, LOGW, FL(" pSession is NULL"));
}
}
eHalStatus csrRoamStartRoaming(tpAniSirGlobal pMac, tANI_U32 sessionId, eCsrRoamingReason roamingReason)
{
eHalStatus status = eHAL_STATUS_FAILURE;
if(CSR_IS_LOSTLINK_ROAMING(roamingReason) &&
(eANI_BOOLEAN_FALSE == pMac->roam.roamSession[sessionId].fCancelRoaming))
{
status = csrScanRequestLostLink1( pMac, sessionId );
}
return(status);
}
//return a boolean to indicate whether roaming completed or continue.
tANI_BOOLEAN csrRoamCompleteRoaming(tpAniSirGlobal pMac, tANI_U32 sessionId,
tANI_BOOLEAN fForce, eCsrRoamResult roamResult)
{
tANI_BOOLEAN fCompleted = eANI_BOOLEAN_TRUE;
tANI_TIMESTAMP roamTime = (tANI_TIMESTAMP)(pMac->roam.configParam.nRoamingTime * PAL_TICKS_PER_SECOND);
tANI_TIMESTAMP curTime = (tANI_TIMESTAMP)palGetTickCount(pMac->hHdd);
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return eANI_BOOLEAN_FALSE;
}
//Check whether time is up
if(pSession->fCancelRoaming || fForce ||
((curTime - pSession->roamingStartTime) > roamTime) ||
eCsrReassocRoaming == pSession->roamingReason ||
eCsrDynamicRoaming == pSession->roamingReason)
{
smsLog(pMac, LOGW, FL(" indicates roaming completion"));
if(pSession->fCancelRoaming && CSR_IS_LOSTLINK_ROAMING(pSession->roamingReason))
{
//roaming is cancelled, tell HDD to indicate disconnect
//Because LIM overload deauth_ind for both deauth frame and missed beacon
//we need to use this logic to detinguish it. For missed beacon, LIM set reason
//to be eSIR_BEACON_MISSED
if(eSIR_BEACON_MISSED == pSession->roamingStatusCode)
{
roamResult = eCSR_ROAM_RESULT_LOSTLINK;
}
else if(eCsrLostlinkRoamingDisassoc == pSession->roamingReason)
{
roamResult = eCSR_ROAM_RESULT_DISASSOC_IND;
}
else if(eCsrLostlinkRoamingDeauth == pSession->roamingReason)
{
roamResult = eCSR_ROAM_RESULT_DEAUTH_IND;
}
else
{
roamResult = eCSR_ROAM_RESULT_LOSTLINK;
}
}
csrCallRoamingCompletionCallback(pMac, pSession, NULL, 0, roamResult);
pSession->roamingReason = eCsrNotRoaming;
}
else
{
pSession->roamResult = roamResult;
if(!HAL_STATUS_SUCCESS(csrRoamStartRoamingTimer(pMac, sessionId, PAL_TIMER_TO_SEC_UNIT)))
{
csrCallRoamingCompletionCallback(pMac, pSession, NULL, 0, roamResult);
pSession->roamingReason = eCsrNotRoaming;
}
else
{
fCompleted = eANI_BOOLEAN_FALSE;
}
}
return(fCompleted);
}
void csrRoamCancelRoaming(tpAniSirGlobal pMac, tANI_U32 sessionId)
{
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return;
}
if(CSR_IS_ROAMING(pSession))
{
smsLog(pMac, LOGW, " Cancelling roaming");
pSession->fCancelRoaming = eANI_BOOLEAN_TRUE;
if(CSR_IS_ROAM_JOINING(pMac, sessionId) && CSR_IS_ROAM_SUBSTATE_CONFIG(pMac, sessionId))
{
//No need to do anything in here because the handler takes care of it
}
else
{
eCsrRoamResult roamResult = CSR_IS_LOSTLINK_ROAMING(pSession->roamingReason) ?
eCSR_ROAM_RESULT_LOSTLINK : eCSR_ROAM_RESULT_NONE;
//Roaming is stopped after here
csrRoamCompleteRoaming(pMac, sessionId, eANI_BOOLEAN_TRUE, roamResult);
//Since CSR may be in lostlink roaming situation, abort all roaming related activities
csrScanAbortMacScan(pMac, sessionId, eCSR_SCAN_ABORT_DEFAULT);
csrRoamStopRoamingTimer(pMac, sessionId);
}
}
}
void csrRoamRoamingTimerHandler(void *pv)
{
tCsrTimerInfo *pInfo = (tCsrTimerInfo *)pv;
tpAniSirGlobal pMac = pInfo->pMac;
tANI_U32 sessionId = pInfo->sessionId;
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return;
}
if(eANI_BOOLEAN_FALSE == pSession->fCancelRoaming)
{
if(!HAL_STATUS_SUCCESS(csrRoamStartRoaming(pMac, sessionId, pSession->roamingReason)))
{
csrCallRoamingCompletionCallback(pMac, pSession, NULL, 0, pSession->roamResult);
pSession->roamingReason = eCsrNotRoaming;
}
}
}
eHalStatus csrRoamStartRoamingTimer(tpAniSirGlobal pMac, tANI_U32 sessionId, tANI_U32 interval)
{
eHalStatus status;
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found"), sessionId);
return eHAL_STATUS_FAILURE;
}
smsLog(pMac, LOG1, " csrScanStartRoamingTimer");
pSession->roamingTimerInfo.sessionId = (tANI_U8)sessionId;
status = vos_timer_start(&pSession->hTimerRoaming, interval/PAL_TIMER_TO_MS_UNIT);
return (status);
}
eHalStatus csrRoamStopRoamingTimer(tpAniSirGlobal pMac, tANI_U32 sessionId)
{
return (vos_timer_stop(&pMac->roam.roamSession[sessionId].hTimerRoaming));
}
void csrRoamWaitForKeyTimeOutHandler(void *pv)
{
tCsrTimerInfo *pInfo = (tCsrTimerInfo *)pv;
tpAniSirGlobal pMac = pInfo->pMac;
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, pInfo->sessionId );
eHalStatus status = eHAL_STATUS_FAILURE;
smsLog(pMac, LOGE, FL("WaitForKey timer expired in state=%s sub-state=%s"),
macTraceGetNeighbourRoamState(
pMac->roam.neighborRoamInfo.neighborRoamState),
macTraceGetcsrRoamSubState(
pMac->roam.curSubState[pInfo->sessionId]));
if (pSession)
{
vos_spin_lock_acquire(&pMac->roam.roam_state_lock);
if( CSR_IS_WAIT_FOR_KEY( pMac, pInfo->sessionId ) )
{
//Change the substate so command queue is unblocked.
if (CSR_ROAM_SESSION_MAX > pInfo->sessionId)
pMac->roam.curSubState[pInfo->sessionId] =
eCSR_ROAM_SUBSTATE_NONE;
vos_spin_lock_release(&pMac->roam.roam_state_lock);
#ifdef FEATURE_WLAN_LFR
if (csrNeighborRoamIsHandoffInProgress(pMac))
{
/*
* Enable heartbeat timer when hand-off is in progress
* and Key Wait timer expired.
*/
smsLog(pMac, LOG2, "Enabling HB timer after WaitKey expiry"
" (nHBCount=%d)",
pMac->roam.configParam.HeartbeatThresh24);
ccmCfgSetInt(pMac, WNI_CFG_HEART_BEAT_THRESHOLD,
pMac->roam.configParam.HeartbeatThresh24,
NULL, eANI_BOOLEAN_FALSE);
}
#endif
smsLog(pMac, LOGE, " SME pre-auth state timeout. ");
if( csrIsConnStateConnectedInfra(pMac, pInfo->sessionId) )
{
csrRoamLinkUp(pMac, pSession->connectedProfile.bssid);
smeProcessPendingQueue(pMac);
status = sme_AcquireGlobalLock(&pMac->sme);
if (HAL_STATUS_SUCCESS(status))
{
csrRoamDisconnect(pMac, pInfo->sessionId,
eCSR_DISCONNECT_REASON_UNSPECIFIED);
sme_ReleaseGlobalLock(&pMac->sme);
}
}
else
{
smsLog(pMac, LOGE, FL("Session id %d is disconnected"),
pInfo->sessionId);
}
}
else
{
vos_spin_lock_release(&pMac->roam.roam_state_lock);
smsLog(pMac, LOGW, "%s: session not found", __func__);
}
}
}
eHalStatus csrRoamStartWaitForKeyTimer(tpAniSirGlobal pMac, tANI_U32 interval)
{
eHalStatus status;
#ifdef FEATURE_WLAN_LFR
if (csrNeighborRoamIsHandoffInProgress(pMac))
{
/* Disable heartbeat timer when hand-off is in progress */
smsLog(pMac, LOG2, FL("disabling HB timer in state=%s sub-state=%s"),
macTraceGetNeighbourRoamState(
pMac->roam.neighborRoamInfo.neighborRoamState),
macTraceGetcsrRoamSubState(
pMac->roam.curSubState[pMac->roam.WaitForKeyTimerInfo.sessionId]
));
ccmCfgSetInt(pMac, WNI_CFG_HEART_BEAT_THRESHOLD, 0, NULL, eANI_BOOLEAN_FALSE);
}
#endif
smsLog(pMac, LOG1, " csrScanStartWaitForKeyTimer");
status = vos_timer_start(&pMac->roam.hTimerWaitForKey, interval/PAL_TIMER_TO_MS_UNIT);
return (status);
}
eHalStatus csrRoamStopWaitForKeyTimer(tpAniSirGlobal pMac)
{
smsLog(pMac, LOG2, FL("WaitForKey timer stopped in state=%s sub-state=%s"),
macTraceGetNeighbourRoamState(
pMac->roam.neighborRoamInfo.neighborRoamState),
macTraceGetcsrRoamSubState(
pMac->roam.curSubState[pMac->roam.WaitForKeyTimerInfo.sessionId]));
#ifdef FEATURE_WLAN_LFR
if (csrNeighborRoamIsHandoffInProgress(pMac))
{
/*
* Enable heartbeat timer when hand-off is in progress
* and Key Wait timer got stopped for some reason
*/
smsLog(pMac, LOG2, "Enabling HB timer after WaitKey stop"
" (nHBCount=%d)",
pMac->roam.configParam.HeartbeatThresh24);
ccmCfgSetInt(pMac, WNI_CFG_HEART_BEAT_THRESHOLD,
pMac->roam.configParam.HeartbeatThresh24,
NULL, eANI_BOOLEAN_FALSE);
}
#endif
return (vos_timer_stop(&pMac->roam.hTimerWaitForKey));
}
void csrRoamCompletion(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamInfo *pRoamInfo, tSmeCmd *pCommand,
eCsrRoamResult roamResult, tANI_BOOLEAN fSuccess)
{
eRoamCmdStatus roamStatus = csrGetRoamCompleteStatus(pMac, sessionId);
tANI_U32 roamId = 0;
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
/* To silence the KW tool Null chaeck is added */
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return;
}
if(pCommand)
{
roamId = pCommand->u.roamCmd.roamId;
VOS_ASSERT( sessionId == pCommand->sessionId );
}
if(eCSR_ROAM_ROAMING_COMPLETION == roamStatus)
{
//if success, force roaming completion
csrRoamCompleteRoaming(pMac, sessionId, fSuccess, roamResult);
}
else
{
VOS_ASSERT(pSession->bRefAssocStartCnt == 0);
smsLog(pMac, LOGW, FL(" indicates association completion. roamResult = %d"), roamResult);
csrRoamCallCallback(pMac, sessionId, pRoamInfo, roamId, roamStatus, roamResult);
}
}
eHalStatus csrRoamLostLink( tpAniSirGlobal pMac, tANI_U32 sessionId, tANI_U32 type, tSirSmeRsp *pSirMsg)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tSirSmeDeauthInd *pDeauthIndMsg = NULL;
tSirSmeDisassocInd *pDisassocIndMsg = NULL;
eCsrRoamResult result = eCSR_ROAM_RESULT_LOSTLINK;
tCsrRoamInfo roamInfo;
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
/* To silence the KW tool Null chaeck is added */
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return eHAL_STATUS_FAILURE;
}
pSession->fCancelRoaming = eANI_BOOLEAN_FALSE;
vos_mem_set(&roamInfo, sizeof(tCsrRoamInfo), 0);
if ( eWNI_SME_DISASSOC_IND == type )
{
result = eCSR_ROAM_RESULT_DISASSOC_IND;
pDisassocIndMsg = (tSirSmeDisassocInd *)pSirMsg;
pSession->roamingStatusCode = pDisassocIndMsg->statusCode;
pSession->joinFailStatusCode.reasonCode = pDisassocIndMsg->reasonCode;
vos_mem_copy(roamInfo.peerMac, pDisassocIndMsg->peerMacAddr,
sizeof(tSirMacAddr));
roamInfo.staId = (tANI_U8)pDisassocIndMsg->staId;
}
else if ( eWNI_SME_DEAUTH_IND == type )
{
result = eCSR_ROAM_RESULT_DEAUTH_IND;
pDeauthIndMsg = (tSirSmeDeauthInd *)pSirMsg;
pSession->roamingStatusCode = pDeauthIndMsg->statusCode;
pSession->joinFailStatusCode.reasonCode = pDeauthIndMsg->reasonCode;
vos_mem_copy(roamInfo.peerMac, pDeauthIndMsg->peerMacAddr,
sizeof(tSirMacAddr));
roamInfo.staId = (tANI_U8)pDeauthIndMsg->staId;
}
else
{
smsLog(pMac, LOGW, FL("gets an unknown type (%d)"), type);
result = eCSR_ROAM_RESULT_NONE;
pSession->joinFailStatusCode.reasonCode = 1;
}
roamInfo.statusCode = (tSirResultCodes)pSession->roamingStatusCode;
roamInfo.reasonCode = pSession->joinFailStatusCode.reasonCode;
smsLog(pMac, LOGW, FL("roamInfo.staId (%d)"), roamInfo.staId);
if (type == eWNI_SME_DEAUTH_IND || type == eWNI_SME_DISASSOC_IND) {
csrRoamCallCallback(pMac, sessionId, &roamInfo, 0,
eCSR_ROAM_LOSTLINK_DETECTED, result);
} else if(!CSR_IS_INFRA_AP(&pSession->connectedProfile)) {
csrRoamCallCallback(pMac, sessionId, NULL, 0,
eCSR_ROAM_LOSTLINK_DETECTED, result);
}
if ( eWNI_SME_DISASSOC_IND == type )
{
status = csrSendMBDisassocCnfMsg(pMac, pDisassocIndMsg);
}
else if ( eWNI_SME_DEAUTH_IND == type )
{
status = csrSendMBDeauthCnfMsg(pMac, pDeauthIndMsg);
}
if(CSR_IS_INFRASTRUCTURE(&pSession->connectedProfile))
{
//remove the connected BSS in infrastructure mode
csrRoamRemoveConnectedBssFromScanCache(pMac,
&pSession->connectedProfile);
csrScanStartIdleScan(pMac);
}
return (status);
}
eHalStatus csrRoamLostLinkAfterhandoffFailure( tpAniSirGlobal pMac,tANI_U32 sessionId)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tListElem *pEntry = NULL;
tSmeCmd *pCommand = NULL;
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return eHAL_STATUS_FAILURE;
}
pSession->fCancelRoaming = eANI_BOOLEAN_FALSE;
//Only remove the connected BSS in infrastructure mode
csrRoamRemoveConnectedBssFromScanCache(pMac, &pSession->connectedProfile);
if(pMac->roam.configParam.nRoamingTime)
{
if(HAL_STATUS_SUCCESS(status = csrRoamStartRoaming(pMac,sessionId, pSession->roamingReason)))
{
//before starting the lost link logic release the roam command for handoff
pEntry = csrLLPeekHead(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK);
if(pEntry)
{
pCommand = GET_BASE_ADDR(pEntry, tSmeCmd, Link);
}
if(pCommand)
{
if (( eSmeCommandRoam == pCommand->command ) &&
( eCsrSmeIssuedAssocToSimilarAP == pCommand->u.roamCmd.roamReason))
{
if( csrLLRemoveEntry( &pMac->sme.smeCmdActiveList, pEntry, LL_ACCESS_LOCK ) )
{
csrReleaseCommandRoam( pMac, pCommand );
}
}
}
smsLog( pMac, LOGW, "Lost link roaming started ...");
}
}
else
{
//We are told not to roam, indicate lostlink
status = eHAL_STATUS_FAILURE;
}
return (status);
}
void csrRoamWmStatusChangeComplete( tpAniSirGlobal pMac )
{
tListElem *pEntry;
tSmeCmd *pCommand;
pEntry = csrLLPeekHead( &pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK );
if ( pEntry )
{
pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link );
if ( eSmeCommandWmStatusChange == pCommand->command )
{
// Nothing to process in a Lost Link completion.... It just kicks off a
// roaming sequence.
if( csrLLRemoveEntry( &pMac->sme.smeCmdActiveList, pEntry, LL_ACCESS_LOCK ) )
{
csrReleaseCommandWmStatusChange( pMac, pCommand );
}
else
{
smsLog( pMac, LOGE, " ******csrRoamWmStatusChangeComplete fail to release command");
}
}
else
{
smsLog( pMac, LOGW, "CSR: WmStatusChange Completion called but LOST LINK command is not ACTIVE ..." );
}
}
else
{
smsLog( pMac, LOGW, "CSR: WmStatusChange Completion called but NO commands are ACTIVE ..." );
}
smeProcessPendingQueue( pMac );
}
void csrRoamProcessWmStatusChangeCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand )
{
eHalStatus status = eHAL_STATUS_FAILURE;
tSirSmeRsp *pSirSmeMsg;
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, pCommand->sessionId );
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), pCommand->sessionId);
return;
}
smsLog(pMac, LOG1, FL("session:%d, CmdType : %d"),
pCommand->sessionId,
pCommand->u.wmStatusChangeCmd.Type);
switch ( pCommand->u.wmStatusChangeCmd.Type )
{
case eCsrDisassociated:
pSirSmeMsg = (tSirSmeRsp *)&pCommand->u.wmStatusChangeCmd.u.DisassocIndMsg;
status = csrRoamLostLink(pMac, pCommand->sessionId, eWNI_SME_DISASSOC_IND, pSirSmeMsg);
break;
case eCsrDeauthenticated:
pSirSmeMsg = (tSirSmeRsp *)&pCommand->u.wmStatusChangeCmd.u.DeauthIndMsg;
status = csrRoamLostLink(pMac, pCommand->sessionId, eWNI_SME_DEAUTH_IND, pSirSmeMsg);
break;
default:
smsLog(pMac, LOGW, FL("gets an unknown command %d"), pCommand->u.wmStatusChangeCmd.Type);
break;
}
//For WDS, we want to stop BSS as well when it is indicated that it is disconnected.
if( CSR_IS_CONN_WDS(&pSession->connectedProfile) )
{
if( !HAL_STATUS_SUCCESS(csrRoamIssueStopBssCmd( pMac, pCommand->sessionId, eANI_BOOLEAN_TRUE )) )
{
//This is not good
smsLog(pMac, LOGE, FL(" failed to issue stopBSS command"));
}
}
// Lost Link just triggers a roaming sequence. We can complte the Lost Link
// command here since there is nothing else to do.
csrRoamWmStatusChangeComplete( pMac );
}
//This function returns band and mode information.
//The only tricky part is that if phyMode is set to 11abg, this function may return eCSR_CFG_DOT11_MODE_11B
//instead of eCSR_CFG_DOT11_MODE_11G if everything is set to auto-pick.
static eCsrCfgDot11Mode csrRoamGetPhyModeBandForBss( tpAniSirGlobal pMac, tCsrRoamProfile *pProfile,
tANI_U8 operationChn, eCsrBand *pBand )
{
eCsrPhyMode phyModeIn = (eCsrPhyMode)pProfile->phyMode;
eCsrCfgDot11Mode cfgDot11Mode = csrGetCfgDot11ModeFromCsrPhyMode(pProfile, phyModeIn,
pMac->roam.configParam.ProprietaryRatesEnabled);
eCsrBand eBand;
//If the global setting for dot11Mode is set to auto/abg, we overwrite the setting in the profile.
if( ((!CSR_IS_INFRA_AP(pProfile )&& !CSR_IS_WDS(pProfile )) &&
((eCSR_CFG_DOT11_MODE_AUTO == pMac->roam.configParam.uCfgDot11Mode) ||
(eCSR_CFG_DOT11_MODE_ABG == pMac->roam.configParam.uCfgDot11Mode))) ||
(eCSR_CFG_DOT11_MODE_AUTO == cfgDot11Mode) || (eCSR_CFG_DOT11_MODE_ABG == cfgDot11Mode) )
{
switch( pMac->roam.configParam.uCfgDot11Mode )
{
case eCSR_CFG_DOT11_MODE_11A:
cfgDot11Mode = eCSR_CFG_DOT11_MODE_11A;
eBand = eCSR_BAND_5G;
break;
case eCSR_CFG_DOT11_MODE_11B:
cfgDot11Mode = eCSR_CFG_DOT11_MODE_11B;
eBand = eCSR_BAND_24;
break;
case eCSR_CFG_DOT11_MODE_11G:
cfgDot11Mode = eCSR_CFG_DOT11_MODE_11G;
eBand = eCSR_BAND_24;
break;
case eCSR_CFG_DOT11_MODE_11N:
cfgDot11Mode = eCSR_CFG_DOT11_MODE_11N;
eBand = CSR_IS_CHANNEL_24GHZ(operationChn) ? eCSR_BAND_24 : eCSR_BAND_5G;
break;
#ifdef WLAN_FEATURE_11AC
case eCSR_CFG_DOT11_MODE_11AC:
if (IS_FEATURE_SUPPORTED_BY_FW(DOT11AC))
{
/* If the operating channel is in 2.4 GHz band, check for
* INI item to disable VHT operation in 2.4 GHz band
*/
if (CSR_IS_CHANNEL_24GHZ(operationChn) &&
!pMac->roam.configParam.enableVhtFor24GHz)
{
/* Disable 11AC operation */
cfgDot11Mode = eCSR_CFG_DOT11_MODE_11N;
}
else
{
cfgDot11Mode = eCSR_CFG_DOT11_MODE_11AC;
}
eBand = CSR_IS_CHANNEL_24GHZ(operationChn) ? eCSR_BAND_24 : eCSR_BAND_5G;
}
else
{
cfgDot11Mode = eCSR_CFG_DOT11_MODE_11N;
eBand = CSR_IS_CHANNEL_24GHZ(operationChn) ? eCSR_BAND_24 : eCSR_BAND_5G;
}
break;
case eCSR_CFG_DOT11_MODE_11AC_ONLY:
if (IS_FEATURE_SUPPORTED_BY_FW(DOT11AC))
{
/* If the operating channel is in 2.4 GHz band, check for
* INI item to disable VHT operation in 2.4 GHz band
*/
if (CSR_IS_CHANNEL_24GHZ(operationChn) &&
!pMac->roam.configParam.enableVhtFor24GHz)
{
/* Disable 11AC operation */
cfgDot11Mode = eCSR_CFG_DOT11_MODE_11N;
}
else
{
cfgDot11Mode = eCSR_CFG_DOT11_MODE_11AC_ONLY;
}
eBand = CSR_IS_CHANNEL_24GHZ(operationChn) ? eCSR_BAND_24 : eCSR_BAND_5G;
}
else
{
eBand = CSR_IS_CHANNEL_24GHZ(operationChn) ? eCSR_BAND_24 : eCSR_BAND_5G;
cfgDot11Mode = eCSR_CFG_DOT11_MODE_11N;
}
break;
#endif
case eCSR_CFG_DOT11_MODE_AUTO:
#ifdef WLAN_FEATURE_11AC
if (IS_FEATURE_SUPPORTED_BY_FW(DOT11AC))
{
/* If the operating channel is in 2.4 GHz band, check for
* INI item to disable VHT operation in 2.4 GHz band
*/
if (CSR_IS_CHANNEL_24GHZ(operationChn) &&
!pMac->roam.configParam.enableVhtFor24GHz)
{
/* Disable 11AC operation */
cfgDot11Mode = eCSR_CFG_DOT11_MODE_11N;
}
else
{
cfgDot11Mode = eCSR_CFG_DOT11_MODE_11AC;
}
eBand = CSR_IS_CHANNEL_24GHZ(operationChn) ? eCSR_BAND_24 : eCSR_BAND_5G;
}
else
{
cfgDot11Mode = eCSR_CFG_DOT11_MODE_11N;
eBand = CSR_IS_CHANNEL_24GHZ(operationChn) ? eCSR_BAND_24 : eCSR_BAND_5G;
}
#else
cfgDot11Mode = eCSR_CFG_DOT11_MODE_11N;
eBand = CSR_IS_CHANNEL_24GHZ(operationChn) ? eCSR_BAND_24 : eCSR_BAND_5G;
#endif
break;
default:
// Global dot11 Mode setting is 11a/b/g.
// use the channel number to determine the Mode setting.
if ( eCSR_OPERATING_CHANNEL_AUTO == operationChn )
{
eBand = pMac->roam.configParam.eBand;
if(eCSR_BAND_24 == eBand)
{
//See reason in else if ( CSR_IS_CHANNEL_24GHZ(operationChn) ) to pick 11B
cfgDot11Mode = eCSR_CFG_DOT11_MODE_11B;
}
else
{
//prefer 5GHz
eBand = eCSR_BAND_5G;
cfgDot11Mode = eCSR_CFG_DOT11_MODE_11A;
}
}
else if ( CSR_IS_CHANNEL_24GHZ(operationChn) )
{
// WiFi tests require IBSS networks to start in 11b mode
// without any change to the default parameter settings
// on the adapter. We use ACU to start an IBSS through
// creation of a startIBSS profile. This startIBSS profile
// has Auto MACProtocol and the adapter property setting
// for dot11Mode is also AUTO. So in this case, let's
// start the IBSS network in 11b mode instead of 11g mode.
// So this is for Auto=profile->MacProtocol && Auto=Global.
// dot11Mode && profile->channel is < 14, then start the IBSS
// in b mode.
//
// Note: we used to have this start as an 11g IBSS for best
// performance... now to specify that the user will have to
// set the do11Mode in the property page to 11g to force it.
cfgDot11Mode = eCSR_CFG_DOT11_MODE_11B;
eBand = eCSR_BAND_24;
}
else
{
// else, it's a 5.0GHz channel. Set mode to 11a.
cfgDot11Mode = eCSR_CFG_DOT11_MODE_11A;
eBand = eCSR_BAND_5G;
}
break;
}//switch
}//if( eCSR_CFG_DOT11_MODE_ABG == cfgDot11Mode )
else
{
//dot11 mode is set, lets pick the band
if ( eCSR_OPERATING_CHANNEL_AUTO == operationChn )
{
// channel is Auto also.
eBand = pMac->roam.configParam.eBand;
if(eCSR_BAND_ALL == eBand)
{
//prefer 5GHz
eBand = eCSR_BAND_5G;
}
}
else if ( CSR_IS_CHANNEL_24GHZ(operationChn) )
{
eBand = eCSR_BAND_24;
}
else
{
eBand = eCSR_BAND_5G;
}
}
if(pBand)
{
*pBand = eBand;
}
if (operationChn == 14){
smsLog(pMac, LOGE, FL(" Switching to Dot11B mode "));
cfgDot11Mode = eCSR_CFG_DOT11_MODE_11B;
}
/* Incase of WEP Security encryption type is coming as part of add key. So while STart BSS dont have information */
if (
#ifdef SAP_AUTH_OFFLOAD
(!pMac->sap_auth_offload && !pMac->sap_auth_offload_sec_type) &&
#endif
((!CSR_IS_11n_ALLOWED(pProfile->EncryptionType.encryptionType[0] ) ||
((pProfile->privacy == 1) &&
(pProfile->EncryptionType.encryptionType[0] == eCSR_ENCRYPT_TYPE_NONE)))) &&
((eCSR_CFG_DOT11_MODE_11N == cfgDot11Mode) ||
#ifdef WLAN_FEATURE_11AC
(eCSR_CFG_DOT11_MODE_11AC == cfgDot11Mode) ||
#endif
(eCSR_CFG_DOT11_MODE_TAURUS == cfgDot11Mode)) )
{
//We cannot do 11n here
if ( CSR_IS_CHANNEL_24GHZ(operationChn) )
{
cfgDot11Mode = eCSR_CFG_DOT11_MODE_11G;
}
else
{
cfgDot11Mode = eCSR_CFG_DOT11_MODE_11A;
}
}
return( cfgDot11Mode );
}
eHalStatus csrRoamIssueStopBss( tpAniSirGlobal pMac, tANI_U32 sessionId, eCsrRoamSubState NewSubstate )
{
eHalStatus status;
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return eHAL_STATUS_FAILURE;
}
#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
{
vos_log_ibss_pkt_type *pIbssLog;
WLAN_VOS_DIAG_LOG_ALLOC(pIbssLog, vos_log_ibss_pkt_type, LOG_WLAN_IBSS_C);
if(pIbssLog)
{
pIbssLog->eventId = WLAN_IBSS_EVENT_STOP_REQ;
WLAN_VOS_DIAG_LOG_REPORT(pIbssLog);
}
}
#endif //FEATURE_WLAN_DIAG_SUPPORT_CSR
// Set the roaming substate to 'stop Bss request'...
csrRoamSubstateChange( pMac, NewSubstate, sessionId );
// attempt to stop the Bss (reason code is ignored...)
status = csrSendMBStopBssReqMsg( pMac, sessionId );
if(!HAL_STATUS_SUCCESS(status))
{
smsLog(pMac, LOGW, FL("csrSendMBStopBssReqMsg failed with status %d"), status);
}
return (status);
}
//pNumChan is a caller allocated space with the sizeof pChannels
eHalStatus csrGetCfgValidChannels(tpAniSirGlobal pMac, tANI_U8 *pChannels, tANI_U32 *pNumChan)
{
return (ccmCfgGetStr(pMac, WNI_CFG_VALID_CHANNEL_LIST,
(tANI_U8 *)pChannels,
pNumChan));
}
tPowerdBm csrGetCfgMaxTxPower (tpAniSirGlobal pMac, tANI_U8 channel)
{
tANI_U32 cfgLength = 0;
tANI_U16 cfgId = 0;
tPowerdBm maxTxPwr = 0;
tANI_U8 *pCountryInfo = NULL;
eHalStatus status;
tANI_U8 count = 0;
tANI_U8 firstChannel;
tANI_U8 maxChannels;
if (CSR_IS_CHANNEL_5GHZ(channel))
{
cfgId = WNI_CFG_MAX_TX_POWER_5;
cfgLength = WNI_CFG_MAX_TX_POWER_5_LEN;
}
else if (CSR_IS_CHANNEL_24GHZ(channel))
{
cfgId = WNI_CFG_MAX_TX_POWER_2_4;
cfgLength = WNI_CFG_MAX_TX_POWER_2_4_LEN;
}
else
return maxTxPwr;
pCountryInfo = vos_mem_malloc(cfgLength);
if ( NULL == pCountryInfo )
status = eHAL_STATUS_FAILURE;
else
status = eHAL_STATUS_SUCCESS;
if (status != eHAL_STATUS_SUCCESS)
{
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
FL("%s: failed to allocate memory, status = %d"),
__FUNCTION__, status);
goto error;
}
status = ccmCfgGetStr(pMac, cfgId, (tANI_U8 *)pCountryInfo, &cfgLength);
if (status != eHAL_STATUS_SUCCESS)
{
goto error;
}
/* Identify the channel and maxtxpower */
while (count <= (cfgLength - (sizeof(tSirMacChanInfo))))
{
firstChannel = pCountryInfo[count++];
maxChannels = pCountryInfo[count++];
maxTxPwr = pCountryInfo[count++];
if ((channel >= firstChannel) &&
(channel < (firstChannel + maxChannels)))
{
break;
}
}
error:
if (NULL != pCountryInfo)
vos_mem_free(pCountryInfo);
return maxTxPwr;
}
tANI_BOOLEAN csrRoamIsChannelValid( tpAniSirGlobal pMac, tANI_U8 channel )
{
tANI_BOOLEAN fValid = FALSE;
tANI_U32 idxValidChannels;
tANI_U32 len = sizeof(pMac->roam.validChannelList);
if (HAL_STATUS_SUCCESS(csrGetCfgValidChannels(pMac, pMac->roam.validChannelList, &len)))
{
for ( idxValidChannels = 0; ( idxValidChannels < len ); idxValidChannels++ )
{
if ( channel == pMac->roam.validChannelList[ idxValidChannels ] )
{
fValid = TRUE;
break;
}
}
}
pMac->roam.numValidChannels = len;
return fValid;
}
tANI_BOOLEAN csrRoamIsValid40MhzChannel(tpAniSirGlobal pMac, tANI_U8 channel)
{
tANI_BOOLEAN fValid = eANI_BOOLEAN_FALSE;
tANI_U8 i;
for(i = 0; i < pMac->scan.base40MHzChannels.numChannels; i++)
{
if(channel == pMac->scan.base40MHzChannels.channelList[i])
{
fValid = eANI_BOOLEAN_TRUE;
break;
}
}
return (fValid);
}
//This function check and validate whether the NIC can do CB (40MHz)
static ePhyChanBondState csrGetCBModeFromIes(tpAniSirGlobal pMac, tANI_U8 primaryChn, tDot11fBeaconIEs *pIes)
{
ePhyChanBondState eRet = PHY_SINGLE_CHANNEL_CENTERED;
tANI_U8 centerChn;
tANI_U32 ChannelBondingMode;
if(CSR_IS_CHANNEL_24GHZ(primaryChn))
{
ChannelBondingMode = pMac->roam.configParam.channelBondingMode24GHz;
}
else
{
ChannelBondingMode = pMac->roam.configParam.channelBondingMode5GHz;
}
//Figure what the other side's CB mode
if(WNI_CFG_CHANNEL_BONDING_MODE_DISABLE != ChannelBondingMode)
{
if(pIes->HTCaps.present && (eHT_CHANNEL_WIDTH_40MHZ == pIes->HTCaps.supportedChannelWidthSet))
{
// In Case WPA2 and TKIP is the only one cipher suite in Pairwise.
if ((pIes->RSN.present && (pIes->RSN.pwise_cipher_suite_count == 1) &&
!memcmp(&(pIes->RSN.pwise_cipher_suites[0][0]),
"\x00\x0f\xac\x02",4))
//In Case only WPA1 is supported and TKIP is the only one cipher suite in Unicast.
||( !pIes->RSN.present && (pIes->WPA.present && (pIes->WPA.unicast_cipher_count == 1) &&
!memcmp(&(pIes->WPA.unicast_ciphers[0][0]),
"\x00\x50\xf2\x02",4))))
{
smsLog(pMac, LOGW, " No channel bonding in TKIP mode ");
eRet = PHY_SINGLE_CHANNEL_CENTERED;
}
else if(pIes->HTInfo.present)
{
/* This is called during INFRA STA/CLIENT and should use the merged value of
* supported channel width and recommended tx width as per standard
*/
smsLog(pMac, LOG1, "scws %u rtws %u sco %u",
pIes->HTCaps.supportedChannelWidthSet,
pIes->HTInfo.recommendedTxWidthSet,
pIes->HTInfo.secondaryChannelOffset);
if (pIes->HTInfo.recommendedTxWidthSet == eHT_CHANNEL_WIDTH_40MHZ)
eRet = (ePhyChanBondState)pIes->HTInfo.secondaryChannelOffset;
else
eRet = PHY_SINGLE_CHANNEL_CENTERED;
switch (eRet) {
case PHY_DOUBLE_CHANNEL_LOW_PRIMARY:
centerChn = primaryChn + CSR_CB_CENTER_CHANNEL_OFFSET;
break;
case PHY_DOUBLE_CHANNEL_HIGH_PRIMARY:
centerChn = primaryChn - CSR_CB_CENTER_CHANNEL_OFFSET;
break;
case PHY_SINGLE_CHANNEL_CENTERED:
default:
centerChn = primaryChn;
break;
}
if((PHY_SINGLE_CHANNEL_CENTERED != eRet) && !csrRoamIsValid40MhzChannel(pMac, centerChn))
{
smsLog(pMac, LOGE, " Invalid center channel (%d), disable 40MHz mode", centerChn);
eRet = PHY_SINGLE_CHANNEL_CENTERED;
}
if ((CSR_IS_CHANNEL_24GHZ(primaryChn))&& !IS_HT40_OBSS_SCAN_FEATURE_ENABLE)
{
smsLog(pMac, LOG1,FL("FW doesn't support channelBondingMode24GHz"));
eRet = PHY_SINGLE_CHANNEL_CENTERED;
}
}
}
}
return eRet;
}
tANI_BOOLEAN csrIsEncryptionInList( tpAniSirGlobal pMac, tCsrEncryptionList *pCipherList, eCsrEncryptionType encryptionType )
{
tANI_BOOLEAN fFound = FALSE;
tANI_U32 idx;
for( idx = 0; idx < pCipherList->numEntries; idx++ )
{
if( pCipherList->encryptionType[idx] == encryptionType )
{
fFound = TRUE;
break;
}
}
return fFound;
}
tANI_BOOLEAN csrIsAuthInList( tpAniSirGlobal pMac, tCsrAuthList *pAuthList, eCsrAuthType authType )
{
tANI_BOOLEAN fFound = FALSE;
tANI_U32 idx;
for( idx = 0; idx < pAuthList->numEntries; idx++ )
{
if( pAuthList->authType[idx] == authType )
{
fFound = TRUE;
break;
}
}
return fFound;
}
tANI_BOOLEAN csrIsSameProfile(tpAniSirGlobal pMac, tCsrRoamConnectedProfile *pProfile1, tCsrRoamProfile *pProfile2)
{
tANI_BOOLEAN fCheck = eANI_BOOLEAN_FALSE;
tCsrScanResultFilter *pScanFilter = NULL;
eHalStatus status = eHAL_STATUS_SUCCESS;
if(pProfile1 && pProfile2)
{
pScanFilter = vos_mem_malloc(sizeof(tCsrScanResultFilter));
if ( NULL == pScanFilter )
status = eHAL_STATUS_FAILURE;
else
status = eHAL_STATUS_SUCCESS;
if(HAL_STATUS_SUCCESS(status))
{
vos_mem_set(pScanFilter, sizeof(tCsrScanResultFilter), 0);
status = csrRoamPrepareFilterFromProfile(pMac, pProfile2, pScanFilter);
if(HAL_STATUS_SUCCESS(status))
{
fCheck = eANI_BOOLEAN_FALSE;
do
{
tANI_U32 i;
for(i = 0; i < pScanFilter->SSIDs.numOfSSIDs; i++)
{
fCheck = csrIsSsidMatch( pMac, pScanFilter->SSIDs.SSIDList[i].SSID.ssId,
pScanFilter->SSIDs.SSIDList[i].SSID.length,
pProfile1->SSID.ssId, pProfile1->SSID.length, eANI_BOOLEAN_FALSE );
if ( fCheck ) break;
}
if(!fCheck)
{
break;
}
if( !csrIsAuthInList( pMac, &pProfile2->AuthType, pProfile1->AuthType)
|| pProfile2->BSSType != pProfile1->BSSType
|| !csrIsEncryptionInList( pMac, &pProfile2->EncryptionType, pProfile1->EncryptionType )
)
{
fCheck = eANI_BOOLEAN_FALSE;
break;
}
#ifdef WLAN_FEATURE_VOWIFI_11R
if (pProfile1->MDID.mdiePresent || pProfile2->MDID.mdiePresent)
{
if (pProfile1->MDID.mobilityDomain != pProfile2->MDID.mobilityDomain)
{
fCheck = eANI_BOOLEAN_FALSE;
break;
}
}
#endif
//Match found
fCheck = eANI_BOOLEAN_TRUE;
}while(0);
csrFreeScanFilter(pMac, pScanFilter);
}
vos_mem_free(pScanFilter);
}
}
return (fCheck);
}
tANI_BOOLEAN csrRoamIsSameProfileKeys(tpAniSirGlobal pMac, tCsrRoamConnectedProfile *pConnProfile, tCsrRoamProfile *pProfile2)
{
tANI_BOOLEAN fCheck = eANI_BOOLEAN_FALSE;
int i;
do
{
//Only check for static WEP
if(!csrIsEncryptionInList(pMac, &pProfile2->EncryptionType, eCSR_ENCRYPT_TYPE_WEP40_STATICKEY) &&
!csrIsEncryptionInList(pMac, &pProfile2->EncryptionType, eCSR_ENCRYPT_TYPE_WEP104_STATICKEY))
{
fCheck = eANI_BOOLEAN_TRUE;
break;
}
if(!csrIsEncryptionInList(pMac, &pProfile2->EncryptionType, pConnProfile->EncryptionType)) break;
if(pConnProfile->Keys.defaultIndex != pProfile2->Keys.defaultIndex) break;
for(i = 0; i < CSR_MAX_NUM_KEY; i++)
{
if(pConnProfile->Keys.KeyLength[i] != pProfile2->Keys.KeyLength[i]) break;
if (!vos_mem_compare(&pConnProfile->Keys.KeyMaterial[i],
&pProfile2->Keys.KeyMaterial[i], pProfile2->Keys.KeyLength[i]))
{
break;
}
}
if( i == CSR_MAX_NUM_KEY)
{
fCheck = eANI_BOOLEAN_TRUE;
}
}while(0);
return (fCheck);
}
//IBSS
tANI_U8 csrRoamGetIbssStartChannelNumber50( tpAniSirGlobal pMac )
{
tANI_U8 channel = 0;
tANI_U32 idx;
tANI_U32 idxValidChannels;
tANI_BOOLEAN fFound = FALSE;
tANI_U32 len = sizeof(pMac->roam.validChannelList);
if(eCSR_OPERATING_CHANNEL_ANY != pMac->roam.configParam.AdHocChannel5G)
{
channel = pMac->roam.configParam.AdHocChannel5G;
if(!csrRoamIsChannelValid(pMac, channel))
{
channel = 0;
}
}
if (0 == channel && HAL_STATUS_SUCCESS(csrGetCfgValidChannels(pMac, (tANI_U8 *)pMac->roam.validChannelList, &len)))
{
for ( idx = 0; ( idx < CSR_NUM_IBSS_START_CHANNELS_50 ) && !fFound; idx++ )
{
for ( idxValidChannels = 0; ( idxValidChannels < len ) && !fFound; idxValidChannels++ )
{
if ( csrStartIbssChannels50[ idx ] == pMac->roam.validChannelList[ idxValidChannels ] )
{
fFound = TRUE;
channel = csrStartIbssChannels50[ idx ];
}
}
}
// this is rare, but if it does happen, we find anyone in 11a bandwidth and return the first 11a channel found!
if (!fFound)
{
for ( idxValidChannels = 0; idxValidChannels < len ; idxValidChannels++ )
{
if ( CSR_IS_CHANNEL_5GHZ(pMac->roam.validChannelList[ idxValidChannels ]) ) // the max channel# in 11g is 14
{
channel = pMac->roam.validChannelList[ idxValidChannels ];
break;
}
}
}
}//if
return( channel );
}
tANI_U8 csrRoamGetIbssStartChannelNumber24( tpAniSirGlobal pMac )
{
tANI_U8 channel = 1;
tANI_U32 idx;
tANI_U32 idxValidChannels;
tANI_BOOLEAN fFound = FALSE;
tANI_U32 len = sizeof(pMac->roam.validChannelList);
if(eCSR_OPERATING_CHANNEL_ANY != pMac->roam.configParam.AdHocChannel24)
{
channel = pMac->roam.configParam.AdHocChannel24;
if(!csrRoamIsChannelValid(pMac, channel))
{
channel = 0;
}
}
if (0 == channel && HAL_STATUS_SUCCESS(csrGetCfgValidChannels(pMac, (tANI_U8 *)pMac->roam.validChannelList, &len)))
{
for ( idx = 0; ( idx < CSR_NUM_IBSS_START_CHANNELS_24 ) && !fFound; idx++ )
{
for ( idxValidChannels = 0; ( idxValidChannels < len ) && !fFound; idxValidChannels++ )
{
if ( csrStartIbssChannels24[ idx ] == pMac->roam.validChannelList[ idxValidChannels ] )
{
fFound = TRUE;
channel = csrStartIbssChannels24[ idx ];
}
}
}
}
return( channel );
}
static void csrRoamGetBssStartParms( tpAniSirGlobal pMac, tCsrRoamProfile *pProfile,
tCsrRoamStartBssParams *pParam )
{
eCsrCfgDot11Mode cfgDot11Mode;
eCsrBand eBand;
tANI_U8 channel = 0;
tSirNwType nwType;
tANI_U8 operationChannel = 0;
if(pProfile->ChannelInfo.numOfChannels && pProfile->ChannelInfo.ChannelList)
{
operationChannel = pProfile->ChannelInfo.ChannelList[0];
}
cfgDot11Mode = csrRoamGetPhyModeBandForBss( pMac, pProfile, operationChannel, &eBand );
if( ( (pProfile->csrPersona == VOS_P2P_CLIENT_MODE) ||
(pProfile->csrPersona == VOS_P2P_GO_MODE) )
&& ( cfgDot11Mode == eCSR_CFG_DOT11_MODE_11B)
)
{
/* This should never happen */
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,
FL("For P2PClient/P2P-GO (persona %d) cfgDot11Mode is 11B"),
pProfile->csrPersona);
VOS_ASSERT(0);
}
switch( cfgDot11Mode )
{
case eCSR_CFG_DOT11_MODE_11G:
nwType = eSIR_11G_NW_TYPE;
break;
case eCSR_CFG_DOT11_MODE_11B:
nwType = eSIR_11B_NW_TYPE;
break;
case eCSR_CFG_DOT11_MODE_11A:
nwType = eSIR_11A_NW_TYPE;
break;
default:
case eCSR_CFG_DOT11_MODE_11N:
case eCSR_CFG_DOT11_MODE_TAURUS:
//Because LIM only verifies it against 11a, 11b or 11g, set only 11g or 11a here
if(eCSR_BAND_24 == eBand)
{
nwType = eSIR_11G_NW_TYPE;
}
else
{
nwType = eSIR_11A_NW_TYPE;
}
break;
}
pParam->extendedRateSet.numRates = 0;
switch ( nwType )
{
default:
smsLog(pMac, LOGE, FL("sees an unknown pSirNwType (%d)"), nwType);
case eSIR_11A_NW_TYPE:
pParam->operationalRateSet.numRates = 8;
pParam->operationalRateSet.rate[0] = SIR_MAC_RATE_6 | CSR_DOT11_BASIC_RATE_MASK;
pParam->operationalRateSet.rate[1] = SIR_MAC_RATE_9;
pParam->operationalRateSet.rate[2] = SIR_MAC_RATE_12 | CSR_DOT11_BASIC_RATE_MASK;
pParam->operationalRateSet.rate[3] = SIR_MAC_RATE_18;
pParam->operationalRateSet.rate[4] = SIR_MAC_RATE_24 | CSR_DOT11_BASIC_RATE_MASK;
pParam->operationalRateSet.rate[5] = SIR_MAC_RATE_36;
pParam->operationalRateSet.rate[6] = SIR_MAC_RATE_48;
pParam->operationalRateSet.rate[7] = SIR_MAC_RATE_54;
if ( eCSR_OPERATING_CHANNEL_ANY == operationChannel )
{
channel = csrRoamGetIbssStartChannelNumber50( pMac );
if( 0 == channel &&
CSR_IS_PHY_MODE_DUAL_BAND(pProfile->phyMode) &&
CSR_IS_PHY_MODE_DUAL_BAND(pMac->roam.configParam.phyMode)
)
{
//We could not find a 5G channel by auto pick, let's try 2.4G channels
//We only do this here because csrRoamGetPhyModeBandForBss always picks 11a for AUTO
nwType = eSIR_11B_NW_TYPE;
channel = csrRoamGetIbssStartChannelNumber24( pMac );
pParam->operationalRateSet.numRates = 4;
pParam->operationalRateSet.rate[0] = SIR_MAC_RATE_1 | CSR_DOT11_BASIC_RATE_MASK;
pParam->operationalRateSet.rate[1] = SIR_MAC_RATE_2 | CSR_DOT11_BASIC_RATE_MASK;
pParam->operationalRateSet.rate[2] = SIR_MAC_RATE_5_5 | CSR_DOT11_BASIC_RATE_MASK;
pParam->operationalRateSet.rate[3] = SIR_MAC_RATE_11 | CSR_DOT11_BASIC_RATE_MASK;
}
}
else
{
channel = operationChannel;
}
break;
case eSIR_11B_NW_TYPE:
pParam->operationalRateSet.numRates = 4;
pParam->operationalRateSet.rate[0] = SIR_MAC_RATE_1 | CSR_DOT11_BASIC_RATE_MASK;
pParam->operationalRateSet.rate[1] = SIR_MAC_RATE_2 | CSR_DOT11_BASIC_RATE_MASK;
pParam->operationalRateSet.rate[2] = SIR_MAC_RATE_5_5 | CSR_DOT11_BASIC_RATE_MASK;
pParam->operationalRateSet.rate[3] = SIR_MAC_RATE_11 | CSR_DOT11_BASIC_RATE_MASK;
if ( eCSR_OPERATING_CHANNEL_ANY == operationChannel )
{
channel = csrRoamGetIbssStartChannelNumber24( pMac );
}
else
{
channel = operationChannel;
}
break;
case eSIR_11G_NW_TYPE:
/* For P2P Client and P2P GO, disable 11b rates */
if( (pProfile->csrPersona == VOS_P2P_CLIENT_MODE) ||
(pProfile->csrPersona == VOS_P2P_GO_MODE)
)
{
pParam->operationalRateSet.numRates = 8;
pParam->operationalRateSet.rate[0] = SIR_MAC_RATE_6 | CSR_DOT11_BASIC_RATE_MASK;
pParam->operationalRateSet.rate[1] = SIR_MAC_RATE_9;
pParam->operationalRateSet.rate[2] = SIR_MAC_RATE_12 | CSR_DOT11_BASIC_RATE_MASK;
pParam->operationalRateSet.rate[3] = SIR_MAC_RATE_18;
pParam->operationalRateSet.rate[4] = SIR_MAC_RATE_24 | CSR_DOT11_BASIC_RATE_MASK;
pParam->operationalRateSet.rate[5] = SIR_MAC_RATE_36;
pParam->operationalRateSet.rate[6] = SIR_MAC_RATE_48;
pParam->operationalRateSet.rate[7] = SIR_MAC_RATE_54;
}
else
{
pParam->operationalRateSet.numRates = 4;
pParam->operationalRateSet.rate[0] = SIR_MAC_RATE_1 | CSR_DOT11_BASIC_RATE_MASK;
pParam->operationalRateSet.rate[1] = SIR_MAC_RATE_2 | CSR_DOT11_BASIC_RATE_MASK;
pParam->operationalRateSet.rate[2] = SIR_MAC_RATE_5_5 | CSR_DOT11_BASIC_RATE_MASK;
pParam->operationalRateSet.rate[3] = SIR_MAC_RATE_11 | CSR_DOT11_BASIC_RATE_MASK;
pParam->extendedRateSet.numRates = 8;
pParam->extendedRateSet.rate[0] = SIR_MAC_RATE_6;
pParam->extendedRateSet.rate[1] = SIR_MAC_RATE_9;
pParam->extendedRateSet.rate[2] = SIR_MAC_RATE_12;
pParam->extendedRateSet.rate[3] = SIR_MAC_RATE_18;
pParam->extendedRateSet.rate[4] = SIR_MAC_RATE_24;
pParam->extendedRateSet.rate[5] = SIR_MAC_RATE_36;
pParam->extendedRateSet.rate[6] = SIR_MAC_RATE_48;
pParam->extendedRateSet.rate[7] = SIR_MAC_RATE_54;
}
if ( eCSR_OPERATING_CHANNEL_ANY == operationChannel )
{
channel = csrRoamGetIbssStartChannelNumber24( pMac );
}
else
{
channel = operationChannel;
}
break;
}
pParam->operationChn = channel;
pParam->sirNwType = nwType;
}
static void csrRoamGetBssStartParmsFromBssDesc( tpAniSirGlobal pMac, tSirBssDescription *pBssDesc,
tDot11fBeaconIEs *pIes, tCsrRoamStartBssParams *pParam )
{
if( pParam )
{
pParam->sirNwType = pBssDesc->nwType;
pParam->cbMode = PHY_SINGLE_CHANNEL_CENTERED;
pParam->operationChn = pBssDesc->channelId;
vos_mem_copy(&pParam->bssid, pBssDesc->bssId, sizeof(tCsrBssid));
if( pIes )
{
if(pIes->SuppRates.present)
{
pParam->operationalRateSet.numRates = pIes->SuppRates.num_rates;
if(pIes->SuppRates.num_rates > SIR_MAC_RATESET_EID_MAX)
{
smsLog(pMac, LOGE, FL("num_rates :%d is more than SIR_MAC_RATESET_EID_MAX, resetting to SIR_MAC_RATESET_EID_MAX"),
pIes->SuppRates.num_rates);
pIes->SuppRates.num_rates = SIR_MAC_RATESET_EID_MAX;
}
vos_mem_copy(pParam->operationalRateSet.rate, pIes->SuppRates.rates,
sizeof(*pIes->SuppRates.rates) * pIes->SuppRates.num_rates);
}
if (pIes->ExtSuppRates.present)
{
pParam->extendedRateSet.numRates = pIes->ExtSuppRates.num_rates;
if(pIes->ExtSuppRates.num_rates > SIR_MAC_RATESET_EID_MAX)
{
smsLog(pMac, LOGE, FL("num_rates :%d is more than \
SIR_MAC_RATESET_EID_MAX, resetting to \
SIR_MAC_RATESET_EID_MAX"),
pIes->ExtSuppRates.num_rates);
pIes->ExtSuppRates.num_rates = SIR_MAC_RATESET_EID_MAX;
}
vos_mem_copy(pParam->extendedRateSet.rate,
pIes->ExtSuppRates.rates,
sizeof(*pIes->ExtSuppRates.rates) * pIes->ExtSuppRates.num_rates);
}
if( pIes->SSID.present )
{
pParam->ssId.length = pIes->SSID.num_ssid;
vos_mem_copy(pParam->ssId.ssId, pIes->SSID.ssid,
pParam->ssId.length);
}
pParam->cbMode = csrGetCBModeFromIes(pMac, pParam->operationChn, pIes);
}
else
{
pParam->ssId.length = 0;
pParam->operationalRateSet.numRates = 0;
}
}
}
static void csrRoamDetermineMaxRateForAdHoc( tpAniSirGlobal pMac, tSirMacRateSet *pSirRateSet )
{
tANI_U8 MaxRate = 0;
tANI_U32 i;
tANI_U8 *pRate;
pRate = pSirRateSet->rate;
for ( i = 0; i < pSirRateSet->numRates; i++ )
{
MaxRate = CSR_MAX( MaxRate, ( pRate[ i ] & (~CSR_DOT11_BASIC_RATE_MASK) ) );
}
// Save the max rate in the connected state information...
// modify LastRates variable as well
return;
}
eHalStatus csrRoamIssueStartBss( tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamStartBssParams *pParam,
tCsrRoamProfile *pProfile, tSirBssDescription *pBssDesc, tANI_U32 roamId )
{
eHalStatus status = eHAL_STATUS_SUCCESS;
eCsrBand eBand;
// Set the roaming substate to 'Start BSS attempt'...
csrRoamSubstateChange( pMac, eCSR_ROAM_SUBSTATE_START_BSS_REQ, sessionId );
#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
//Need to figure out whether we need to log WDS???
if( CSR_IS_IBSS( pProfile ) )
{
vos_log_ibss_pkt_type *pIbssLog;
WLAN_VOS_DIAG_LOG_ALLOC(pIbssLog, vos_log_ibss_pkt_type, LOG_WLAN_IBSS_C);
if(pIbssLog)
{
if(pBssDesc)
{
pIbssLog->eventId = WLAN_IBSS_EVENT_JOIN_IBSS_REQ;
vos_mem_copy(pIbssLog->bssid, pBssDesc->bssId, 6);
}
else
{
pIbssLog->eventId = WLAN_IBSS_EVENT_START_IBSS_REQ;
}
vos_mem_copy(pIbssLog->ssid, pParam->ssId.ssId, pParam->ssId.length);
if(pProfile->ChannelInfo.numOfChannels == 0)
{
pIbssLog->channelSetting = AUTO_PICK;
}
else
{
pIbssLog->channelSetting = SPECIFIED;
}
pIbssLog->operatingChannel = pParam->operationChn;
WLAN_VOS_DIAG_LOG_REPORT(pIbssLog);
}
}
#endif //FEATURE_WLAN_DIAG_SUPPORT_CSR
//Put RSN information in for Starting BSS
pParam->nRSNIELength = (tANI_U16)pProfile->nRSNReqIELength;
pParam->pRSNIE = pProfile->pRSNReqIE;
pParam->privacy = pProfile->privacy;
pParam->fwdWPSPBCProbeReq = pProfile->fwdWPSPBCProbeReq;
pParam->authType = pProfile->csr80211AuthType;
pParam->beaconInterval = pProfile->beaconInterval;
pParam->dtimPeriod = pProfile->dtimPeriod;
pParam->ApUapsdEnable = pProfile->ApUapsdEnable;
pParam->ssidHidden = pProfile->SSIDs.SSIDList[0].ssidHidden;
if (CSR_IS_INFRA_AP(pProfile)&& (pParam->operationChn != 0))
{
if (csrIsValidChannel(pMac, pParam->operationChn) != eHAL_STATUS_SUCCESS)
{
pParam->operationChn = INFRA_AP_DEFAULT_CHANNEL;
}
}
pParam->protEnabled = pProfile->protEnabled;
pParam->obssProtEnabled = pProfile->obssProtEnabled;
pParam->ht_protection = pProfile->cfg_protection;
pParam->wps_state = pProfile->wps_state;
pParam->uCfgDot11Mode = csrRoamGetPhyModeBandForBss(pMac, pProfile, pParam->operationChn /* pProfile->operationChannel*/,
&eBand);
pParam->bssPersona = pProfile->csrPersona;
#ifdef WLAN_FEATURE_11W
pParam->mfpCapable = (0 != pProfile->MFPCapable);
pParam->mfpRequired = (0 != pProfile->MFPRequired);
#endif
// When starting an IBSS, start on the channel from the Profile.
status = csrSendMBStartBssReqMsg( pMac, sessionId, pProfile->BSSType, pParam, pBssDesc );
return (status);
}
static void csrRoamPrepareBssParams(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfile *pProfile,
tSirBssDescription *pBssDesc, tBssConfigParam *pBssConfig, tDot11fBeaconIEs *pIes)
{
tANI_U8 Channel;
ePhyChanBondState cbMode = PHY_SINGLE_CHANNEL_CENTERED;
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return;
}
if( pBssDesc )
{
csrRoamGetBssStartParmsFromBssDesc( pMac, pBssDesc, pIes, &pSession->bssParams );
//Since csrRoamGetBssStartParmsFromBssDesc fills in the bssid for pSession->bssParams
//The following code has to be do after that.
//For WDS station, use selfMac as the self BSSID
if( CSR_IS_WDS_STA( pProfile ) )
{
vos_mem_copy(&pSession->bssParams.bssid, &pSession->selfMacAddr,
sizeof(tCsrBssid));
}
}
else
{
csrRoamGetBssStartParms(pMac, pProfile, &pSession->bssParams);
//Use the first SSID
if(pProfile->SSIDs.numOfSSIDs)
{
vos_mem_copy(&pSession->bssParams.ssId, pProfile->SSIDs.SSIDList,
sizeof(tSirMacSSid));
}
//For WDS station, use selfMac as the self BSSID
if( CSR_IS_WDS_STA( pProfile ) )
{
vos_mem_copy(&pSession->bssParams.bssid, &pSession->selfMacAddr,
sizeof(tCsrBssid));
}
//Use the first BSSID
else if( pProfile->BSSIDs.numOfBSSIDs )
{
vos_mem_copy(&pSession->bssParams.bssid, pProfile->BSSIDs.bssid,
sizeof(tCsrBssid));
}
else
{
vos_mem_set(&pSession->bssParams.bssid, sizeof(tCsrBssid), 0);
}
}
Channel = pSession->bssParams.operationChn;
//Set operating channel in pProfile which will be used
//in csrRoamSetBssConfigCfg() to determine channel bonding
//mode and will be configured in CFG later
pProfile->operationChannel = Channel;
if(Channel == 0)
{
smsLog(pMac, LOGE, " CSR cannot find a channel to start IBSS");
}
else
{
csrRoamDetermineMaxRateForAdHoc( pMac, &pSession->bssParams.operationalRateSet );
if (CSR_IS_INFRA_AP(pProfile) || CSR_IS_START_IBSS( pProfile ) )
{
if(CSR_IS_CHANNEL_24GHZ(Channel) )
{
#ifdef WLAN_FEATURE_AP_HT40_24G
if (CSR_IS_INFRA_AP(pProfile))
cbMode = pMac->roam.configParam.channelBondingAPMode24GHz;
else
cbMode = PHY_SINGLE_CHANNEL_CENTERED;
#else
cbMode = PHY_SINGLE_CHANNEL_CENTERED;
#endif
}
else
{
cbMode = pMac->roam.configParam.channelBondingMode5GHz;
}
pBssConfig->cbMode = cbMode;
pSession->bssParams.cbMode = cbMode;
if (cbMode >= PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_CENTERED)
pSession->bssParams.orig_ch_width = eHT_CHANNEL_WIDTH_80MHZ;
else if (cbMode > PHY_SINGLE_CHANNEL_CENTERED)
pSession->bssParams.orig_ch_width = eHT_CHANNEL_WIDTH_40MHZ;
else
pSession->bssParams.orig_ch_width = eHT_CHANNEL_WIDTH_20MHZ;
smsLog(pMac, LOG1, FL("## cbMode %d orig_width %d"), cbMode,
pSession->bssParams.orig_ch_width);
}
}
}
static eHalStatus csrRoamStartIbss( tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfile *pProfile,
tANI_BOOLEAN *pfSameIbss )
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tANI_BOOLEAN fSameIbss = FALSE;
if ( csrIsConnStateIbss( pMac, sessionId ) )
{
// Check if any profile parameter has changed ? If any profile parameter
// has changed then stop old BSS and start a new one with new parameters
if ( csrIsSameProfile( pMac, &pMac->roam.roamSession[sessionId].connectedProfile, pProfile ) )
{
fSameIbss = TRUE;
}
else
{
status = csrRoamIssueStopBss( pMac, sessionId, eCSR_ROAM_SUBSTATE_DISCONNECT_CONTINUE_ROAMING );
}
}
else if ( csrIsConnStateConnectedInfra( pMac, sessionId ) )
{
// Disassociate from the connected Infrastructure network...
status = csrRoamIssueDisassociate( pMac, sessionId, eCSR_ROAM_SUBSTATE_DISCONNECT_CONTINUE_ROAMING, FALSE );
}
else
{
tBssConfigParam *pBssConfig;
pBssConfig = vos_mem_malloc(sizeof(tBssConfigParam));
if ( NULL == pBssConfig )
status = eHAL_STATUS_FAILURE;
else
status = eHAL_STATUS_SUCCESS;
if(HAL_STATUS_SUCCESS(status))
{
vos_mem_set(pBssConfig, sizeof(tBssConfigParam), 0);
// there is no Bss description before we start an IBSS so we need to adopt
// all Bss configuration parameters from the Profile.
status = csrRoamPrepareBssConfigFromProfile(pMac, pProfile, pBssConfig, NULL);
if(HAL_STATUS_SUCCESS(status))
{
//save dotMode
pMac->roam.roamSession[sessionId].bssParams.uCfgDot11Mode = pBssConfig->uCfgDot11Mode;
//Prepare some more parameters for this IBSS
csrRoamPrepareBssParams(pMac, sessionId, pProfile, NULL, pBssConfig, NULL);
status = csrRoamSetBssConfigCfg(pMac, sessionId, pProfile,
NULL, pBssConfig,
NULL, eANI_BOOLEAN_FALSE);
}
vos_mem_free(pBssConfig);
}//Allocate memory
}
if(pfSameIbss)
{
*pfSameIbss = fSameIbss;
}
return( status );
}
static void csrRoamUpdateConnectedProfileFromNewBss( tpAniSirGlobal pMac, tANI_U32 sessionId,
tSirSmeNewBssInfo *pNewBss )
{
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return;
}
if( pNewBss )
{
// Set the operating channel.
pSession->connectedProfile.operationChannel = pNewBss->channelNumber;
// move the BSSId from the BSS description into the connected state information.
vos_mem_copy(&pSession->connectedProfile.bssid, &(pNewBss->bssId),
sizeof( tCsrBssid ));
}
return;
}
#ifdef FEATURE_WLAN_WAPI
eHalStatus csrRoamSetBKIDCache( tpAniSirGlobal pMac, tANI_U32 sessionId, tBkidCacheInfo *pBKIDCache,
tANI_U32 numItems )
{
eHalStatus status = eHAL_STATUS_INVALID_PARAMETER;
tCsrRoamSession *pSession = NULL;
if(!CSR_IS_SESSION_VALID( pMac, sessionId ))
{
smsLog(pMac, LOGE, FL(" Invalid session ID"));
return status;
}
smsLog(pMac, LOGW, "csrRoamSetBKIDCache called, numItems = %d", numItems);
pSession = CSR_GET_SESSION( pMac, sessionId );
if(numItems <= CSR_MAX_BKID_ALLOWED)
{
status = eHAL_STATUS_SUCCESS;
//numItems may be 0 to clear the cache
pSession->NumBkidCache = (tANI_U16)numItems;
if(numItems && pBKIDCache)
{
vos_mem_copy(pSession->BkidCacheInfo, pBKIDCache,
sizeof(tBkidCacheInfo) * numItems);
status = eHAL_STATUS_SUCCESS;
}
}
return (status);
}
eHalStatus csrRoamGetBKIDCache(tpAniSirGlobal pMac, tANI_U32 sessionId, tANI_U32 *pNum,
tBkidCacheInfo *pBkidCache)
{
eHalStatus status = eHAL_STATUS_INVALID_PARAMETER;
tCsrRoamSession *pSession = NULL;
if(!CSR_IS_SESSION_VALID( pMac, sessionId ))
{
smsLog(pMac, LOGE, FL(" Invalid session ID"));
return status;
}
pSession = CSR_GET_SESSION( pMac, sessionId );
if(pNum && pBkidCache)
{
if(pSession->NumBkidCache == 0)
{
*pNum = 0;
status = eHAL_STATUS_SUCCESS;
}
else if(*pNum >= pSession->NumBkidCache)
{
if(pSession->NumBkidCache > CSR_MAX_BKID_ALLOWED)
{
smsLog(pMac, LOGE, FL("NumBkidCache :%d is more than CSR_MAX_BKID_ALLOWED, resetting to CSR_MAX_BKID_ALLOWED"),
pSession->NumBkidCache);
pSession->NumBkidCache = CSR_MAX_BKID_ALLOWED;
}
vos_mem_copy(pBkidCache, pSession->BkidCacheInfo,
sizeof(tBkidCacheInfo) * pSession->NumBkidCache);
*pNum = pSession->NumBkidCache;
status = eHAL_STATUS_SUCCESS;
}
}
return (status);
}
tANI_U32 csrRoamGetNumBKIDCache(tpAniSirGlobal pMac, tANI_U32 sessionId)
{
return (pMac->roam.roamSession[sessionId].NumBkidCache);
}
#endif /* FEATURE_WLAN_WAPI */
eHalStatus csrRoamSetPMKIDCache( tpAniSirGlobal pMac, tANI_U32 sessionId,
tPmkidCacheInfo *pPMKIDCache,
tANI_U32 numItems,
tANI_BOOLEAN update_entire_cache )
{
eHalStatus status = eHAL_STATUS_INVALID_PARAMETER;
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
if (!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return eHAL_STATUS_FAILURE;
}
smsLog(pMac, LOGW, "csrRoamSetPMKIDCache called, numItems = %d", numItems);
if (numItems <= CSR_MAX_PMKID_ALLOWED)
{
#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
{
WLAN_VOS_DIAG_EVENT_DEF(secEvent, vos_event_wlan_security_payload_type);
vos_mem_set(&secEvent,
sizeof(vos_event_wlan_security_payload_type), 0);
secEvent.eventId = WLAN_SECURITY_EVENT_PMKID_UPDATE;
secEvent.encryptionModeMulticast =
(v_U8_t)diagEncTypeFromCSRType(pSession->connectedProfile.mcEncryptionType);
secEvent.encryptionModeUnicast =
(v_U8_t)diagEncTypeFromCSRType(pSession->connectedProfile.EncryptionType);
vos_mem_copy(secEvent.bssid, pSession->connectedProfile.bssid, 6);
secEvent.authMode =
(v_U8_t)diagAuthTypeFromCSRType(pSession->connectedProfile.AuthType);
WLAN_VOS_DIAG_EVENT_REPORT(&secEvent, EVENT_WLAN_SECURITY);
}
#endif//FEATURE_WLAN_DIAG_SUPPORT_CSR
status = eHAL_STATUS_SUCCESS;
if (update_entire_cache) {
if (numItems && pPMKIDCache)
{
pSession->NumPmkidCache = (tANI_U16)numItems;
vos_mem_copy(pSession->PmkidCacheInfo, pPMKIDCache,
sizeof(tPmkidCacheInfo) * numItems);
pSession->CurCacheIndex = (tANI_U16)numItems;
}
} else {
tANI_U32 i = 0;
tPmkidCacheInfo *pmksa;
for (i = 0; i < numItems; i++) {
pmksa = &pPMKIDCache[i];
/* Delete the entry if present */
csrRoamDelPMKIDfromCache(pMac,sessionId,pmksa->BSSID,FALSE);
/* Add entry to the cache */
vos_mem_copy(
pSession->PmkidCacheInfo[pSession->CurCacheIndex].BSSID,
pmksa->BSSID, VOS_MAC_ADDR_SIZE);
vos_mem_copy(
pSession->PmkidCacheInfo[pSession->CurCacheIndex].PMKID,
pmksa->PMKID, CSR_RSN_PMKID_SIZE);
/* Increment the CSR local cache index */
if (pSession->CurCacheIndex < (CSR_MAX_PMKID_ALLOWED - 1))
pSession->CurCacheIndex++;
else
pSession->CurCacheIndex = 0;
pSession->NumPmkidCache++;
if(pSession->NumPmkidCache > CSR_MAX_PMKID_ALLOWED)
pSession->NumPmkidCache = CSR_MAX_PMKID_ALLOWED;
}
}
}
return (status);
}
eHalStatus csrRoamDelPMKIDfromCache( tpAniSirGlobal pMac, tANI_U32 sessionId,
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0))
const tANI_U8 *pBSSId,
#else
tANI_U8 *pBSSId,
#endif
tANI_BOOLEAN flush_cache )
{
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
tANI_BOOLEAN fMatchFound = FALSE;
tANI_U32 Index;
tANI_U32 CurIndex;
tANI_U32 i;
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return eHAL_STATUS_FAILURE;
}
/* Check if there are no entries to delete */
if (0 == pSession->NumPmkidCache) {
smsLog(pMac, LOG1, FL("No entries to delete/Flush"));
return eHAL_STATUS_SUCCESS;
}
if (!flush_cache) {
for (Index = 0; Index < CSR_MAX_PMKID_ALLOWED; Index++) {
if (vos_mem_compare(pSession->PmkidCacheInfo[Index].BSSID,
pBSSId, VOS_MAC_ADDR_SIZE)) {
fMatchFound = 1;
/* Clear this - the matched entry */
vos_mem_zero(&pSession->PmkidCacheInfo[Index],
sizeof(tPmkidCacheInfo));
break;
}
}
if (Index == CSR_MAX_PMKID_ALLOWED && !fMatchFound) {
smsLog(pMac, LOG1, FL("No such PMKSA entry exists "MAC_ADDRESS_STR),
MAC_ADDR_ARRAY(pBSSId));
}
else {
/* Match Found */
CurIndex = pSession->CurCacheIndex;
if(Index < CurIndex) {
for(i = Index; i < (CurIndex-1); i++) {
vos_mem_copy(&pSession->PmkidCacheInfo[i],
&pSession->PmkidCacheInfo[i+1],sizeof(tPmkidCacheInfo));
}
pSession->CurCacheIndex--;
vos_mem_zero(&pSession->PmkidCacheInfo[pSession->CurCacheIndex],
sizeof(tPmkidCacheInfo));
} else if(Index > CurIndex) {
for(i = Index; i > (CurIndex); i--) {
vos_mem_copy(&pSession->PmkidCacheInfo[i],
&pSession->PmkidCacheInfo[i-1],sizeof(tPmkidCacheInfo));
}
vos_mem_zero(&pSession->PmkidCacheInfo[pSession->CurCacheIndex],
sizeof(tPmkidCacheInfo));
}
pSession->NumPmkidCache--;
}
} else {
/* Flush the entire cache */
vos_mem_zero(pSession->PmkidCacheInfo,
sizeof(tPmkidCacheInfo) * CSR_MAX_PMKID_ALLOWED);
pSession->NumPmkidCache = 0;
pSession->CurCacheIndex = 0;
}
return eHAL_STATUS_SUCCESS;
}
tANI_U32 csrRoamGetNumPMKIDCache(tpAniSirGlobal pMac, tANI_U32 sessionId)
{
return (pMac->roam.roamSession[sessionId].NumPmkidCache);
}
eHalStatus csrRoamGetPMKIDCache(tpAniSirGlobal pMac, tANI_U32 sessionId, tANI_U32 *pNum, tPmkidCacheInfo *pPmkidCache)
{
eHalStatus status = eHAL_STATUS_INVALID_PARAMETER;
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
tPmkidCacheInfo *pmksa;
tANI_U16 i,j;
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return eHAL_STATUS_FAILURE;
}
if(pNum && pPmkidCache)
{
if(pSession->NumPmkidCache == 0)
{
*pNum = 0;
status = eHAL_STATUS_SUCCESS;
}
else if(*pNum >= pSession->NumPmkidCache)
{
if(pSession->NumPmkidCache > CSR_MAX_PMKID_ALLOWED)
{
smsLog(pMac, LOGE, FL("NumPmkidCache :%d is more than CSR_MAX_PMKID_ALLOWED, resetting to CSR_MAX_PMKID_ALLOWED"),
pSession->NumPmkidCache);
pSession->NumPmkidCache = CSR_MAX_PMKID_ALLOWED;
}
for(i = 0,j = 0; (j<pSession->NumPmkidCache)&&(i<CSR_MAX_PMKID_ALLOWED); i++) {
pmksa = &pSession->PmkidCacheInfo[i];
if(!csrIsMacAddressZero(pMac, &pmksa->BSSID)) {
vos_mem_copy(pPmkidCache,pmksa,sizeof(tPmkidCacheInfo));
pPmkidCache++;
j++;
}
}
*pNum = pSession->NumPmkidCache;
status = eHAL_STATUS_SUCCESS;
}
}
return (status);
}
eHalStatus csrRoamGetWpaRsnReqIE(tpAniSirGlobal pMac, tANI_U32 sessionId, tANI_U32 *pLen, tANI_U8 *pBuf)
{
eHalStatus status = eHAL_STATUS_INVALID_PARAMETER;
tANI_U32 len;
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return eHAL_STATUS_FAILURE;
}
if(pLen)
{
len = *pLen;
*pLen = pSession->nWpaRsnReqIeLength;
if(pBuf)
{
if(len >= pSession->nWpaRsnReqIeLength)
{
vos_mem_copy(pBuf, pSession->pWpaRsnReqIE,
pSession->nWpaRsnReqIeLength);
status = eHAL_STATUS_SUCCESS;
}
}
}
return (status);
}
eHalStatus csrRoamGetWpaRsnRspIE(tpAniSirGlobal pMac, tANI_U32 sessionId, tANI_U32 *pLen, tANI_U8 *pBuf)
{
eHalStatus status = eHAL_STATUS_INVALID_PARAMETER;
tANI_U32 len;
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return eHAL_STATUS_FAILURE;
}
if(pLen)
{
len = *pLen;
*pLen = pSession->nWpaRsnRspIeLength;
if(pBuf)
{
if(len >= pSession->nWpaRsnRspIeLength)
{
vos_mem_copy(pBuf, pSession->pWpaRsnRspIE,
pSession->nWpaRsnRspIeLength);
status = eHAL_STATUS_SUCCESS;
}
}
}
return (status);
}
#ifdef FEATURE_WLAN_WAPI
eHalStatus csrRoamGetWapiReqIE(tpAniSirGlobal pMac, tANI_U32 sessionId, tANI_U32 *pLen, tANI_U8 *pBuf)
{
eHalStatus status = eHAL_STATUS_INVALID_PARAMETER;
tANI_U32 len;
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return eHAL_STATUS_FAILURE;
}
if(pLen)
{
len = *pLen;
*pLen = pSession->nWapiReqIeLength;
if(pBuf)
{
if(len >= pSession->nWapiReqIeLength)
{
vos_mem_copy(pBuf, pSession->pWapiReqIE,
pSession->nWapiReqIeLength);
status = eHAL_STATUS_SUCCESS;
}
}
}
return (status);
}
eHalStatus csrRoamGetWapiRspIE(tpAniSirGlobal pMac, tANI_U32 sessionId, tANI_U32 *pLen, tANI_U8 *pBuf)
{
eHalStatus status = eHAL_STATUS_INVALID_PARAMETER;
tANI_U32 len;
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return eHAL_STATUS_FAILURE;
}
if(pLen)
{
len = *pLen;
*pLen = pSession->nWapiRspIeLength;
if(pBuf)
{
if(len >= pSession->nWapiRspIeLength)
{
vos_mem_copy(pBuf, pSession->pWapiRspIE,
pSession->nWapiRspIeLength);
status = eHAL_STATUS_SUCCESS;
}
}
}
return (status);
}
#endif /* FEATURE_WLAN_WAPI */
eRoamCmdStatus csrGetRoamCompleteStatus(tpAniSirGlobal pMac, tANI_U32 sessionId)
{
eRoamCmdStatus retStatus = eCSR_ROAM_CONNECT_COMPLETION;
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return (retStatus);
}
if(CSR_IS_ROAMING(pSession))
{
retStatus = eCSR_ROAM_ROAMING_COMPLETION;
pSession->fRoaming = eANI_BOOLEAN_FALSE;
}
return (retStatus);
}
//This function remove the connected BSS from te cached scan result
eHalStatus csrRoamRemoveConnectedBssFromScanCache(tpAniSirGlobal pMac,
tCsrRoamConnectedProfile *pConnProfile)
{
eHalStatus status = eHAL_STATUS_FAILURE;
tCsrScanResultFilter *pScanFilter = NULL;
tListElem *pEntry;
tCsrScanResult *pResult;
tDot11fBeaconIEs *pIes;
tANI_BOOLEAN fMatch;
if(!(csrIsMacAddressZero(pMac, &pConnProfile->bssid) ||
csrIsMacAddressBroadcast(pMac, &pConnProfile->bssid)))
{
do
{
//Prepare the filter. Only fill in the necessary fields. Not all fields are needed
pScanFilter = vos_mem_malloc(sizeof(tCsrScanResultFilter));
if ( NULL == pScanFilter )
status = eHAL_STATUS_FAILURE;
else
status = eHAL_STATUS_SUCCESS;
if(!HAL_STATUS_SUCCESS(status)) break;
vos_mem_set(pScanFilter, sizeof(tCsrScanResultFilter), 0);
pScanFilter->BSSIDs.bssid = vos_mem_malloc(sizeof(tCsrBssid));
if ( NULL == pScanFilter->BSSIDs.bssid )
status = eHAL_STATUS_FAILURE;
else
status = eHAL_STATUS_SUCCESS;
if(!HAL_STATUS_SUCCESS(status)) break;
vos_mem_copy(pScanFilter->BSSIDs.bssid, &pConnProfile->bssid,
sizeof(tCsrBssid));
pScanFilter->BSSIDs.numOfBSSIDs = 1;
if(!csrIsNULLSSID(pConnProfile->SSID.ssId, pConnProfile->SSID.length))
{
pScanFilter->SSIDs.SSIDList = vos_mem_malloc(sizeof(tCsrSSIDInfo));
if ( NULL == pScanFilter->SSIDs.SSIDList )
status = eHAL_STATUS_FAILURE;
else
status = eHAL_STATUS_SUCCESS;
if (!HAL_STATUS_SUCCESS(status)) break;
vos_mem_copy(&pScanFilter->SSIDs.SSIDList[0].SSID,
&pConnProfile->SSID, sizeof(tSirMacSSid));
}
pScanFilter->authType.numEntries = 1;
pScanFilter->authType.authType[0] = pConnProfile->AuthType;
pScanFilter->BSSType = pConnProfile->BSSType;
pScanFilter->EncryptionType.numEntries = 1;
pScanFilter->EncryptionType.encryptionType[0] = pConnProfile->EncryptionType;
pScanFilter->mcEncryptionType.numEntries = 1;
pScanFilter->mcEncryptionType.encryptionType[0] = pConnProfile->mcEncryptionType;
//We ignore the channel for now, BSSID should be enough
pScanFilter->ChannelInfo.numOfChannels = 0;
//Also ignore the following fields
pScanFilter->uapsd_mask = 0;
pScanFilter->bWPSAssociation = eANI_BOOLEAN_FALSE;
pScanFilter->bOSENAssociation = eANI_BOOLEAN_FALSE;
pScanFilter->countryCode[0] = 0;
pScanFilter->phyMode = eCSR_DOT11_MODE_TAURUS;
csrLLLock(&pMac->scan.scanResultList);
pEntry = csrLLPeekHead( &pMac->scan.scanResultList, LL_ACCESS_NOLOCK );
while( pEntry )
{
pResult = GET_BASE_ADDR( pEntry, tCsrScanResult, Link );
pIes = (tDot11fBeaconIEs *)( pResult->Result.pvIes );
fMatch = csrMatchBSS(pMac, &pResult->Result.BssDescriptor,
pScanFilter, NULL, NULL, NULL, &pIes);
//Release the IEs allocated by csrMatchBSS is needed
if( !pResult->Result.pvIes )
{
//need to free the IEs since it is allocated by csrMatchBSS
vos_mem_free(pIes);
}
if(fMatch)
{
//We found the one
if( csrLLRemoveEntry(&pMac->scan.scanResultList, pEntry, LL_ACCESS_NOLOCK) )
{
//Free the memory
csrFreeScanResultEntry( pMac, pResult );
}
break;
}
pEntry = csrLLNext(&pMac->scan.scanResultList, pEntry, LL_ACCESS_NOLOCK);
}//while
csrLLUnlock(&pMac->scan.scanResultList);
}while(0);
if(pScanFilter)
{
csrFreeScanFilter(pMac, pScanFilter);
vos_mem_free(pScanFilter);
}
}
return (status);
}
//BT-AMP
eHalStatus csrIsBTAMPAllowed( tpAniSirGlobal pMac, tANI_U32 chnId )
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tANI_U32 sessionId;
for( sessionId = 0; sessionId < CSR_ROAM_SESSION_MAX; sessionId++ )
{
if( CSR_IS_SESSION_VALID( pMac, sessionId ) )
{
if( csrIsConnStateIbss( pMac, sessionId ) || csrIsBTAMP( pMac, sessionId ) )
{
//co-exist with IBSS or BT-AMP is not supported
smsLog( pMac, LOGW, " BTAMP is not allowed due to IBSS/BT-AMP exist in session %d", sessionId );
status = eHAL_STATUS_CSR_WRONG_STATE;
break;
}
if( csrIsConnStateInfra( pMac, sessionId ) )
{
if( chnId &&
( (tANI_U8)chnId != pMac->roam.roamSession[sessionId].connectedProfile.operationChannel ) )
{
smsLog( pMac, LOGW, " BTAMP is not allowed due to channel (%d) diff than infr channel (%d)",
chnId, pMac->roam.roamSession[sessionId].connectedProfile.operationChannel );
status = eHAL_STATUS_CSR_WRONG_STATE;
break;
}
}
}
}
return ( status );
}
static eHalStatus csrRoamStartWds( tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfile *pProfile, tSirBssDescription *pBssDesc )
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
tBssConfigParam bssConfig;
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return eHAL_STATUS_FAILURE;
}
if ( csrIsConnStateIbss( pMac, sessionId ) )
{
status = csrRoamIssueStopBss( pMac, sessionId, eCSR_ROAM_SUBSTATE_DISCONNECT_CONTINUE_ROAMING );
}
else if ( csrIsConnStateConnectedInfra( pMac, sessionId ) )
{
// Disassociate from the connected Infrastructure network...
status = csrRoamIssueDisassociate( pMac, sessionId, eCSR_ROAM_SUBSTATE_DISCONNECT_CONTINUE_ROAMING, FALSE );
}
else
{
//We don't expect Bt-AMP HDD not to disconnect the last connection first at this time.
//Otherwise we need to add code to handle the
//situation just like IBSS. Though for WDS station, we need to send disassoc to PE first then
//send stop_bss to PE, before we can continue.
VOS_ASSERT( !csrIsConnStateWds( pMac, sessionId ) );
vos_mem_set(&bssConfig, sizeof(tBssConfigParam), 0);
/* Assume HDD provide bssid in profile */
vos_mem_copy(&pSession->bssParams.bssid, pProfile->BSSIDs.bssid[0],
sizeof(tCsrBssid));
// there is no Bss description before we start an WDS so we need
// to adopt all Bss configuration parameters from the Profile.
status = csrRoamPrepareBssConfigFromProfile(pMac, pProfile, &bssConfig, pBssDesc);
if(HAL_STATUS_SUCCESS(status))
{
//Save profile for late use
csrFreeRoamProfile( pMac, sessionId );
pSession->pCurRoamProfile = vos_mem_malloc(sizeof(tCsrRoamProfile));
if (pSession->pCurRoamProfile != NULL )
{
vos_mem_set(pSession->pCurRoamProfile,
sizeof(tCsrRoamProfile), 0);
csrRoamCopyProfile(pMac, pSession->pCurRoamProfile, pProfile);
}
//Prepare some more parameters for this WDS
csrRoamPrepareBssParams(pMac, sessionId, pProfile, NULL, &bssConfig, NULL);
status = csrRoamSetBssConfigCfg(pMac, sessionId, pProfile,
NULL, &bssConfig,
NULL, eANI_BOOLEAN_FALSE);
}
}
return( status );
}
////////////////////Mail box
//pBuf is caller allocated memory point to &(tSirSmeJoinReq->rsnIE.rsnIEdata[ 0 ]) + pMsg->rsnIE.length;
//or &(tSirSmeReassocReq->rsnIE.rsnIEdata[ 0 ]) + pMsg->rsnIE.length;
static void csrPrepareJoinReassocReqBuffer( tpAniSirGlobal pMac,
tSirBssDescription *pBssDescription,
tANI_U8 *pBuf, tANI_U8 uapsdMask)
{
tCsrChannelSet channelGroup;
tSirMacCapabilityInfo *pAP_capabilityInfo;
tAniBool fTmp;
tANI_BOOLEAN found = FALSE;
tANI_U32 size = 0;
tANI_S8 pwrLimit = 0;
tANI_U16 i;
// plug in neighborhood occupancy info (i.e. BSSes on primary or secondary channels)
*pBuf++ = (tANI_U8)FALSE; //tAniTitanCBNeighborInfo->cbBssFoundPri
*pBuf++ = (tANI_U8)FALSE; //tAniTitanCBNeighborInfo->cbBssFoundSecDown
*pBuf++ = (tANI_U8)FALSE; //tAniTitanCBNeighborInfo->cbBssFoundSecUp
// 802.11h
//We can do this because it is in HOST CPU order for now.
pAP_capabilityInfo = (tSirMacCapabilityInfo *)&pBssDescription->capabilityInfo;
//tell the target AP my 11H capability only if both AP and STA support 11H and the channel being used is 11a
if ( csrIs11hSupported( pMac ) && pAP_capabilityInfo->spectrumMgt && eSIR_11A_NW_TYPE == pBssDescription->nwType )
{
fTmp = (tAniBool)pal_cpu_to_be32(1);
}
else
fTmp = (tAniBool)0;
// corresponds to --- pMsg->spectrumMgtIndicator = ON;
vos_mem_copy(pBuf, (tANI_U8 *)&fTmp, sizeof(tAniBool));
pBuf += sizeof(tAniBool);
*pBuf++ = MIN_TX_PWR_CAP; // it is for pMsg->powerCap.minTxPower = 0;
found = csrSearchChannelListForTxPower(pMac, pBssDescription, &channelGroup);
// This is required for 11k test VoWiFi Ent: Test 2.
// We need the power capabilities for Assoc Req.
// This macro is provided by the halPhyCfg.h. We pick our
// max and min capability by the halPhy provided macros
pwrLimit = csrGetCfgMaxTxPower (pMac, pBssDescription->channelId);
if (0 != pwrLimit)
{
*pBuf++ = pwrLimit;
}
else
{
*pBuf++ = MAX_TX_PWR_CAP;
}
size = sizeof(pMac->roam.validChannelList);
if(HAL_STATUS_SUCCESS(csrGetCfgValidChannels(pMac, (tANI_U8 *)pMac->roam.validChannelList, &size)))
{
tANI_U8 *actualSize = pBuf++;
*actualSize = 0;
for ( i = 0; i < size; i++)
{
/* Only add 5ghz channels*/
if (CSR_IS_CHANNEL_5GHZ(pMac->roam.validChannelList[ i ]))
{
*actualSize +=1;
*pBuf++ = pMac->roam.validChannelList[ i ];
}
}
}
else
{
smsLog(pMac, LOGE, FL("can not find any valid channel"));
*pBuf++ = 0; //tSirSupChnl->numChnl
}
//Check whether it is ok to enter UAPSD
#ifndef WLAN_MDM_CODE_REDUCTION_OPT
if( btcIsReadyForUapsd(pMac) )
#endif /* WLAN_MDM_CODE_REDUCTION_OPT*/
{
*pBuf++ = uapsdMask;
}
#ifndef WLAN_MDM_CODE_REDUCTION_OPT
else
{
smsLog(pMac, LOGE, FL(" BTC doesn't allow UAPSD for uapsd_mask(0x%X)"), uapsdMask);
*pBuf++ = 0;
}
#endif /* WLAN_MDM_CODE_REDUCTION_OPT*/
// move the entire BssDescription into the join request.
vos_mem_copy(pBuf, pBssDescription,
pBssDescription->length + sizeof( pBssDescription->length ));
pBuf += pBssDescription->length + sizeof( pBssDescription->length ); // update to new location
}
/*
* The communication between HDD and LIM is thru mailbox (MB).
* Both sides will access the data structure "tSirSmeJoinReq".
* The rule is, while the components of "tSirSmeJoinReq" can be accessed in the regular way like tSirSmeJoinReq.assocType, this guideline
* stops at component tSirRSNie; any acces to the components after tSirRSNie is forbidden because the space from tSirRSNie is quueezed
* with the component "tSirBssDescription". And since the size of actual 'tSirBssDescription' varies, the receiving side (which is the routine
* limJoinReqSerDes() of limSerDesUtils.cc) should keep in mind not to access the components DIRECTLY after tSirRSNie.
*/
eHalStatus csrSendJoinReqMsg( tpAniSirGlobal pMac, tANI_U32 sessionId, tSirBssDescription *pBssDescription,
tCsrRoamProfile *pProfile, tDot11fBeaconIEs *pIes, tANI_U16 messageType )
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tSirSmeJoinReq *pMsg;
tANI_U8 *pBuf;
v_U8_t acm_mask = 0, uapsd_mask;
tANI_U16 msgLen, wTmp, ieLen;
tSirMacRateSet OpRateSet;
tSirMacRateSet ExRateSet;
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
tANI_U32 dwTmp;
tANI_U8 wpaRsnIE[DOT11F_IE_RSN_MAX_LEN]; //RSN MAX is bigger than WPA MAX
tANI_U32 ucDot11Mode = 0;
tANI_U8 txBFCsnValue = 0;
tANI_U16 rateBitmap = 0;
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return eHAL_STATUS_FAILURE;
}
/* To satisfy klockworks */
if (NULL == pBssDescription)
{
smsLog(pMac, LOGE, FL(" pBssDescription is NULL"));
return eHAL_STATUS_FAILURE;
}
do {
pSession->joinFailStatusCode.statusCode = eSIR_SME_SUCCESS;
pSession->joinFailStatusCode.reasonCode = 0;
vos_mem_copy (&pSession->joinFailStatusCode.bssId, &pBssDescription->bssId, sizeof(tSirMacAddr));
// There are a number of variable length fields to consider. First, the tSirSmeJoinReq
// includes a single bssDescription. bssDescription includes a single tANI_U32 for the
// IE fields, but the length field in the bssDescription needs to be interpreted to
// determine length of the IE fields.
//
// So, take the size of the JoinReq, subtract the size of the bssDescription and
// add in the length from the bssDescription (then add the size of the 'length' field
// itself because that is NOT included in the length field).
msgLen = sizeof( tSirSmeJoinReq ) - sizeof( *pBssDescription ) +
pBssDescription->length + sizeof( pBssDescription->length ) +
sizeof( tCsrWpaIe ) + sizeof( tCsrWpaAuthIe ) + sizeof( tANI_U16 ); // add in the size of the WPA IE that we may build.
pMsg = vos_mem_malloc(msgLen);
if (NULL == pMsg)
status = eHAL_STATUS_FAILURE;
else
status = eHAL_STATUS_SUCCESS;
if ( !HAL_STATUS_SUCCESS(status) ) break;
vos_mem_set(pMsg, msgLen , 0);
pMsg->messageType = pal_cpu_to_be16((tANI_U16)messageType);
pMsg->length = pal_cpu_to_be16(msgLen);
pBuf = &pMsg->sessionId;
// sessionId
*pBuf = (tANI_U8)sessionId;
pBuf++;
// transactionId
*pBuf = 0;
*( pBuf + 1 ) = 0;
pBuf += sizeof(tANI_U16);
// ssId
if( pIes->SSID.present && pIes->SSID.num_ssid )
{
// ssId len
*pBuf = pIes->SSID.num_ssid;
pBuf++;
vos_mem_copy(pBuf, pIes->SSID.ssid, pIes->SSID.num_ssid);
pBuf += pIes->SSID.num_ssid;
}
else
{
*pBuf = 0;
pBuf++;
}
// selfMacAddr
vos_mem_copy((tSirMacAddr *)pBuf, &pSession->selfMacAddr,
sizeof(tSirMacAddr));
pBuf += sizeof(tSirMacAddr);
// bsstype
dwTmp = pal_cpu_to_be32( csrTranslateBsstypeToMacType( pProfile->BSSType ) );
if (dwTmp == eSIR_BTAMP_STA_MODE) dwTmp = eSIR_BTAMP_AP_MODE; // Override BssType for BTAMP
vos_mem_copy(pBuf, &dwTmp, sizeof(tSirBssType));
pBuf += sizeof(tSirBssType);
// dot11mode
ucDot11Mode = csrTranslateToWNICfgDot11Mode( pMac, pSession->bssParams.uCfgDot11Mode );
if (pBssDescription->channelId <= 14 &&
FALSE == pMac->roam.configParam.enableVhtFor24GHz &&
WNI_CFG_DOT11_MODE_11AC == ucDot11Mode)
{
//Need to disable VHT operation in 2.4 GHz band
ucDot11Mode = WNI_CFG_DOT11_MODE_11N;
}
smsLog(pMac, LOG1, FL("dot11mode %d uCfgDot11Mode %d"),
ucDot11Mode, pSession->bssParams.uCfgDot11Mode);
*pBuf = (tANI_U8)ucDot11Mode;
pBuf++;
//Persona
*pBuf = (tANI_U8)pProfile->csrPersona;
pBuf++;
*pBuf = (tANI_U8)pProfile->bOSENAssociation;
pBuf++;
*pBuf = (tANI_U8)pProfile->bWPSAssociation;
pBuf++;
//CBMode
*pBuf = (tANI_U8)pSession->bssParams.cbMode;
pBuf++;
*pBuf = (tANI_U8)pProfile->force_24ghz_in_ht20;
pBuf++;
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
FL("CSR PERSONA=%d CSR CbMode %d force_24ghz_in_ht20 %d"),
pProfile->csrPersona, pSession->bssParams.cbMode,
pProfile->force_24ghz_in_ht20);
// uapsdPerAcBitmask
*pBuf = pProfile->uapsd_mask;
pBuf++;
status = csrGetRateSet(pMac, pProfile, (eCsrPhyMode)pProfile->phyMode, pBssDescription, pIes, &OpRateSet, &ExRateSet,&rateBitmap);
if (HAL_STATUS_SUCCESS(status) )
{
// OperationalRateSet
if (OpRateSet.numRates) {
*pBuf++ = OpRateSet.numRates;
vos_mem_copy(pBuf, OpRateSet.rate, OpRateSet.numRates);
pBuf += OpRateSet.numRates;
} else *pBuf++ = 0;
// ExtendedRateSet
if (ExRateSet.numRates) {
*pBuf++ = ExRateSet.numRates;
vos_mem_copy(pBuf, ExRateSet.rate, ExRateSet.numRates);
pBuf += ExRateSet.numRates;
} else *pBuf++ = 0;
}
else
{
*pBuf++ = 0;
*pBuf++ = 0;
}
//rateBitmap
vos_mem_copy(pBuf, &rateBitmap, sizeof(tANI_U16));
pBuf += sizeof(tANI_U16);
// rsnIE
if ( csrIsProfileWpa( pProfile ) )
{
// Insert the Wpa IE into the join request
ieLen = csrRetrieveWpaIe( pMac, pProfile, pBssDescription, pIes,
(tCsrWpaIe *)( wpaRsnIE ) );
}
else if( csrIsProfileRSN( pProfile ) )
{
// Insert the RSN IE into the join request
ieLen = csrRetrieveRsnIe( pMac, sessionId, pProfile, pBssDescription, pIes,
(tCsrRSNIe *)( wpaRsnIE ) );
pMsg->force_rsne_override =
pProfile->force_rsne_override;
}
#ifdef FEATURE_WLAN_WAPI
else if( csrIsProfileWapi( pProfile ) )
{
// Insert the WAPI IE into the join request
ieLen = csrRetrieveWapiIe( pMac, sessionId, pProfile, pBssDescription, pIes,
(tCsrWapiIe *)( wpaRsnIE ) );
}
#endif /* FEATURE_WLAN_WAPI */
else
{
ieLen = 0;
}
//remember the IE for future use
if( ieLen )
{
if(ieLen > DOT11F_IE_RSN_MAX_LEN)
{
smsLog(pMac, LOGE, FL(" WPA RSN IE length :%d is more than DOT11F_IE_RSN_MAX_LEN, resetting to %d"), ieLen, DOT11F_IE_RSN_MAX_LEN);
ieLen = DOT11F_IE_RSN_MAX_LEN;
}
#ifdef FEATURE_WLAN_WAPI
if( csrIsProfileWapi( pProfile ) )
{
//Check whether we need to allocate more memory
if(ieLen > pSession->nWapiReqIeLength)
{
if(pSession->pWapiReqIE && pSession->nWapiReqIeLength)
{
vos_mem_free(pSession->pWapiReqIE);
}
pSession->pWapiReqIE = vos_mem_malloc(ieLen);
if (NULL == pSession->pWapiReqIE)
status = eHAL_STATUS_FAILURE;
else
status = eHAL_STATUS_SUCCESS;
if(!HAL_STATUS_SUCCESS(status)) break;
}
pSession->nWapiReqIeLength = ieLen;
vos_mem_copy(pSession->pWapiReqIE, wpaRsnIE, ieLen);
wTmp = pal_cpu_to_be16( ieLen );
vos_mem_copy(pBuf, &wTmp, sizeof(tANI_U16));
pBuf += sizeof(tANI_U16);
vos_mem_copy(pBuf, wpaRsnIE, ieLen);
pBuf += ieLen;
}
else//should be WPA/WPA2 otherwise
#endif /* FEATURE_WLAN_WAPI */
{
//Check whether we need to allocate more memory
if(ieLen > pSession->nWpaRsnReqIeLength)
{
if(pSession->pWpaRsnReqIE && pSession->nWpaRsnReqIeLength)
{
vos_mem_free(pSession->pWpaRsnReqIE);
}
pSession->pWpaRsnReqIE = vos_mem_malloc(ieLen);
if (NULL == pSession->pWpaRsnReqIE)
status = eHAL_STATUS_FAILURE;
else
status = eHAL_STATUS_SUCCESS;
if(!HAL_STATUS_SUCCESS(status)) break;
}
pSession->nWpaRsnReqIeLength = ieLen;
vos_mem_copy(pSession->pWpaRsnReqIE, wpaRsnIE, ieLen);
wTmp = pal_cpu_to_be16( ieLen );
vos_mem_copy(pBuf, &wTmp, sizeof(tANI_U16));
pBuf += sizeof(tANI_U16);
vos_mem_copy(pBuf, wpaRsnIE, ieLen);
pBuf += ieLen;
}
}
else
{
//free whatever old info
pSession->nWpaRsnReqIeLength = 0;
if(pSession->pWpaRsnReqIE)
{
vos_mem_free(pSession->pWpaRsnReqIE);
pSession->pWpaRsnReqIE = NULL;
}
#ifdef FEATURE_WLAN_WAPI
pSession->nWapiReqIeLength = 0;
if(pSession->pWapiReqIE)
{
vos_mem_free(pSession->pWapiReqIE);
pSession->pWapiReqIE = NULL;
}
#endif /* FEATURE_WLAN_WAPI */
//length is two bytes
*pBuf = 0;
*(pBuf + 1) = 0;
pBuf += 2;
}
#ifdef FEATURE_WLAN_ESE
if( eWNI_SME_JOIN_REQ == messageType )
{
// Never include the cckmIE in an Join Request
//length is two bytes
*pBuf = 0;
*(pBuf + 1) = 0;
pBuf += 2;
}
else if(eWNI_SME_REASSOC_REQ == messageType )
{
// cckmIE
if( csrIsProfileESE( pProfile ) )
{
// Insert the CCKM IE into the join request
#ifdef FEATURE_WLAN_ESE_UPLOAD
ieLen = pSession->suppCckmIeInfo.cckmIeLen;
vos_mem_copy((void *) (wpaRsnIE),
pSession->suppCckmIeInfo.cckmIe, ieLen);
#else
ieLen = csrConstructEseCckmIe( pMac,
pSession,
pProfile,
pBssDescription,
pSession->pWpaRsnReqIE,
pSession->nWpaRsnReqIeLength,
(void *)( wpaRsnIE ) );
#endif /* FEATURE_WLAN_ESE_UPLOAD */
}
else
{
ieLen = 0;
}
//If present, copy the IE into the eWNI_SME_REASSOC_REQ message buffer
if( ieLen )
{
//Copy the CCKM IE over from the temp buffer (wpaRsnIE)
wTmp = pal_cpu_to_be16( ieLen );
vos_mem_copy(pBuf, &wTmp, sizeof(tANI_U16));
pBuf += sizeof(tANI_U16);
vos_mem_copy(pBuf, wpaRsnIE, ieLen);
pBuf += ieLen;
}
else
{
//Indicate you have no CCKM IE
//length is two bytes
*pBuf = 0;
*(pBuf + 1) = 0;
pBuf += 2;
}
}
#endif /* FEATURE_WLAN_ESE */
// addIEScan
if (pProfile->nAddIEScanLength)
{
ieLen = pProfile->nAddIEScanLength;
memset(pSession->addIEScan, 0 , pSession->nAddIEScanLength);
pSession->nAddIEScanLength = ieLen;
vos_mem_copy(pSession->addIEScan, pProfile->addIEScan, ieLen);
wTmp = pal_cpu_to_be16( ieLen );
vos_mem_copy(pBuf, &wTmp, sizeof(tANI_U16));
pBuf += sizeof(tANI_U16);
vos_mem_copy(pBuf, pProfile->addIEScan, ieLen);
pBuf += ieLen;
}
else
{
memset(pSession->addIEScan, 0, pSession->nAddIEScanLength);
pSession->nAddIEScanLength = 0;
*pBuf = 0;
*(pBuf + 1) = 0;
pBuf += 2;
}
// addIEAssoc
if(pProfile->nAddIEAssocLength && pProfile->pAddIEAssoc)
{
ieLen = pProfile->nAddIEAssocLength;
if(ieLen > pSession->nAddIEAssocLength)
{
if(pSession->pAddIEAssoc && pSession->nAddIEAssocLength)
{
vos_mem_free(pSession->pAddIEAssoc);
}
pSession->pAddIEAssoc = vos_mem_malloc(ieLen);
if (NULL == pSession->pAddIEAssoc)
status = eHAL_STATUS_FAILURE;
else
status = eHAL_STATUS_SUCCESS;
if(!HAL_STATUS_SUCCESS(status)) break;
}
pSession->nAddIEAssocLength = ieLen;
vos_mem_copy(pSession->pAddIEAssoc, pProfile->pAddIEAssoc, ieLen);
wTmp = pal_cpu_to_be16( ieLen );
vos_mem_copy(pBuf, &wTmp, sizeof(tANI_U16));
pBuf += sizeof(tANI_U16);
vos_mem_copy(pBuf, pProfile->pAddIEAssoc, ieLen);
pBuf += ieLen;
}
else
{
pSession->nAddIEAssocLength = 0;
if(pSession->pAddIEAssoc)
{
vos_mem_free(pSession->pAddIEAssoc);
pSession->pAddIEAssoc = NULL;
}
*pBuf = 0;
*(pBuf + 1) = 0;
pBuf += 2;
}
if(eWNI_SME_REASSOC_REQ == messageType )
{
//Unmask any AC in reassoc that is ACM-set
uapsd_mask = (v_U8_t)pProfile->uapsd_mask;
if( uapsd_mask && ( NULL != pBssDescription ) )
{
if( CSR_IS_QOS_BSS(pIes) && CSR_IS_UAPSD_BSS(pIes) )
{
#ifndef WLAN_MDM_CODE_REDUCTION_OPT
acm_mask = sme_QosGetACMMask(pMac, pBssDescription, pIes);
#endif /* WLAN_MDM_CODE_REDUCTION_OPT*/
}
else
{
uapsd_mask = 0;
}
}
}
dwTmp = pal_cpu_to_be32( csrTranslateEncryptTypeToEdType( pProfile->negotiatedUCEncryptionType) );
vos_mem_copy(pBuf, &dwTmp, sizeof(tANI_U32));
pBuf += sizeof(tANI_U32);
dwTmp = pal_cpu_to_be32( csrTranslateEncryptTypeToEdType( pProfile->negotiatedMCEncryptionType) );
vos_mem_copy(pBuf, &dwTmp, sizeof(tANI_U32));
pBuf += sizeof(tANI_U32);
#ifdef WLAN_FEATURE_11W
//MgmtEncryption
if (pProfile->MFPEnabled)
{
dwTmp = pal_cpu_to_be32(eSIR_ED_AES_128_CMAC);
}
else
{
dwTmp = pal_cpu_to_be32(eSIR_ED_NONE);
}
vos_mem_copy(pBuf, &dwTmp, sizeof(tANI_U32));
pBuf += sizeof(tANI_U32);
#endif
#ifdef WLAN_FEATURE_VOWIFI_11R
pProfile->MDID.mdiePresent = pBssDescription->mdiePresent;
if (csrIsProfile11r( pProfile )
#ifdef FEATURE_WLAN_ESE
&& !((pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_OPEN_SYSTEM) &&
(pIes->ESEVersion.present) && (pMac->roam.configParam.isEseIniFeatureEnabled))
#endif
)
{
// is11Rconnection;
dwTmp = pal_cpu_to_be32(TRUE);
vos_mem_copy(pBuf, &dwTmp, sizeof(tAniBool)) ;
pBuf += sizeof(tAniBool);
}
else
{
// is11Rconnection;
dwTmp = pal_cpu_to_be32(FALSE);
vos_mem_copy(pBuf, &dwTmp, sizeof(tAniBool));
pBuf += sizeof(tAniBool);
}
#endif
#ifdef FEATURE_WLAN_ESE
// isESEFeatureIniEnabled
if (TRUE == pMac->roam.configParam.isEseIniFeatureEnabled)
{
dwTmp = pal_cpu_to_be32(TRUE);
vos_mem_copy(pBuf, &dwTmp, sizeof(tAniBool));
pBuf += sizeof(tAniBool);
}
else
{
dwTmp = pal_cpu_to_be32(FALSE);
vos_mem_copy(pBuf, &dwTmp, sizeof(tAniBool));
pBuf += sizeof(tAniBool);
}
/* A profile can not be both ESE and 11R. But an 802.11R AP
* may be advertising support for ESE as well. So if we are
* associating Open or explicitly ESE then we will get ESE.
* If we are associating explictly 11R only then we will get
* 11R.
*/
if ((csrIsProfileESE(pProfile) ||
((pIes->ESEVersion.present)
&& ((pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_OPEN_SYSTEM)
|| (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_WPA)
|| (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_WPA_PSK)
|| (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_RSN)
#ifdef WLAN_FEATURE_11W
|| (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_RSN_PSK_SHA256)
|| (pProfile->negotiatedAuthType ==
eCSR_AUTH_TYPE_RSN_8021X_SHA256)
#endif
|| (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_RSN_PSK))))
&& (pMac->roam.configParam.isEseIniFeatureEnabled))
{
// isESEconnection;
dwTmp = pal_cpu_to_be32(TRUE);
vos_mem_copy(pBuf, &dwTmp, sizeof(tAniBool));
pBuf += sizeof(tAniBool);
}
else
{
//isESEconnection;
dwTmp = pal_cpu_to_be32(FALSE);
vos_mem_copy(pBuf, &dwTmp, sizeof(tAniBool));
pBuf += sizeof(tAniBool);
}
if (eWNI_SME_JOIN_REQ == messageType)
{
tESETspecInfo eseTspec;
// ESE-Tspec IEs in the ASSOC request is presently not supported
// so nullify the TSPEC parameters
vos_mem_set(&eseTspec, sizeof(tESETspecInfo), 0);
vos_mem_copy(pBuf, &eseTspec, sizeof(tESETspecInfo));
pBuf += sizeof(tESETspecInfo);
}
else if (eWNI_SME_REASSOC_REQ == messageType)
{
if ((csrIsProfileESE(pProfile) ||
((pIes->ESEVersion.present)
&& ((pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_OPEN_SYSTEM)
|| (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_WPA)
|| (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_WPA_PSK)
|| (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_RSN)
#ifdef WLAN_FEATURE_11W
|| (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_RSN_PSK_SHA256)
|| (pProfile->negotiatedAuthType ==
eCSR_AUTH_TYPE_RSN_8021X_SHA256)
#endif
|| (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_RSN_PSK))))
&& (pMac->roam.configParam.isEseIniFeatureEnabled))
{
tESETspecInfo eseTspec;
// ESE Tspec information
vos_mem_set(&eseTspec, sizeof(tESETspecInfo), 0);
eseTspec.numTspecs = sme_QosESERetrieveTspecInfo(pMac, sessionId, (tTspecInfo *) &eseTspec.tspec[0]);
*pBuf = eseTspec.numTspecs;
pBuf += sizeof(tANI_U8);
// Copy the TSPEC information only if present
if (eseTspec.numTspecs) {
vos_mem_copy(pBuf, (void*)&eseTspec.tspec[0],
(eseTspec.numTspecs*sizeof(tTspecInfo)));
}
pBuf += sizeof(eseTspec.tspec);
}
else
{
tESETspecInfo eseTspec;
// ESE-Tspec IEs in the ASSOC request is presently not supported
// so nullify the TSPEC parameters
vos_mem_set(&eseTspec, sizeof(tESETspecInfo), 0);
vos_mem_copy(pBuf, &eseTspec, sizeof(tESETspecInfo));
pBuf += sizeof(tESETspecInfo);
}
}
#endif // FEATURE_WLAN_ESE
#if defined WLAN_FEATURE_VOWIFI_11R || defined FEATURE_WLAN_ESE || defined(FEATURE_WLAN_LFR)
// Fill in isFastTransitionEnabled
if (pMac->roam.configParam.isFastTransitionEnabled
#ifdef FEATURE_WLAN_LFR
|| csrRoamIsFastRoamEnabled(pMac, sessionId)
#endif
)
{
dwTmp = pal_cpu_to_be32(TRUE);
vos_mem_copy(pBuf, &dwTmp, sizeof(tAniBool));
pBuf += sizeof(tAniBool);
}
else
{
dwTmp = pal_cpu_to_be32(FALSE);
vos_mem_copy(pBuf, &dwTmp, sizeof(tAniBool));
pBuf += sizeof(tAniBool);
}
#endif
#ifdef FEATURE_WLAN_LFR
if(csrRoamIsFastRoamEnabled(pMac, sessionId))
{
//legacy fast roaming enabled
dwTmp = pal_cpu_to_be32(TRUE);
vos_mem_copy(pBuf, &dwTmp, sizeof(tAniBool));
pBuf += sizeof(tAniBool);
}
else
{
dwTmp = pal_cpu_to_be32(FALSE);
vos_mem_copy(pBuf, &dwTmp, sizeof(tAniBool));
pBuf += sizeof(tAniBool);
}
#endif
// txLdpcIniFeatureEnabled
*pBuf = (tANI_U8)pMac->roam.configParam.txLdpcEnable;
pBuf++;
if ((csrIs11hSupported (pMac)) && (CSR_IS_CHANNEL_5GHZ(pBssDescription->channelId)) &&
(pIes->Country.present) && (!pMac->roam.configParam.fSupplicantCountryCodeHasPriority))
{
csrSaveToChannelPower2G_5G( pMac, pIes->Country.num_triplets * sizeof(tSirMacChanInfo),
(tSirMacChanInfo *)(&pIes->Country.triplets[0]) );
csrApplyPower2Current(pMac);
}
#ifdef WLAN_FEATURE_11AC
// txBFIniFeatureEnabled
*pBuf = (tANI_U8)pMac->roam.configParam.txBFEnable;
pBuf++;
// txBFCsnValue
if (IS_BSS_VHT_CAPABLE(pIes->VHTCaps))
{
txBFCsnValue = (tANI_U8)pMac->roam.configParam.txBFCsnValue;
if (pIes->VHTCaps.numSoundingDim)
txBFCsnValue = CSR_ROAM_MIN
(txBFCsnValue, pIes->VHTCaps.numSoundingDim);
}
*pBuf = txBFCsnValue;
pBuf++;
/* Only enable MuBf if no other MuBF session exist
* and FW and HOST is MuBF capable.
*/
if ( IS_MUMIMO_BFORMEE_CAPABLE && (FALSE == pMac->isMuBfsessionexist) )
{
*pBuf = (tANI_U8)pMac->roam.configParam.txMuBformee;
pBuf++;
}
else
{
*pBuf = 0;
pBuf++;
}
#endif
*pBuf = (tANI_U8)pMac->roam.configParam.isAmsduSupportInAMPDU;
pBuf++;
// WME
if(pMac->roam.roamSession[sessionId].fWMMConnection)
{
//WME enabled
dwTmp = pal_cpu_to_be32(TRUE);
vos_mem_copy(pBuf, &dwTmp, sizeof(tAniBool));
pBuf += sizeof(tAniBool);
}
else
{
dwTmp = pal_cpu_to_be32(FALSE);
vos_mem_copy(pBuf, &dwTmp, sizeof(tAniBool));
pBuf += sizeof(tAniBool);
}
// QOS
if(pMac->roam.roamSession[sessionId].fQOSConnection)
{
//QOS enabled
dwTmp = pal_cpu_to_be32(TRUE);
vos_mem_copy(pBuf, &dwTmp, sizeof(tAniBool));
pBuf += sizeof(tAniBool);
}
else
{
dwTmp = pal_cpu_to_be32(FALSE);
vos_mem_copy(pBuf, &dwTmp, sizeof(tAniBool));
pBuf += sizeof(tAniBool);
}
//BssDesc
csrPrepareJoinReassocReqBuffer( pMac, pBssDescription, pBuf,
(tANI_U8)pProfile->uapsd_mask);
status = palSendMBMessage(pMac->hHdd, pMsg );
/* Memory allocated to pMsg will get free'd in palSendMBMessage */
pMsg = NULL;
if(!HAL_STATUS_SUCCESS(status))
{
break;
}
else
{
#ifndef WLAN_MDM_CODE_REDUCTION_OPT
if (eWNI_SME_JOIN_REQ == messageType)
{
//Tush-QoS: notify QoS module that join happening
sme_QosCsrEventInd(pMac, (v_U8_t)sessionId, SME_QOS_CSR_JOIN_REQ, NULL);
}
else if (eWNI_SME_REASSOC_REQ == messageType)
{
//Tush-QoS: notify QoS module that reassoc happening
sme_QosCsrEventInd(pMac, (v_U8_t)sessionId, SME_QOS_CSR_REASSOC_REQ, NULL);
}
#endif
}
} while( 0 );
if (pMsg != NULL)
{
vos_mem_free( pMsg );
}
pMac->roam.roamSession[sessionId].connect_req_start_time =
vos_timer_get_system_time();
return( status );
}
#ifdef WLAN_FEATURE_LFR_MBB
/**
* csr_prepare_reassoc_req () - Prepares reassoc request
* @mac: MAC context
* @session_id: session id
* @pbss_description: bss description
* @ies: pointer to beacon IE's
* @reassoc_req: pointer to reassociation request
*
*Return: None
*/
eHalStatus csr_fill_reassoc_req(tpAniSirGlobal mac, tANI_U32 session_id,
tSirBssDescription *bss_description, tDot11fBeaconIEs *ies,
tSirSmeJoinReq **reassoc_req)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tSirSmeJoinReq *csr_join_req;
tANI_U8 *buf;
v_U8_t acm_mask = 0, uapsd_mask;
tANI_U16 msg_len, w_tmp, ie_len;
tSirMacRateSet op_rate_set;
tSirMacRateSet ex_rate_set;
tCsrRoamSession *session = CSR_GET_SESSION(mac, session_id);
tANI_U32 dw_tmp;
tANI_U8 wpa_rsn_ie[DOT11F_IE_RSN_MAX_LEN];
tANI_U32 uc_dot11_mode = 0;
tANI_U8 tx_bf_csn_value = 0;
tANI_U16 rate_bitmap = 0;
tANI_U16 message_type = eWNI_SME_REASSOC_REQ;
tCsrRoamProfile *profile;
if(!session) {
smsLog(mac, LOGE, FL(" session %d not found "), session_id);
return eHAL_STATUS_FAILURE;
}
if (NULL == bss_description) {
smsLog(mac, LOGE, FL(" pBssDescription is NULL"));
return eHAL_STATUS_FAILURE;
}
smsLog(mac, LOG1,
FL("session_id %d"), session_id);
profile = vos_mem_malloc(sizeof(*profile));
if (NULL == profile) {
smsLog(mac, LOGE, FL("Memory allocation failure for profile"));
return eHAL_STATUS_RESOURCES;
}
status = csrRoamCopyProfile(mac, profile, session->pCurRoamProfile);
if(!HAL_STATUS_SUCCESS(status)) {
smsLog(mac, LOGE, FL("Profile copy failed"));
return eHAL_STATUS_FAILURE;
}
do {
/*
* There are a number of variable length fields to consider.
* First, the tSirSmeJoinReq includes a single bssDescription.
* bssDescription includes a single tANI_U32 for the IE fields,
* but the length field in the bssDescription needs to be
* interpreted to determine length of the IE fields.
* So, take the size of the JoinReq, subtract the size of the
* bssDescription and add in the length from the bssDescription
* (then add the size of the 'length' field itself because that is
* NOT included in the length field). msgLen =
* sizeof( tSirSmeJoinReq ) - sizeof( *pBssDescription ) +
* pBssDescription->length + sizeof( pBssDescription->length ) +
* sizeof( tCsrWpaIe ) + sizeof( tCsrWpaAuthIe ) + sizeof( tANI_U16 );
* add in the size of the WPA IE that we may build.
*/
msg_len = sizeof(tSirSmeJoinReq) - sizeof(*bss_description) +
bss_description->length + sizeof(bss_description->length) +
sizeof(tCsrWpaIe) + sizeof(tCsrWpaAuthIe) + sizeof(tANI_U16);
csr_join_req = vos_mem_malloc(msg_len);
if (NULL == csr_join_req)
status = eHAL_STATUS_FAILURE;
else
status = eHAL_STATUS_SUCCESS;
if (!HAL_STATUS_SUCCESS(status)) break;
vos_mem_set(csr_join_req, msg_len, 0);
*reassoc_req = csr_join_req;
csr_join_req->messageType = pal_cpu_to_be16(eWNI_SME_REASSOC_REQ);
csr_join_req->length = pal_cpu_to_be16(msg_len);
buf = &csr_join_req->sessionId;
/* session_id */
*buf = (tANI_U8)session_id;
buf++;
/* transactionId */
*buf = 0;
*(buf + 1) = 0;
buf += sizeof(tANI_U16);
/* ssId */
if(ies->SSID.present && ies->SSID.num_ssid)
{
/* ssId len */
*buf = ies->SSID.num_ssid;
buf++;
vos_mem_copy(buf, ies->SSID.ssid, ies->SSID.num_ssid);
buf += ies->SSID.num_ssid;
}
else
{
*buf = 0;
buf++;
}
/* selfMacAddr */
vos_mem_copy((tSirMacAddr *)buf, &session->selfMacAddr,
sizeof(tSirMacAddr));
buf += sizeof(tSirMacAddr);
/* bsstype */
dw_tmp =
pal_cpu_to_be32(csrTranslateBsstypeToMacType(profile->BSSType));
/* Override BssType for BTAMP */
if (dw_tmp == eSIR_BTAMP_STA_MODE) dw_tmp = eSIR_BTAMP_AP_MODE;
vos_mem_copy(buf, &dw_tmp, sizeof(tSirBssType));
buf += sizeof(tSirBssType);
/* dot11mode */
uc_dot11_mode =
csrTranslateToWNICfgDot11Mode(mac, session->bssParams.uCfgDot11Mode);
if (bss_description->channelId <= 14 &&
FALSE == mac->roam.configParam.enableVhtFor24GHz &&
WNI_CFG_DOT11_MODE_11AC == uc_dot11_mode)
{
/* Need to disable VHT operation in 2.4 GHz band */
uc_dot11_mode = WNI_CFG_DOT11_MODE_11N;
}
*buf = (tANI_U8)uc_dot11_mode;
buf++;
/* Persona */
*buf = (tANI_U8)profile->csrPersona;
buf++;
*buf = (tANI_U8)profile->bOSENAssociation;
buf++;
*buf = (tANI_U8)profile->bWPSAssociation;
buf++;
/* CBMode */
*buf = (tANI_U8)session->bssParams.cbMode;
buf++;
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
FL("CSR PERSONA=%d CSR CbMode %d"), profile->csrPersona,
session->bssParams.cbMode);
/* uapsdPerAcBitmask */
*buf = profile->uapsd_mask;
buf++;
status = csrGetRateSet(mac, profile, (eCsrPhyMode)profile->phyMode,
bss_description, ies, &op_rate_set, &ex_rate_set,&rate_bitmap);
if (HAL_STATUS_SUCCESS(status))
{
/* OperationalRateSet */
if (op_rate_set.numRates) {
*buf++ = op_rate_set.numRates;
vos_mem_copy(buf, op_rate_set.rate, op_rate_set.numRates);
buf += op_rate_set.numRates;
} else *buf++ = 0;
/* ExtendedRateSet */
if (ex_rate_set.numRates) {
*buf++ = ex_rate_set.numRates;
vos_mem_copy(buf, ex_rate_set.rate, ex_rate_set.numRates);
buf += ex_rate_set.numRates;
} else *buf++ = 0;
}
else
{
*buf++ = 0;
*buf++ = 0;
}
/* rateBitmap */
vos_mem_copy(buf, &rate_bitmap, sizeof(tANI_U16));
buf += sizeof(tANI_U16);
profile->negotiatedAuthType =
mac->roam.roamSession[session_id].connectedProfile.AuthType;
profile->negotiatedUCEncryptionType =
mac->roam.roamSession[session_id].connectedProfile.EncryptionType;
/* rsnIE */
if ( csrIsProfileWpa(profile))
{
/* Insert the Wpa IE into the join request */
ie_len = csrRetrieveWpaIe(mac, profile, bss_description, ies,
(tCsrWpaIe *)(wpa_rsn_ie));
}
else if( csrIsProfileRSN(profile))
{
/* Insert the RSN IE into the join request */
ie_len = csrRetrieveRsnIe(mac, session_id, profile, bss_description,
ies, (tCsrRSNIe *)(wpa_rsn_ie));
}
#ifdef FEATURE_WLAN_WAPI
else if( csrIsProfileWapi(profile))
{
/* Insert the WAPI IE into the join request */
ie_len = csrRetrieveWapiIe(mac, session_id, profile,
bss_description, ies, (tCsrWapiIe *)(wpa_rsn_ie));
}
#endif
else
{
ie_len = 0;
}
/* remember the IE for future use */
if(ie_len)
{
if(ie_len > DOT11F_IE_RSN_MAX_LEN)
{
smsLog(mac, LOGE,
FL("WPA RSN IE length :%d is more than RSN_MAX_LEN %d"),
ie_len, DOT11F_IE_RSN_MAX_LEN);
ie_len = DOT11F_IE_RSN_MAX_LEN;
}
#ifdef FEATURE_WLAN_WAPI
if( csrIsProfileWapi(profile))
{
/* Check whether we need to allocate more memory */
if(ie_len > session->nWapiReqIeLength)
{
if(session->pWapiReqIE && session->nWapiReqIeLength)
{
vos_mem_free(session->pWapiReqIE);
}
session->pWapiReqIE = vos_mem_malloc(ie_len);
if (NULL == session->pWapiReqIE)
status = eHAL_STATUS_FAILURE;
else
status = eHAL_STATUS_SUCCESS;
if(!HAL_STATUS_SUCCESS(status)) break;
}
session->nWapiReqIeLength = ie_len;
vos_mem_copy(session->pWapiReqIE, wpa_rsn_ie, ie_len);
w_tmp = pal_cpu_to_be16(ie_len);
vos_mem_copy(buf, &w_tmp, sizeof(tANI_U16));
buf += sizeof(tANI_U16);
vos_mem_copy(buf, wpa_rsn_ie, ie_len);
buf += ie_len;
}
else /* should be WPA/WPA2 otherwise */
#endif
{
/* Check whether we need to allocate more memory */
if(ie_len > session->nWpaRsnReqIeLength)
{
if(session->pWpaRsnReqIE && session->nWpaRsnReqIeLength)
{
vos_mem_free(session->pWpaRsnReqIE);
}
session->pWpaRsnReqIE = vos_mem_malloc(ie_len);
if (NULL == session->pWpaRsnReqIE)
status = eHAL_STATUS_FAILURE;
else
status = eHAL_STATUS_SUCCESS;
if(!HAL_STATUS_SUCCESS(status)) break;
}
session->nWpaRsnReqIeLength = ie_len;
vos_mem_copy(session->pWpaRsnReqIE, wpa_rsn_ie, ie_len);
w_tmp = pal_cpu_to_be16(ie_len);
vos_mem_copy(buf, &w_tmp, sizeof(tANI_U16));
buf += sizeof(tANI_U16);
vos_mem_copy(buf, wpa_rsn_ie, ie_len);
buf += ie_len;
}
}
else
{
/* free whatever old info */
session->nWpaRsnReqIeLength = 0;
if(session->pWpaRsnReqIE)
{
vos_mem_free(session->pWpaRsnReqIE);
session->pWpaRsnReqIE = NULL;
}
#ifdef FEATURE_WLAN_WAPI
session->nWapiReqIeLength = 0;
if(session->pWapiReqIE)
{
vos_mem_free(session->pWapiReqIE);
session->pWapiReqIE = NULL;
}
#endif
/* length is two bytes */
*buf = 0;
*(buf + 1) = 0;
buf += 2;
}
#ifdef FEATURE_WLAN_ESE
if(eWNI_SME_JOIN_REQ == message_type)
{
/*
* Never include the cckmIE in an Join Request
* length is two bytes
*/
*buf = 0;
*(buf + 1) = 0;
buf += 2;
}
else if(eWNI_SME_REASSOC_REQ == message_type)
{
/* cckmIE */
if( csrIsProfileESE(profile))
{
/* Insert the CCKM IE into the join request */
#ifdef FEATURE_WLAN_ESE_UPLOAD
ie_len = session->suppCckmIeInfo.cckmIeLen;
vos_mem_copy((void *) (wpa_rsn_ie),
session->suppCckmIeInfo.cckmIe, ie_len);
#else
ie_len = csrConstructEseCckmIe(mac,
session,
profile,
bss_description,
session->pWpaRsnReqIE,
session->nWpaRsnReqIeLength,
(void *)(wpa_rsn_ie));
#endif
}
else
{
ie_len = 0;
}
/*
* If present, copy the IE into the eWNI_SME_REASSOC_REQ
* message buffer
*/
if(ie_len)
{
/* Copy the CCKM IE over from the temp buffer (wpaRsnIE) */
w_tmp = pal_cpu_to_be16(ie_len);
vos_mem_copy(buf, &w_tmp, sizeof(tANI_U16));
buf += sizeof(tANI_U16);
vos_mem_copy(buf, wpa_rsn_ie, ie_len);
buf += ie_len;
}
else
{
/* Indicate you have no CCKM IE length is two bytes */
*buf = 0;
*(buf + 1) = 0;
buf += 2;
}
}
#endif
/* addIEScan */
if (profile->nAddIEScanLength)
{
ie_len = profile->nAddIEScanLength;
memset(session->addIEScan, 0 , session->nAddIEScanLength);
session->nAddIEScanLength = ie_len;
vos_mem_copy(session->addIEScan, profile->addIEScan, ie_len);
w_tmp = pal_cpu_to_be16(ie_len);
vos_mem_copy(buf, &w_tmp, sizeof(tANI_U16));
buf += sizeof(tANI_U16);
vos_mem_copy(buf, profile->addIEScan, ie_len);
buf += ie_len;
}
else
{
memset(session->addIEScan, 0, session->nAddIEScanLength);
session->nAddIEScanLength = 0;
*buf = 0;
*(buf + 1) = 0;
buf += 2;
}
/* addIEAssoc */
if(profile->nAddIEAssocLength && profile->pAddIEAssoc)
{
ie_len = profile->nAddIEAssocLength;
if(ie_len > session->nAddIEAssocLength)
{
if(session->pAddIEAssoc && session->nAddIEAssocLength)
{
vos_mem_free(session->pAddIEAssoc);
}
session->pAddIEAssoc = vos_mem_malloc(ie_len);
if (NULL == session->pAddIEAssoc)
status = eHAL_STATUS_FAILURE;
else
status = eHAL_STATUS_SUCCESS;
if(!HAL_STATUS_SUCCESS(status)) break;
}
session->nAddIEAssocLength = ie_len;
vos_mem_copy(session->pAddIEAssoc, profile->pAddIEAssoc, ie_len);
w_tmp = pal_cpu_to_be16(ie_len);
vos_mem_copy(buf, &w_tmp, sizeof(tANI_U16));
buf += sizeof(tANI_U16);
vos_mem_copy(buf, profile->pAddIEAssoc, ie_len);
buf += ie_len;
}
else
{
session->nAddIEAssocLength = 0;
if(session->pAddIEAssoc)
{
vos_mem_free(session->pAddIEAssoc);
session->pAddIEAssoc = NULL;
}
*buf = 0;
*(buf + 1) = 0;
buf += 2;
}
if(eWNI_SME_REASSOC_REQ == message_type )
{
/*Unmask any AC in reassoc that is ACM-set */
uapsd_mask = (v_U8_t)profile->uapsd_mask;
if( uapsd_mask && (NULL != bss_description))
{
if( CSR_IS_QOS_BSS(ies) && CSR_IS_UAPSD_BSS(ies) )
{
#ifndef WLAN_MDM_CODE_REDUCTION_OPT
acm_mask = sme_QosGetACMMask(mac, bss_description, ies);
#endif
}
else
{
uapsd_mask = 0;
}
}
}
dw_tmp = pal_cpu_to_be32(csrTranslateEncryptTypeToEdType(
profile->negotiatedUCEncryptionType));
vos_mem_copy(buf, &dw_tmp, sizeof(tANI_U32));
buf += sizeof(tANI_U32);
dw_tmp = pal_cpu_to_be32(csrTranslateEncryptTypeToEdType(
profile->negotiatedMCEncryptionType));
vos_mem_copy(buf, &dw_tmp, sizeof(tANI_U32));
buf += sizeof(tANI_U32);
#ifdef WLAN_FEATURE_11W
/* MgmtEncryption */
if (profile->MFPEnabled)
{
dw_tmp = pal_cpu_to_be32(eSIR_ED_AES_128_CMAC);
}
else
{
dw_tmp = pal_cpu_to_be32(eSIR_ED_NONE);
}
vos_mem_copy(buf, &dw_tmp, sizeof(tANI_U32));
buf += sizeof(tANI_U32);
#endif
#ifdef WLAN_FEATURE_VOWIFI_11R
profile->MDID.mdiePresent = bss_description->mdiePresent;
if (csrIsProfile11r(profile)
#ifdef FEATURE_WLAN_ESE
&& !((profile->negotiatedAuthType == eCSR_AUTH_TYPE_OPEN_SYSTEM) &&
(ies->ESEVersion.present) &&
(mac->roam.configParam.isEseIniFeatureEnabled))
#endif
)
{
/* is11Rconnection */
dw_tmp = pal_cpu_to_be32(TRUE);
vos_mem_copy(buf, &dw_tmp, sizeof(tAniBool)) ;
buf += sizeof(tAniBool);
}
else
{
/* is11Rconnection */
dw_tmp = pal_cpu_to_be32(FALSE);
vos_mem_copy(buf, &dw_tmp, sizeof(tAniBool));
buf += sizeof(tAniBool);
}
#endif
#ifdef FEATURE_WLAN_ESE
/* isESEFeatureIniEnabled */
if (TRUE == mac->roam.configParam.isEseIniFeatureEnabled)
{
dw_tmp = pal_cpu_to_be32(TRUE);
vos_mem_copy(buf, &dw_tmp, sizeof(tAniBool));
buf += sizeof(tAniBool);
}
else
{
dw_tmp = pal_cpu_to_be32(FALSE);
vos_mem_copy(buf, &dw_tmp, sizeof(tAniBool));
buf += sizeof(tAniBool);
}
/* A profile can not be both ESE and 11R. But an 802.11R AP
* may be advertising support for ESE as well. So if we are
* associating Open or explicitly ESE then we will get ESE.
* If we are associating explictly 11R only then we will get
* 11R.
*/
if ((csrIsProfileESE(profile) ||
((ies->ESEVersion.present)
&& ((profile->negotiatedAuthType == eCSR_AUTH_TYPE_OPEN_SYSTEM)
|| (profile->negotiatedAuthType == eCSR_AUTH_TYPE_WPA)
|| (profile->negotiatedAuthType == eCSR_AUTH_TYPE_WPA_PSK)
|| (profile->negotiatedAuthType == eCSR_AUTH_TYPE_RSN)
#ifdef WLAN_FEATURE_11W
|| (profile->negotiatedAuthType ==
eCSR_AUTH_TYPE_RSN_PSK_SHA256)
|| (profile->negotiatedAuthType ==
eCSR_AUTH_TYPE_RSN_8021X_SHA256)
#endif
|| (profile->negotiatedAuthType == eCSR_AUTH_TYPE_RSN_PSK))))
&& (mac->roam.configParam.isEseIniFeatureEnabled))
{
/* isESEconnection */
dw_tmp = pal_cpu_to_be32(TRUE);
vos_mem_copy(buf, &dw_tmp, sizeof(tAniBool));
buf += sizeof(tAniBool);
}
else
{
/* isESEconnection */
dw_tmp = pal_cpu_to_be32(FALSE);
vos_mem_copy(buf, &dw_tmp, sizeof(tAniBool));
buf += sizeof(tAniBool);
}
if (eWNI_SME_JOIN_REQ == message_type)
{
tESETspecInfo eseTspec;
/*
* ESE-Tspec IEs in the ASSOC request is presently not supported
* so nullify the TSPEC parameters
*/
vos_mem_set(&eseTspec, sizeof(tESETspecInfo), 0);
vos_mem_copy(buf, &eseTspec, sizeof(tESETspecInfo));
buf += sizeof(tESETspecInfo);
}
else if (eWNI_SME_REASSOC_REQ == message_type)
{
if ((csrIsProfileESE(profile) ||
((ies->ESEVersion.present)
&& ((profile->negotiatedAuthType == eCSR_AUTH_TYPE_OPEN_SYSTEM)
|| (profile->negotiatedAuthType == eCSR_AUTH_TYPE_WPA)
|| (profile->negotiatedAuthType == eCSR_AUTH_TYPE_WPA_PSK)
|| (profile->negotiatedAuthType == eCSR_AUTH_TYPE_RSN)
#ifdef WLAN_FEATURE_11W
|| (profile->negotiatedAuthType ==
eCSR_AUTH_TYPE_RSN_PSK_SHA256)
|| (profile->negotiatedAuthType ==
eCSR_AUTH_TYPE_RSN_8021X_SHA256)
#endif
|| (profile->negotiatedAuthType ==
eCSR_AUTH_TYPE_RSN_PSK))))
&& (mac->roam.configParam.isEseIniFeatureEnabled))
{
tESETspecInfo eseTspec;
/* ESE Tspec information */
vos_mem_set(&eseTspec, sizeof(tESETspecInfo), 0);
eseTspec.numTspecs = sme_QosESERetrieveTspecInfo(mac, session_id,
(tTspecInfo *) &eseTspec.tspec[0]);
*buf = eseTspec.numTspecs;
buf += sizeof(tANI_U8);
// Copy the TSPEC information only if present
if (eseTspec.numTspecs) {
vos_mem_copy(buf, (void*)&eseTspec.tspec[0],
(eseTspec.numTspecs*sizeof(tTspecInfo)));
}
buf += sizeof(eseTspec.tspec);
}
else
{
tESETspecInfo eseTspec;
/*
* ESE-Tspec IEs in the ASSOC request is presently
* not supported so nullify the TSPEC parameters
*/
vos_mem_set(&eseTspec, sizeof(tESETspecInfo), 0);
vos_mem_copy(buf, &eseTspec, sizeof(tESETspecInfo));
buf += sizeof(tESETspecInfo);
}
}
#endif
#if defined WLAN_FEATURE_VOWIFI_11R || defined FEATURE_WLAN_ESE || defined(FEATURE_WLAN_LFR)
/* Fill in isFastTransitionEnabled */
if (mac->roam.configParam.isFastTransitionEnabled
#ifdef FEATURE_WLAN_LFR
|| csrRoamIsFastRoamEnabled(mac, session_id)
#endif
)
{
dw_tmp = pal_cpu_to_be32(TRUE);
vos_mem_copy(buf, &dw_tmp, sizeof(tAniBool));
buf += sizeof(tAniBool);
}
else
{
dw_tmp = pal_cpu_to_be32(FALSE);
vos_mem_copy(buf, &dw_tmp, sizeof(tAniBool));
buf += sizeof(tAniBool);
}
#endif
#ifdef FEATURE_WLAN_LFR
if(csrRoamIsFastRoamEnabled(mac, session_id))
{
/* legacy fast roaming enabled */
dw_tmp = pal_cpu_to_be32(TRUE);
vos_mem_copy(buf, &dw_tmp, sizeof(tAniBool));
buf += sizeof(tAniBool);
}
else
{
dw_tmp = pal_cpu_to_be32(FALSE);
vos_mem_copy(buf, &dw_tmp, sizeof(tAniBool));
buf += sizeof(tAniBool);
}
#endif
/* txLdpcIniFeatureEnabled */
*buf = (tANI_U8)mac->roam.configParam.txLdpcEnable;
buf++;
if ((csrIs11hSupported(mac)) &&
(CSR_IS_CHANNEL_5GHZ(bss_description->channelId)) &&
(ies->Country.present) &&\
(!mac->roam.configParam.fSupplicantCountryCodeHasPriority))
{
csrSaveToChannelPower2G_5G(mac,
ies->Country.num_triplets * sizeof(tSirMacChanInfo),
(tSirMacChanInfo *)(&ies->Country.triplets[0]));
csrApplyPower2Current(mac);
}
#ifdef WLAN_FEATURE_11AC
/* txBFIniFeatureEnabled */
*buf = (tANI_U8)mac->roam.configParam.txBFEnable;
buf++;
/* txBFCsnValue */
if (IS_BSS_VHT_CAPABLE(ies->VHTCaps))
{
tx_bf_csn_value = (tANI_U8)mac->roam.configParam.txBFCsnValue;
if (ies->VHTCaps.numSoundingDim)
tx_bf_csn_value = CSR_ROAM_MIN
(tx_bf_csn_value, ies->VHTCaps.numSoundingDim);
}
*buf = tx_bf_csn_value;
buf++;
/* Only enable MuBf if no other MuBF session exist
* and FW and HOST is MuBF capable.
*/
if (IS_MUMIMO_BFORMEE_CAPABLE && (FALSE == mac->isMuBfsessionexist))
{
*buf = (tANI_U8)mac->roam.configParam.txMuBformee;
buf++;
}
else
{
*buf = 0;
buf++;
}
#endif
*buf = (tANI_U8)mac->roam.configParam.isAmsduSupportInAMPDU;
buf++;
/* WME */
if(mac->roam.roamSession[session_id].fWMMConnection)
{
/* WME enabled */
dw_tmp = pal_cpu_to_be32(TRUE);
vos_mem_copy(buf, &dw_tmp, sizeof(tAniBool));
buf += sizeof(tAniBool);
}
else
{
dw_tmp = pal_cpu_to_be32(FALSE);
vos_mem_copy(buf, &dw_tmp, sizeof(tAniBool));
buf += sizeof(tAniBool);
}
/* QOS */
if(mac->roam.roamSession[session_id].fQOSConnection)
{
/* QOS enabled */
dw_tmp = pal_cpu_to_be32(TRUE);
vos_mem_copy(buf, &dw_tmp, sizeof(tAniBool));
buf += sizeof(tAniBool);
}
else
{
dw_tmp = pal_cpu_to_be32(FALSE);
vos_mem_copy(buf, &dw_tmp, sizeof(tAniBool));
buf += sizeof(tAniBool);
}
/* BssDesc */
csrPrepareJoinReassocReqBuffer(mac, bss_description, buf,
(tANI_U8)profile->uapsd_mask);
} while( 0 );
smsLog(mac, LOG1, FL("status %d"), status);
vos_mem_free(profile);
return status;
}
#endif
//
eHalStatus csrSendMBDisassocReqMsg( tpAniSirGlobal pMac, tANI_U32 sessionId, tSirMacAddr bssId, tANI_U16 reasonCode )
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tSirSmeDisassocReq *pMsg;
tANI_U8 *pBuf;
tANI_U16 wTmp;
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
if (!CSR_IS_SESSION_VALID( pMac, sessionId ))
return eHAL_STATUS_FAILURE;
do {
pMsg = vos_mem_malloc(sizeof(tSirSmeDisassocReq));
if (NULL == pMsg)
status = eHAL_STATUS_FAILURE;
else
status = eHAL_STATUS_SUCCESS;
if ( !HAL_STATUS_SUCCESS(status) ) break;
vos_mem_set(pMsg, sizeof( tSirSmeDisassocReq ), 0);
pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_DISASSOC_REQ);
pMsg->length = pal_cpu_to_be16((tANI_U16)sizeof( tSirSmeDisassocReq ));
pBuf = &pMsg->sessionId;
// sessionId
*pBuf++ = (tANI_U8)sessionId;
// transactionId
*pBuf = 0;
*( pBuf + 1 ) = 0;
pBuf += sizeof(tANI_U16);
if ( (pSession->pCurRoamProfile != NULL) &&
((CSR_IS_INFRA_AP(pSession->pCurRoamProfile)) ||
(CSR_IS_WDS_AP(pSession->pCurRoamProfile))) )
{
// Set the bssid address before sending the message to LIM
vos_mem_copy((tSirMacAddr *)pBuf, pSession->selfMacAddr,
sizeof( tSirMacAddr ));
status = eHAL_STATUS_SUCCESS;
pBuf = pBuf + sizeof ( tSirMacAddr );
// Set the peer MAC address before sending the message to LIM
vos_mem_copy((tSirMacAddr *)pBuf, bssId, sizeof( tSirMacAddr ));
//perMacAddr is passed as bssId for softAP
status = eHAL_STATUS_SUCCESS;
pBuf = pBuf + sizeof ( tSirMacAddr );
}
else
{
// Set the peer MAC address before sending the message to LIM
vos_mem_copy((tSirMacAddr *)pBuf, bssId, sizeof( tSirMacAddr ));
status = eHAL_STATUS_SUCCESS;
pBuf = pBuf + sizeof ( tSirMacAddr );
vos_mem_copy((tSirMacAddr *)pBuf, bssId, sizeof( pMsg->bssId ));
status = eHAL_STATUS_SUCCESS;
pBuf = pBuf + sizeof ( tSirMacAddr );
}
if(!HAL_STATUS_SUCCESS(status))
{
vos_mem_free(pMsg);
break;
}
// reasonCode
wTmp = pal_cpu_to_be16(reasonCode);
vos_mem_copy(pBuf, &wTmp, sizeof(tANI_U16));
status = eHAL_STATUS_SUCCESS;
if(!HAL_STATUS_SUCCESS(status))
{
vos_mem_free(pMsg);
break;
}
pBuf += sizeof(tANI_U16);
/* The state will be DISASSOC_HANDOFF only when we are doing handoff.
Here we should not send the disassoc over the air to the AP */
if ( CSR_IS_ROAM_SUBSTATE_DISASSOC_HO(pMac, sessionId)
#ifdef WLAN_FEATURE_VOWIFI_11R
&& csrRoamIs11rAssoc(pMac)
#endif
)
{
*pBuf = CSR_DONT_SEND_DISASSOC_OVER_THE_AIR; /* Set DoNotSendOverTheAir flag to 1 only for handoff case */
}
pBuf += sizeof(tANI_U8);
status = palSendMBMessage( pMac->hHdd, pMsg );
} while( 0 );
return( status );
}
eHalStatus csrSendMBTkipCounterMeasuresReqMsg( tpAniSirGlobal pMac, tANI_U32 sessionId, tANI_BOOLEAN bEnable, tSirMacAddr bssId )
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tSirSmeTkipCntrMeasReq *pMsg;
tANI_U8 *pBuf;
do
{
pMsg = vos_mem_malloc(sizeof( tSirSmeTkipCntrMeasReq ));
if ( NULL == pMsg )
status = eHAL_STATUS_FAILURE;
else
status = eHAL_STATUS_SUCCESS;
if ( !HAL_STATUS_SUCCESS(status) ) break;
vos_mem_set(pMsg, sizeof( tSirSmeTkipCntrMeasReq ), 0);
pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_TKIP_CNTR_MEAS_REQ);
pMsg->length = pal_cpu_to_be16((tANI_U16)sizeof( tSirSmeTkipCntrMeasReq ));
pBuf = &pMsg->sessionId;
// sessionId
*pBuf++ = (tANI_U8)sessionId;
// transactionId
*pBuf = 0;
*( pBuf + 1 ) = 0;
pBuf += sizeof(tANI_U16);
// bssid
vos_mem_copy(pMsg->bssId, bssId, sizeof( tSirMacAddr ));
status = eHAL_STATUS_SUCCESS;
pBuf = pBuf + sizeof ( tSirMacAddr );
// bEnable
*pBuf = (tANI_BOOLEAN)bEnable;
if(!HAL_STATUS_SUCCESS(status))
{
vos_mem_free(pMsg);
break;
}
status = palSendMBMessage( pMac->hHdd, pMsg );
} while( 0 );
return( status );
}
eHalStatus
csrSendMBGetAssociatedStasReqMsg( tpAniSirGlobal pMac, tANI_U32 sessionId,
VOS_MODULE_ID modId, tSirMacAddr bssId,
void *pUsrContext, void *pfnSapEventCallback,
tANI_U8 *pAssocStasBuf )
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tSirSmeGetAssocSTAsReq *pMsg;
tANI_U8 *pBuf = NULL, *wTmpBuf = NULL;
tANI_U32 dwTmp;
do
{
pMsg = vos_mem_malloc(sizeof( tSirSmeGetAssocSTAsReq ));
if ( NULL == pMsg )
status = eHAL_STATUS_FAILURE;
else
status = eHAL_STATUS_SUCCESS;
if (!HAL_STATUS_SUCCESS(status)) break;
vos_mem_set(pMsg, sizeof( tSirSmeGetAssocSTAsReq ), 0);
pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_GET_ASSOC_STAS_REQ);
pBuf = (tANI_U8 *)&pMsg->bssId;
wTmpBuf = pBuf;
// bssId
vos_mem_copy((tSirMacAddr *)pBuf, bssId, sizeof(tSirMacAddr));
pBuf += sizeof(tSirMacAddr);
// modId
dwTmp = pal_cpu_to_be16((tANI_U16)modId);
vos_mem_copy(pBuf, (tANI_U8 *)&dwTmp, sizeof(tANI_U16));
pBuf += sizeof(tANI_U16);
// pUsrContext
vos_mem_copy(pBuf, (tANI_U8 *)pUsrContext, sizeof(void *));
pBuf += sizeof(void*);
// pfnSapEventCallback
vos_mem_copy(pBuf, (tANI_U8 *)pfnSapEventCallback, sizeof(void*));
pBuf += sizeof(void*);
// pAssocStasBuf
vos_mem_copy(pBuf, pAssocStasBuf, sizeof(void*));
pBuf += sizeof(void*);
pMsg->length = pal_cpu_to_be16((tANI_U16)(sizeof(tANI_U32 ) + (pBuf - wTmpBuf)));//msg_header + msg
status = palSendMBMessage( pMac->hHdd, pMsg );
} while( 0 );
return( status );
}
eHalStatus
csrSendMBGetWPSPBCSessions( tpAniSirGlobal pMac, tANI_U32 sessionId,
tSirMacAddr bssId, void *pUsrContext, void *pfnSapEventCallback,v_MACADDR_t pRemoveMac)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tSirSmeGetWPSPBCSessionsReq *pMsg;
tANI_U8 *pBuf = NULL, *wTmpBuf = NULL;
do
{
pMsg = vos_mem_malloc(sizeof(tSirSmeGetWPSPBCSessionsReq));
if ( NULL == pMsg )
status = eHAL_STATUS_FAILURE;
else
status = eHAL_STATUS_SUCCESS;
if (!HAL_STATUS_SUCCESS(status)) break;
vos_mem_set(pMsg, sizeof( tSirSmeGetWPSPBCSessionsReq ), 0);
pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_GET_WPSPBC_SESSION_REQ);
pBuf = (tANI_U8 *)&pMsg->pUsrContext;
VOS_ASSERT(pBuf);
wTmpBuf = pBuf;
// pUsrContext
vos_mem_copy(pBuf, (tANI_U8 *)pUsrContext, sizeof(void*));
pBuf += sizeof(void *);
// pSapEventCallback
vos_mem_copy(pBuf, (tANI_U8 *)pfnSapEventCallback, sizeof(void *));
pBuf += sizeof(void *);
// bssId
vos_mem_copy((tSirMacAddr *)pBuf, bssId, sizeof(tSirMacAddr));
pBuf += sizeof(tSirMacAddr);
// MAC Address of STA in WPS session
vos_mem_copy((tSirMacAddr *)pBuf, pRemoveMac.bytes, sizeof(v_MACADDR_t));
pBuf += sizeof(v_MACADDR_t);
pMsg->length = pal_cpu_to_be16((tANI_U16)(sizeof(tANI_U32 ) + (pBuf - wTmpBuf)));//msg_header + msg
status = palSendMBMessage( pMac->hHdd, pMsg );
} while( 0 );
return( status );
}
eHalStatus
csrSendChngMCCBeaconInterval(tpAniSirGlobal pMac, tANI_U32 sessionId)
{
tpSirChangeBIParams pMsg;
tANI_U16 len = 0;
eHalStatus status = eHAL_STATUS_SUCCESS;
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return eHAL_STATUS_FAILURE;
}
//NO need to update the Beacon Params if update beacon parameter flag is not set
if(!pMac->roam.roamSession[sessionId].bssParams.updatebeaconInterval )
return eHAL_STATUS_SUCCESS;
pMac->roam.roamSession[sessionId].bssParams.updatebeaconInterval = eANI_BOOLEAN_FALSE;
/* Create the message and send to lim */
len = sizeof(tSirChangeBIParams);
pMsg = vos_mem_malloc(len);
if ( NULL == pMsg )
status = eHAL_STATUS_FAILURE;
else
status = eHAL_STATUS_SUCCESS;
if(HAL_STATUS_SUCCESS(status))
{
vos_mem_set(pMsg, sizeof(tSirChangeBIParams), 0);
pMsg->messageType = eWNI_SME_CHNG_MCC_BEACON_INTERVAL;
pMsg->length = len;
// bssId
vos_mem_copy((tSirMacAddr *)pMsg->bssId, &pSession->selfMacAddr,
sizeof(tSirMacAddr));
smsLog( pMac, LOG1, FL("CSR Attempting to change BI for Bssid= "MAC_ADDRESS_STR),
MAC_ADDR_ARRAY(pMsg->bssId));
pMsg->sessionId = sessionId;
smsLog(pMac, LOG1, FL(" session %d BeaconInterval %d"), sessionId, pMac->roam.roamSession[sessionId].bssParams.beaconInterval);
pMsg->beaconInterval = pMac->roam.roamSession[sessionId].bssParams.beaconInterval;
status = palSendMBMessage(pMac->hHdd, pMsg);
}
return status;
}
#ifdef WLAN_FEATURE_AP_HT40_24G
eHalStatus csrSetHT2040Mode(tpAniSirGlobal pMac, tANI_U32 sessionId, tANI_U8 cbMode)
{
tpSirSetHT2040Mode pMsg;
tANI_U16 len = 0;
eHalStatus status = eHAL_STATUS_SUCCESS;
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return eHAL_STATUS_FAILURE;
}
/* Create the message and send to lim */
len = sizeof(tSirSetHT2040Mode);
pMsg = vos_mem_malloc(len);
if ( NULL == pMsg )
{
smsLog( pMac, LOGE, FL("Memory Allocation Fail !!!"));
status = eHAL_STATUS_FAILURE;
}
else
status = eHAL_STATUS_SUCCESS;
if(HAL_STATUS_SUCCESS(status))
{
vos_mem_set(pMsg, sizeof(tSirSetHT2040Mode), 0);
pMsg->messageType = eWNI_SME_SET_HT_2040_MODE;
pMsg->length = len;
// bssId
vos_mem_copy((tSirMacAddr *)pMsg->bssId, &pSession->selfMacAddr,
sizeof(tSirMacAddr));
smsLog( pMac, LOGW, FL("CSR Attempting to set "
"HT20/40 mode for Bssid= "MAC_ADDRESS_STR),
MAC_ADDR_ARRAY(pMsg->bssId));
pMsg->sessionId = sessionId;
pMsg->cbMode = cbMode;
smsLog(pMac, LOGW, FL("session %d Channel Bonding: %d"),
sessionId, cbMode);
status = palSendMBMessage(pMac->hHdd, pMsg);
}
return status;
}
#endif
eHalStatus csrSendMBDeauthReqMsg( tpAniSirGlobal pMac, tANI_U32 sessionId, tSirMacAddr bssId, tANI_U16 reasonCode )
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tSirSmeDeauthReq *pMsg;
tANI_U8 *pBuf;
tANI_U16 wTmp;
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
if (!CSR_IS_SESSION_VALID( pMac, sessionId ))
return eHAL_STATUS_FAILURE;
do {
pMsg = vos_mem_malloc(sizeof( tSirSmeDeauthReq ));
if ( NULL == pMsg )
status = eHAL_STATUS_FAILURE;
else
status = eHAL_STATUS_SUCCESS;
if ( !HAL_STATUS_SUCCESS(status) ) break;
vos_mem_set(pMsg, sizeof( tSirSmeDeauthReq ), 0);
pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_DEAUTH_REQ);
pMsg->length = pal_cpu_to_be16((tANI_U16)sizeof( tSirSmeDeauthReq ));
//sessionId
pBuf = &pMsg->sessionId;
*pBuf++ = (tANI_U8)sessionId;
//tansactionId
*pBuf = 0;
*(pBuf + 1 ) = 0;
pBuf += sizeof(tANI_U16);
if ((pSession->pCurRoamProfile != NULL) && (
(CSR_IS_INFRA_AP(pSession->pCurRoamProfile)) ||
(CSR_IS_WDS_AP(pSession->pCurRoamProfile)))){
// Set the BSSID before sending the message to LIM
vos_mem_copy( (tSirMacAddr *)pBuf, pSession->selfMacAddr,
sizeof( pMsg->peerMacAddr ) );
status = eHAL_STATUS_SUCCESS;
pBuf = pBuf + sizeof(tSirMacAddr);
}
else
{
// Set the BSSID before sending the message to LIM
vos_mem_copy( (tSirMacAddr *)pBuf, bssId, sizeof( pMsg->peerMacAddr ) );
status = eHAL_STATUS_SUCCESS;
pBuf = pBuf + sizeof(tSirMacAddr);
}
if(!HAL_STATUS_SUCCESS(status))
{
vos_mem_free(pMsg);
break;
}
// Set the peer MAC address before sending the message to LIM
vos_mem_copy( (tSirMacAddr *) pBuf, bssId, sizeof( pMsg->peerMacAddr ) );
status = eHAL_STATUS_SUCCESS;
pBuf = pBuf + sizeof(tSirMacAddr);
if(!HAL_STATUS_SUCCESS(status))
{
vos_mem_free(pMsg);
break;
}
wTmp = pal_cpu_to_be16(reasonCode);
vos_mem_copy( pBuf, &wTmp,sizeof( tANI_U16 ) );
status = eHAL_STATUS_SUCCESS;
if(!HAL_STATUS_SUCCESS(status))
{
vos_mem_free(pMsg);
break;
}
status = palSendMBMessage( pMac->hHdd, pMsg );
} while( 0 );
return( status );
}
eHalStatus csrSendMBDisassocCnfMsg( tpAniSirGlobal pMac, tpSirSmeDisassocInd pDisassocInd )
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tSirSmeDisassocCnf *pMsg;
do {
pMsg = vos_mem_malloc(sizeof( tSirSmeDisassocCnf ));
if ( NULL == pMsg )
status = eHAL_STATUS_FAILURE;
else
status = eHAL_STATUS_SUCCESS;
if ( !HAL_STATUS_SUCCESS(status) ) break;
vos_mem_set(pMsg, sizeof( tSirSmeDisassocCnf), 0);
pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_DISASSOC_CNF);
pMsg->statusCode = (tSirResultCodes)pal_cpu_to_be32(eSIR_SME_SUCCESS);
pMsg->length = pal_cpu_to_be16((tANI_U16)sizeof( tSirSmeDisassocCnf ));
pMsg->assocId = pal_cpu_to_be16((tANI_U16)pDisassocInd->assocId);
vos_mem_copy(pMsg->peerMacAddr, pDisassocInd->peerMacAddr,
sizeof(pMsg->peerMacAddr));
status = eHAL_STATUS_SUCCESS;
if(!HAL_STATUS_SUCCESS(status))
{
vos_mem_free(pMsg);
break;
}
//To test reconn
vos_mem_copy(pMsg->bssId, pDisassocInd->bssId, sizeof(pMsg->peerMacAddr));
status = eHAL_STATUS_SUCCESS;
if(!HAL_STATUS_SUCCESS(status))
{
vos_mem_free(pMsg);
break;
}
//To test reconn ends
status = palSendMBMessage( pMac->hHdd, pMsg );
} while( 0 );
return( status );
}
eHalStatus csrSendMBDeauthCnfMsg( tpAniSirGlobal pMac, tpSirSmeDeauthInd pDeauthInd )
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tSirSmeDeauthCnf *pMsg;
do {
pMsg = vos_mem_malloc(sizeof( tSirSmeDeauthCnf ));
if ( NULL == pMsg )
status = eHAL_STATUS_FAILURE;
else
status = eHAL_STATUS_SUCCESS;
if ( !HAL_STATUS_SUCCESS(status) ) break;
vos_mem_set(pMsg, sizeof( tSirSmeDeauthCnf ), 0);
pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_DEAUTH_CNF);
pMsg->statusCode = (tSirResultCodes)pal_cpu_to_be32(eSIR_SME_SUCCESS);
pMsg->length = pal_cpu_to_be16((tANI_U16)sizeof( tSirSmeDeauthCnf ));
pMsg->assocId = pal_cpu_to_be16((tANI_U16)pDeauthInd->assocId);
vos_mem_copy(pMsg->bssId, pDeauthInd->bssId, sizeof(pMsg->bssId));
status = eHAL_STATUS_SUCCESS;
if(!HAL_STATUS_SUCCESS(status))
{
vos_mem_free(pMsg);
break;
}
vos_mem_copy(pMsg->peerMacAddr, pDeauthInd->peerMacAddr,
sizeof(pMsg->peerMacAddr));
status = eHAL_STATUS_SUCCESS;
if(!HAL_STATUS_SUCCESS(status))
{
vos_mem_free(pMsg);
break;
}
status = palSendMBMessage( pMac->hHdd, pMsg );
} while( 0 );
return( status );
}
eHalStatus csrSendAssocCnfMsg( tpAniSirGlobal pMac, tpSirSmeAssocInd pAssocInd, eHalStatus Halstatus )
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tSirSmeAssocCnf *pMsg;
tANI_U8 *pBuf;
tSirResultCodes statusCode;
tANI_U16 wTmp;
vos_msg_t msg;
smsLog( pMac, LOG1, FL("Posting eWNI_SME_ASSOC_CNF to LIM. "
"HalStatus : %d"),
Halstatus);
do {
pMsg = vos_mem_malloc(sizeof( tSirSmeAssocCnf ));
if ( NULL == pMsg )
status = eHAL_STATUS_FAILURE;
else
status = eHAL_STATUS_SUCCESS;
if ( !HAL_STATUS_SUCCESS(status) ) break;
vos_mem_set(pMsg, sizeof( tSirSmeAssocCnf ), 0);
pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_ASSOC_CNF);
pMsg->length = pal_cpu_to_be16((tANI_U16)sizeof( tSirSmeAssocCnf ));
pBuf = (tANI_U8 *)&pMsg->statusCode;
if(HAL_STATUS_SUCCESS(Halstatus))
statusCode = (tSirResultCodes)pal_cpu_to_be32(eSIR_SME_SUCCESS);
else
statusCode = (tSirResultCodes)pal_cpu_to_be32(eSIR_SME_ASSOC_REFUSED);
vos_mem_copy(pBuf, &statusCode, sizeof(tSirResultCodes));
pBuf += sizeof(tSirResultCodes);
// bssId
vos_mem_copy((tSirMacAddr *)pBuf, pAssocInd->bssId, sizeof(tSirMacAddr));
status = eHAL_STATUS_SUCCESS;
pBuf += sizeof (tSirMacAddr);
// peerMacAddr
vos_mem_copy((tSirMacAddr *)pBuf, pAssocInd->peerMacAddr,
sizeof(tSirMacAddr));
status = eHAL_STATUS_SUCCESS;
pBuf += sizeof (tSirMacAddr);
// aid
wTmp = pal_cpu_to_be16(pAssocInd->aid);
vos_mem_copy(pBuf, &wTmp, sizeof(tANI_U16));
pBuf += sizeof (tANI_U16);
// alternateBssId
vos_mem_copy((tSirMacAddr *)pBuf, pAssocInd->bssId, sizeof(tSirMacAddr));
status = eHAL_STATUS_SUCCESS;
pBuf += sizeof (tSirMacAddr);
// alternateChannelId
*pBuf = 11;
msg.type = pMsg->messageType;
msg.bodyval = 0;
msg.bodyptr = pMsg;
status = vos_mq_post_message_high_pri(VOS_MQ_ID_PE, &msg);
if(!HAL_STATUS_SUCCESS(status))
{
//pMsg is freed by palSendMBMessage
vos_mem_free(pMsg);
break;
}
} while( 0 );
return( status );
}
eHalStatus csrSendAssocIndToUpperLayerCnfMsg( tpAniSirGlobal pMac,
tpSirSmeAssocInd pAssocInd,
eHalStatus Halstatus,
tANI_U8 sessionId)
{
tSirMsgQ msgQ;
tSirSmeAssocIndToUpperLayerCnf *pMsg;
tANI_U8 *pBuf;
tSirResultCodes statusCode;
tANI_U16 wTmp;
do {
pMsg = vos_mem_malloc(sizeof( tSirSmeAssocIndToUpperLayerCnf ));
if ( NULL == pMsg ) return eHAL_STATUS_FAILURE;
vos_mem_set(pMsg, sizeof( tSirSmeAssocIndToUpperLayerCnf ), 0);
pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_UPPER_LAYER_ASSOC_CNF);
pMsg->length = pal_cpu_to_be16((tANI_U16)sizeof( tSirSmeAssocIndToUpperLayerCnf ));
pMsg->sessionId = sessionId;
pBuf = (tANI_U8 *)&pMsg->statusCode;
if(HAL_STATUS_SUCCESS(Halstatus))
statusCode = (tSirResultCodes)pal_cpu_to_be32(eSIR_SME_SUCCESS);
else
statusCode = (tSirResultCodes)pal_cpu_to_be32(eSIR_SME_ASSOC_REFUSED);
vos_mem_copy(pBuf, &statusCode, sizeof(tSirResultCodes)) ;
pBuf += sizeof(tSirResultCodes);
// bssId
vos_mem_copy((tSirMacAddr *)pBuf, pAssocInd->bssId, sizeof(tSirMacAddr));
pBuf += sizeof (tSirMacAddr);
// peerMacAddr
vos_mem_copy((tSirMacAddr *)pBuf, pAssocInd->peerMacAddr,
sizeof(tSirMacAddr));
pBuf += sizeof (tSirMacAddr);
// StaId
wTmp = pal_cpu_to_be16(pAssocInd->staId);
vos_mem_copy(pBuf, &wTmp, sizeof(tANI_U16));
pBuf += sizeof (tANI_U16);
// alternateBssId
vos_mem_copy((tSirMacAddr *)pBuf, pAssocInd->bssId, sizeof(tSirMacAddr));
pBuf += sizeof (tSirMacAddr);
// alternateChannelId
*pBuf = 11;
pBuf += sizeof (tANI_U8);
// Instead of copying roam Info, we just copy only WmmEnabled, RsnIE information
//Wmm
*pBuf = pAssocInd->wmmEnabledSta;
pBuf += sizeof (tANI_U8);
//RSN IE
vos_mem_copy((tSirRSNie *)pBuf, &pAssocInd->rsnIE, sizeof(tSirRSNie));
pBuf += sizeof (tSirRSNie);
//Additional IE
vos_mem_copy((void *)pBuf, &pAssocInd->addIE, sizeof(tSirAddie));
pBuf += sizeof (tSirAddie);
//reassocReq
*pBuf = pAssocInd->reassocReq;
pBuf += sizeof (tANI_U8);
#ifdef WLAN_FEATURE_AP_HT40_24G
// 40 MHz Intolerant
*pBuf = pAssocInd->HT40MHzIntoEnabledSta;
pBuf += sizeof (tANI_U8);
#endif
*pBuf = pAssocInd->rate_flags;
pBuf += sizeof (uint32_t);
pBuf = (tANI_U8 *)&pMsg->chan_info;
vos_mem_copy((void *)pBuf, &pAssocInd->chan_info,
sizeof(tSirSmeChanInfo));
pBuf = (tANI_U8 *)&pMsg->ch_width;
*pBuf = pAssocInd->ch_width;
if (pAssocInd->HTCaps.present) {
pBuf = (tANI_U8 *)&pMsg->HTCaps;
vos_mem_copy(pBuf, &pAssocInd->HTCaps, sizeof(pMsg->HTCaps));
}
if (pAssocInd->VHTCaps.present) {
pBuf = (tANI_U8 *)&pMsg->VHTCaps;
vos_mem_copy(pBuf, &pAssocInd->VHTCaps, sizeof(pMsg->VHTCaps));
}
msgQ.type = eWNI_SME_UPPER_LAYER_ASSOC_CNF;
msgQ.bodyptr = pMsg;
msgQ.bodyval = 0;
SysProcessMmhMsg(pMac, &msgQ);
} while( 0 );
return( eHAL_STATUS_SUCCESS );
}
eHalStatus csrSendMBSetContextReqMsg( tpAniSirGlobal pMac, tANI_U32 sessionId,
tSirMacAddr peerMacAddr, tANI_U8 numKeys, tAniEdType edType,
tANI_BOOLEAN fUnicast, tAniKeyDirection aniKeyDirection,
tANI_U8 keyId, tANI_U8 keyLength, tANI_U8 *pKey, tANI_U8 paeRole,
tANI_U8 *pKeyRsc )
{
tSirSmeSetContextReq *pMsg;
tANI_U16 msgLen;
VOS_STATUS status;
tAniEdType tmpEdType;
tAniKeyDirection tmpDirection;
tANI_U8 *pBuf = NULL;
tANI_U8 *p = NULL;
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
vos_msg_t msg;
smsLog( pMac, LOG1, FL("keylength is %d, Encry type is : %d"),
keyLength, edType);
do {
if( ( 1 != numKeys ) && ( 0 != numKeys ) ) break;
// all of these fields appear in every SET_CONTEXT message. Below we'll add in the size for each
// key set. Since we only support upto one key, we always allocate memory for 1 key
msgLen = sizeof( tANI_U16) + sizeof( tANI_U16 ) + sizeof( tSirMacAddr ) +
sizeof( tSirMacAddr ) + 1 + sizeof(tANI_U16) +
sizeof( pMsg->keyMaterial.length ) + sizeof( pMsg->keyMaterial.edType ) + sizeof( pMsg->keyMaterial.numKeys ) +
( sizeof( pMsg->keyMaterial.key ) );
pMsg = vos_mem_malloc(msgLen);
if ( NULL == pMsg ) return eHAL_STATUS_FAILURE;
vos_mem_set(pMsg, msgLen, 0);
pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_SETCONTEXT_REQ);
pMsg->length = pal_cpu_to_be16(msgLen);
//sessionId
pBuf = &pMsg->sessionId;
*pBuf = (tANI_U8)sessionId;
pBuf++;
// transactionId
*pBuf = 0;
*(pBuf + 1) = 0;
pBuf += sizeof(tANI_U16);
// peerMacAddr
vos_mem_copy(pBuf, (tANI_U8 *)peerMacAddr, sizeof(tSirMacAddr));
pBuf += sizeof(tSirMacAddr);
// bssId
vos_mem_copy(pBuf, (tANI_U8 *)&pSession->connectedProfile.bssid,
sizeof(tSirMacAddr));
pBuf += sizeof(tSirMacAddr);
p = pBuf;
// Set the pMsg->keyMaterial.length field (this length is defined as all data that follows the edType field
// in the tSirKeyMaterial keyMaterial; field).
//
// !!NOTE: This keyMaterial.length contains the length of a MAX size key, though the keyLength can be
// shorter than this max size. Is LIM interpreting this ok ?
p = pal_set_U16( p, pal_cpu_to_be16((tANI_U16)( sizeof( pMsg->keyMaterial.numKeys ) + ( numKeys * sizeof( pMsg->keyMaterial.key ) ) )) );
// set pMsg->keyMaterial.edType
tmpEdType = (tAniEdType)pal_cpu_to_be32(edType);
vos_mem_copy(p, (tANI_U8 *)&tmpEdType, sizeof(tAniEdType));
p += sizeof( pMsg->keyMaterial.edType );
// set the pMsg->keyMaterial.numKeys field
*p = numKeys;
p += sizeof( pMsg->keyMaterial.numKeys );
// set pSirKey->keyId = keyId;
*p = keyId;
p += sizeof( pMsg->keyMaterial.key[ 0 ].keyId );
// set pSirKey->unicast = (tANI_U8)fUnicast;
*p = (tANI_U8)fUnicast;
p += sizeof( pMsg->keyMaterial.key[ 0 ].unicast );
// set pSirKey->keyDirection = aniKeyDirection;
tmpDirection = (tAniKeyDirection)pal_cpu_to_be32(aniKeyDirection);
vos_mem_copy(p, (tANI_U8 *)&tmpDirection, sizeof(tAniKeyDirection));
p += sizeof(tAniKeyDirection);
// pSirKey->keyRsc = ;;
vos_mem_copy(p, pKeyRsc, CSR_MAX_RSC_LEN);
p += sizeof( pMsg->keyMaterial.key[ 0 ].keyRsc );
// set pSirKey->paeRole
*p = paeRole; // 0 is Supplicant
p++;
// set pSirKey->keyLength = keyLength;
p = pal_set_U16( p, pal_cpu_to_be16(keyLength) );
if ( keyLength && pKey )
vos_mem_copy(p, pKey, keyLength);
msg.type = pMsg->messageType;
msg.bodyptr = pMsg;
msg.bodyval = 0;
if (fUnicast)
status = vos_mq_post_message_high_pri(VOS_MQ_ID_PE, &msg);
else
status = vos_mq_post_message(VOS_MQ_ID_PE, &msg);
if (!VOS_IS_STATUS_SUCCESS(status)) {
vos_mem_free(pMsg);
return eHAL_STATUS_FAILURE;
}
} while( 0 );
return eHAL_STATUS_SUCCESS;
}
eHalStatus csrSendMBStartBssReqMsg( tpAniSirGlobal pMac, tANI_U32 sessionId, eCsrRoamBssType bssType,
tCsrRoamStartBssParams *pParam, tSirBssDescription *pBssDesc )
{
eHalStatus status;
tSirSmeStartBssReq *pMsg;
tANI_U8 *pBuf = NULL;
tANI_U8 *wTmpBuf = NULL;
tANI_U16 msgLen, wTmp;
tANI_U32 dwTmp;
tSirNwType nwType;
ePhyChanBondState cbMode;
tANI_U32 authType;
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return eHAL_STATUS_FAILURE;
}
do {
pSession->joinFailStatusCode.statusCode = eSIR_SME_SUCCESS;
pSession->joinFailStatusCode.reasonCode = 0;
msgLen = sizeof(tSirSmeStartBssReq);
pMsg = vos_mem_malloc(msgLen);
if ( NULL == pMsg ) return eHAL_STATUS_FAILURE;
vos_mem_set(pMsg, msgLen, 0);
pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_START_BSS_REQ);
pBuf = &pMsg->sessionId;
wTmpBuf = pBuf;
//sessionId
*pBuf = (tANI_U8)sessionId;
pBuf++;
// transactionId
*pBuf = 0;
*(pBuf + 1) = 0;
pBuf += sizeof(tANI_U16);
// bssid
vos_mem_copy(pBuf, pParam->bssid, sizeof(tSirMacAddr));
pBuf += sizeof(tSirMacAddr);
// selfMacAddr
vos_mem_copy(pBuf, pSession->selfMacAddr, sizeof(tSirMacAddr));
pBuf += sizeof(tSirMacAddr);
// beaconInterval
if( pBssDesc && pBssDesc->beaconInterval )
{
wTmp = pal_cpu_to_be16( pBssDesc->beaconInterval );
}
else if(pParam->beaconInterval)
{
wTmp = pal_cpu_to_be16( pParam->beaconInterval );
}
else
{
wTmp = pal_cpu_to_be16( WNI_CFG_BEACON_INTERVAL_STADEF );
}
if(csrIsconcurrentsessionValid (pMac, sessionId,
pParam->bssPersona)
== eHAL_STATUS_SUCCESS )
{
csrValidateMCCBeaconInterval(pMac, pParam->operationChn, &wTmp, sessionId,
pParam->bssPersona);
//Update the beacon Interval
pParam->beaconInterval = wTmp;
}
else
{
smsLog( pMac,LOGE, FL("****Start BSS failed persona already exists***"));
status = eHAL_STATUS_FAILURE;
vos_mem_free(pMsg);
return status;
}
vos_mem_copy(pBuf, &wTmp, sizeof( tANI_U16 ));
pBuf += sizeof(tANI_U16);
// dot11mode
*pBuf = (tANI_U8)csrTranslateToWNICfgDot11Mode( pMac, pParam->uCfgDot11Mode );
pBuf += 1;
// bssType
dwTmp = pal_cpu_to_be32( csrTranslateBsstypeToMacType( bssType ) );
vos_mem_copy(pBuf, &dwTmp, sizeof(tSirBssType));
pBuf += sizeof(tSirBssType);
// ssId
if( pParam->ssId.length )
{
// ssId len
*pBuf = pParam->ssId.length;
pBuf++;
vos_mem_copy(pBuf, pParam->ssId.ssId, pParam->ssId.length);
pBuf += pParam->ssId.length;
}
else
{
*pBuf = 0;
pBuf++;
}
// set the channel Id
*pBuf = pParam->operationChn;
pBuf++;
//What should we really do for the cbmode.
cbMode = (ePhyChanBondState)pal_cpu_to_be32(pParam->cbMode);
vos_mem_copy(pBuf, (tANI_U8 *)&cbMode, sizeof(ePhyChanBondState));
pBuf += sizeof(ePhyChanBondState);
// Set privacy
*pBuf = pParam->privacy;
pBuf++;
//Set Uapsd
*pBuf = pParam->ApUapsdEnable;
pBuf++;
//Set SSID hidden
*pBuf = pParam->ssidHidden;
pBuf++;
*pBuf = (tANI_U8)pParam->fwdWPSPBCProbeReq;
pBuf++;
//Ht protection Enable/Disable
*pBuf = (tANI_U8)pParam->protEnabled;
pBuf++;
//Enable Beacons to Receive for OBSS protection Enable/Disable
*pBuf = (tANI_U8)pParam->obssProtEnabled;
pBuf++;
//set cfg related to protection
wTmp = pal_cpu_to_be16( pParam->ht_protection );
vos_mem_copy(pBuf, &wTmp, sizeof( tANI_U16 ));
pBuf += sizeof(tANI_U16);
// Set Auth type
authType = pal_cpu_to_be32(pParam->authType);
vos_mem_copy(pBuf, (tANI_U8 *)&authType, sizeof(tANI_U32));
pBuf += sizeof(tANI_U32);
// Set DTIM
dwTmp = pal_cpu_to_be32(pParam->dtimPeriod);
vos_mem_copy(pBuf, (tANI_U8 *)&dwTmp, sizeof(tANI_U32));
pBuf += sizeof(tANI_U32);
// Set wps_state
*pBuf = pParam->wps_state;
pBuf++;
// set isCoalesingInIBSSAllowed
*pBuf = pMac->isCoalesingInIBSSAllowed;
pBuf++;
//Persona
*pBuf = (tANI_U8)pParam->bssPersona;
pBuf++;
//txLdpcIniFeatureEnabled
*pBuf = (tANI_U8)(tANI_U8)pMac->roam.configParam.txLdpcEnable;
pBuf++;
#ifdef WLAN_FEATURE_11W
// Set MFP capable/required
*pBuf = (tANI_U8)pParam->mfpCapable;
pBuf++;
*pBuf = (tANI_U8)pParam->mfpRequired;
pBuf++;
#endif
// set RSN IE
if( pParam->nRSNIELength > sizeof(pMsg->rsnIE.rsnIEdata) )
{
status = eHAL_STATUS_INVALID_PARAMETER;
vos_mem_free(pMsg);
break;
}
wTmp = pal_cpu_to_be16( pParam->nRSNIELength );
vos_mem_copy(pBuf, &wTmp, sizeof(tANI_U16));
pBuf += sizeof(tANI_U16);
if( wTmp )
{
wTmp = pParam->nRSNIELength;
vos_mem_copy(pBuf, pParam->pRSNIE, wTmp);
pBuf += wTmp;
}
nwType = (tSirNwType)pal_cpu_to_be32(pParam->sirNwType);
vos_mem_copy(pBuf, (tANI_U8 *)&nwType, sizeof(tSirNwType));
pBuf += sizeof(tSirNwType);
*pBuf = pParam->operationalRateSet.numRates; //tSirMacRateSet->numRates
pBuf++;
vos_mem_copy(pBuf, pParam->operationalRateSet.rate,
pParam->operationalRateSet.numRates );
pBuf += pParam->operationalRateSet.numRates ;
*pBuf++ = pParam->extendedRateSet.numRates;
if(0 != pParam->extendedRateSet.numRates)
{
vos_mem_copy(pBuf, pParam->extendedRateSet.rate,
pParam->extendedRateSet.numRates);
pBuf += pParam->extendedRateSet.numRates;
}
#ifdef WLAN_FEATURE_AP_HT40_24G
*pBuf++ = (tANI_U8)pMac->roam.configParam.apHT40_24GEnabled;
#endif
msgLen = (tANI_U16)(sizeof(tANI_U32 ) + (pBuf - wTmpBuf)); //msg_header + msg
pMsg->length = pal_cpu_to_be16(msgLen);
status = palSendMBMessage(pMac->hHdd, pMsg);
} while( 0 );
return( status );
}
eHalStatus csrSendMBStopBssReqMsg( tpAniSirGlobal pMac, tANI_U32 sessionId )
{
eHalStatus status = eHAL_STATUS_FAILURE;
tSirSmeStopBssReq *pMsg;
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
tANI_U8 *pBuf;
tANI_U16 msgLen;
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return eHAL_STATUS_FAILURE;
}
pMsg = vos_mem_malloc(sizeof(tSirSmeStopBssReq));
if ( NULL == pMsg ) return eHAL_STATUS_FAILURE;
vos_mem_set(pMsg, sizeof( tSirSmeStopBssReq ), 0);
pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_STOP_BSS_REQ);
pBuf = &pMsg->sessionId;
//sessionId
*pBuf = (tANI_U8)sessionId;
pBuf++;
// transactionId
*pBuf = 0;
pBuf += sizeof(tANI_U16);
//reason code
*pBuf = 0;
pBuf += sizeof(tSirResultCodes);
// bssid
// if BSSType is WDS sta, use selfmacAddr as bssid, else use bssid in connectedProfile
if( CSR_IS_CONN_WDS_STA(&pSession->connectedProfile) )
{
vos_mem_copy(pBuf, (tANI_U8 *)&pSession->selfMacAddr,
sizeof(tSirMacAddr));
}
else
{
vos_mem_copy(pBuf, (tANI_U8 *)&pSession->connectedProfile.bssid,
sizeof(tSirMacAddr));
}
pBuf += sizeof(tSirMacAddr);
msgLen = sizeof(tANI_U16) + sizeof(tANI_U16) + 1 + sizeof(tANI_U16) + sizeof(tSirResultCodes) + sizeof(tSirMacAddr);
pMsg->length = pal_cpu_to_be16(msgLen);
status = palSendMBMessage( pMac->hHdd, pMsg );
return( status );
}
eHalStatus csrReassoc(tpAniSirGlobal pMac, tANI_U32 sessionId,
tCsrRoamModifyProfileFields *pModProfileFields,
tANI_U32 *pRoamId, v_BOOL_t fForce)
{
eHalStatus status = eHAL_STATUS_FAILURE;
tANI_U32 roamId = 0;
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
if((csrIsConnStateConnected(pMac, sessionId)) &&
(fForce || (!vos_mem_compare( &pModProfileFields,
&pSession->connectedProfile.modifyProfileFields,
sizeof(tCsrRoamModifyProfileFields)))) )
{
roamId = GET_NEXT_ROAM_ID(&pMac->roam);
if(pRoamId)
{
*pRoamId = roamId;
}
status = csrRoamIssueReassoc(pMac, sessionId, NULL, pModProfileFields,
eCsrSmeIssuedReassocToSameAP, roamId,
eANI_BOOLEAN_FALSE);
}
return status;
}
static eHalStatus csrRoamSessionOpened(tpAniSirGlobal pMac, tANI_U32 sessionId)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tCsrRoamInfo roamInfo;
vos_mem_set(&roamInfo, sizeof(tCsrRoamInfo), 0);
status = csrRoamCallCallback(pMac, sessionId, &roamInfo, 0,
eCSR_ROAM_SESSION_OPENED, eCSR_ROAM_RESULT_NONE);
return (status);
}
eHalStatus csrProcessAddStaSessionRsp( tpAniSirGlobal pMac, tANI_U8 *pMsg)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tListElem *pEntry = NULL;
tSmeCmd *pCommand = NULL;
tSirSmeAddStaSelfRsp *pRsp;
do
{
if(pMsg == NULL)
{
smsLog(pMac, LOGE, "in %s msg ptr is NULL", __func__);
status = eHAL_STATUS_FAILURE;
break;
}
pEntry = csrLLPeekHead( &pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK );
if(pEntry)
{
pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link );
if(eSmeCommandAddStaSession == pCommand->command)
{
pRsp = (tSirSmeAddStaSelfRsp*)pMsg;
smsLog( pMac, LOG1, "Add Sta rsp status = %d", pRsp->status );
if (pRsp->status == eSIR_FAILURE) {
VOS_ASSERT( 0 );
}
//Nothing to be done. May be indicate the self sta addition success by calling session callback (TODO).
csrRoamSessionOpened(pMac, pCommand->sessionId);
//Remove this command out of the active list
if(csrLLRemoveEntry(&pMac->sme.smeCmdActiveList, pEntry, LL_ACCESS_LOCK))
{
//Now put this command back on the avilable command list
csrReleaseCommand(pMac, pCommand);
}
smeProcessPendingQueue( pMac );
}
else
{
smsLog(pMac, LOGE, "in %s eWNI_SME_ADD_STA_SELF_RSP Received but NO Add sta session command are ACTIVE ...",
__func__);
status = eHAL_STATUS_FAILURE;
break;
}
}
else
{
smsLog(pMac, LOGE, "in %s eWNI_SME_ADD_STA_SELF_RSP Received but NO commands are ACTIVE ...",
__func__);
status = eHAL_STATUS_FAILURE;
break;
}
} while(0);
return status;
}
eHalStatus csrSendMBAddSelfStaReqMsg(tpAniSirGlobal pMac,
tAddStaForSessionCmd *pAddStaReq)
{
tSirSmeAddStaSelfReq *pMsg;
tANI_U16 msgLen;
eHalStatus status = eHAL_STATUS_FAILURE;
do {
msgLen = sizeof(tSirSmeAddStaSelfReq);
pMsg = vos_mem_malloc(msgLen);
if ( NULL == pMsg ) break;
vos_mem_set(pMsg, msgLen, 0);
pMsg->mesgType = pal_cpu_to_be16((tANI_U16)eWNI_SME_ADD_STA_SELF_REQ);
pMsg->mesgLen = pal_cpu_to_be16(msgLen);
// self station address
vos_mem_copy((tANI_U8 *)pMsg->selfMacAddr,
(tANI_U8 *)&pAddStaReq->selfMacAddr, sizeof(tSirMacAddr));
pMsg->currDeviceMode = pAddStaReq->currDeviceMode;
smsLog( pMac, LOG1, FL("selfMac="MAC_ADDRESS_STR),
MAC_ADDR_ARRAY(pMsg->selfMacAddr));
status = palSendMBMessage(pMac->hHdd, pMsg);
} while( 0 );
return( status );
}
eHalStatus csrIssueAddStaForSessionReq(tpAniSirGlobal pMac,
tANI_U32 sessionId,
tSirMacAddr sessionMacAddr)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tSmeCmd *pCommand;
pCommand = csrGetCommandBuffer(pMac);
if(NULL == pCommand)
{
status = eHAL_STATUS_RESOURCES;
}
else
{
pCommand->command = eSmeCommandAddStaSession;
pCommand->sessionId = (tANI_U8)sessionId;
vos_mem_copy(pCommand->u.addStaSessionCmd.selfMacAddr, sessionMacAddr,
sizeof( tSirMacAddr ) );
pCommand->u.addStaSessionCmd.currDeviceMode = pMac->sme.currDeviceMode;
status = csrQueueSmeCommand(pMac, pCommand, TRUE);
if( !HAL_STATUS_SUCCESS( status ) )
{
//Should be panic??
smsLog( pMac, LOGE, FL(" fail to send message status = %d"), status );
}
}
return (status);
}
eHalStatus csrProcessAddStaSessionCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand )
{
return csrSendMBAddSelfStaReqMsg(pMac, &pCommand->u.addStaSessionCmd);
}
eHalStatus csrRoamOpenSession(tpAniSirGlobal pMac,
csrRoamCompleteCallback callback,
void *pContext, tANI_U8 *pSelfMacAddr,
tANI_U8 *pbSessionId)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tANI_U32 i;
tCsrRoamSession *pSession = NULL;
*pbSessionId = CSR_SESSION_ID_INVALID;
for( i = 0; i < CSR_ROAM_SESSION_MAX; i++ )
{
if( !CSR_IS_SESSION_VALID( pMac, i ) )
{
pSession = CSR_GET_SESSION( pMac, i );
status = eHAL_STATUS_SUCCESS;
pSession->sessionActive = eANI_BOOLEAN_TRUE;
pSession->sessionId = (tANI_U8)i;
pSession->callback = callback;
pSession->pContext = pContext;
vos_mem_copy(&pSession->selfMacAddr, pSelfMacAddr, sizeof(tCsrBssid));
*pbSessionId = (tANI_U8)i;
status = vos_timer_init(&pSession->hTimerRoaming, VOS_TIMER_TYPE_SW,
csrRoamRoamingTimerHandler,
&pSession->roamingTimerInfo);
if (!HAL_STATUS_SUCCESS(status))
{
smsLog(pMac, LOGE, FL("cannot allocate memory for Roaming timer"));
break;
}
#ifdef FEATURE_WLAN_BTAMP_UT_RF
status = vos_timer_init(&pSession->hTimerJoinRetry, VOS_TIMER_TYPE_SW,
csrRoamJoinRetryTimerHandler,
&pSession->joinRetryTimerInfo);
if (!HAL_STATUS_SUCCESS(status))
{
smsLog(pMac, LOGE, FL("cannot allocate memory for joinretry timer"));
break;
}
#endif
status = csrIssueAddStaForSessionReq (pMac, i, pSelfMacAddr);
break;
}
}
if( CSR_ROAM_SESSION_MAX == i )
{
//No session is available
status = eHAL_STATUS_RESOURCES;
}
return ( status );
}
eHalStatus csrProcessDelStaSessionRsp( tpAniSirGlobal pMac, tANI_U8 *pMsg)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tListElem *pEntry = NULL;
tSmeCmd *pCommand = NULL;
tSirSmeDelStaSelfRsp *pRsp;
do
{
if(pMsg == NULL)
{
smsLog(pMac, LOGE, "in %s msg ptr is NULL", __func__);
status = eHAL_STATUS_FAILURE;
break;
}
pEntry = csrLLPeekHead( &pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK );
if(pEntry)
{
pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link );
if(eSmeCommandDelStaSession == pCommand->command)
{
tANI_U8 sessionId = pCommand->sessionId;
pRsp = (tSirSmeDelStaSelfRsp*)pMsg;
smsLog( pMac, LOG1, "Del Sta rsp status = %d", pRsp->status );
//This session is done.
csrCleanupSession(pMac, sessionId);
if(pCommand->u.delStaSessionCmd.callback)
{
status = sme_ReleaseGlobalLock( &pMac->sme );
if ( HAL_STATUS_SUCCESS( status ) )
{
pCommand->u.delStaSessionCmd.callback(
pCommand->u.delStaSessionCmd.pContext);
status = sme_AcquireGlobalLock( &pMac->sme );
if (! HAL_STATUS_SUCCESS( status ) )
{
smsLog(pMac, LOGP, "%s: Failed to Acquire Lock", __func__);
return status;
}
}
else {
smsLog(pMac, LOGE, "%s: Failed to Release Lock", __func__);
}
}
//Remove this command out of the active list
if(csrLLRemoveEntry(&pMac->sme.smeCmdActiveList, pEntry, LL_ACCESS_LOCK))
{
//Now put this command back on the avilable command list
csrReleaseCommand(pMac, pCommand);
}
smeProcessPendingQueue( pMac );
}
else
{
smsLog(pMac, LOGE, "in %s eWNI_SME_DEL_STA_SELF_RSP Received but NO Del sta session command are ACTIVE ...",
__func__);
status = eHAL_STATUS_FAILURE;
break;
}
}
else
{
smsLog(pMac, LOGE, "in %s eWNI_SME_DEL_STA_SELF_RSP Received but NO commands are ACTIVE ...",
__func__);
status = eHAL_STATUS_FAILURE;
break;
}
} while(0);
return status;
}
eHalStatus csrSendMBDelSelfStaReqMsg( tpAniSirGlobal pMac, tSirMacAddr macAddr )
{
tSirSmeDelStaSelfReq *pMsg;
tANI_U16 msgLen;
eHalStatus status = eHAL_STATUS_FAILURE;
do {
msgLen = sizeof( tANI_U16 ) + sizeof( tANI_U16 ) + sizeof( tSirMacAddr ) /*+
sizeof( tSirBssType )*/;
pMsg = vos_mem_malloc(msgLen);
if ( NULL == pMsg ) return eHAL_STATUS_FAILURE;
vos_mem_set(pMsg, msgLen, 0);
pMsg->mesgType = pal_cpu_to_be16((tANI_U16)eWNI_SME_DEL_STA_SELF_REQ);
pMsg->mesgLen = pal_cpu_to_be16(msgLen);
// self station address
vos_mem_copy((tANI_U8 *)pMsg->selfMacAddr, (tANI_U8 *)macAddr,
sizeof(tSirMacAddr));
status = palSendMBMessage(pMac->hHdd, pMsg);
} while( 0 );
return( status );
}
eHalStatus csrIssueDelStaForSessionReq(tpAniSirGlobal pMac, tANI_U32 sessionId,
tANI_BOOLEAN fHighPriority,
tSirMacAddr sessionMacAddr,
csrRoamSessionCloseCallback callback,
void *pContext)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tSmeCmd *pCommand;
pCommand = csrGetCommandBuffer(pMac);
if(NULL == pCommand)
{
status = eHAL_STATUS_RESOURCES;
}
else
{
pCommand->command = eSmeCommandDelStaSession;
pCommand->sessionId = (tANI_U8)sessionId;
pCommand->u.delStaSessionCmd.callback = callback;
pCommand->u.delStaSessionCmd.pContext = pContext;
vos_mem_copy(pCommand->u.delStaSessionCmd.selfMacAddr, sessionMacAddr,
sizeof( tSirMacAddr ));
status = csrQueueSmeCommand(pMac, pCommand, fHighPriority);
if( !HAL_STATUS_SUCCESS( status ) )
{
//Should be panic??
smsLog( pMac, LOGE, FL(" fail to send message status = %d"), status );
}
}
return (status);
}
eHalStatus csrProcessDelStaSessionCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand )
{
return csrSendMBDelSelfStaReqMsg( pMac,
pCommand->u.delStaSessionCmd.selfMacAddr );
}
static void purgeCsrSessionCmdList(tpAniSirGlobal pMac, tANI_U32 sessionId,
bool flush_all)
{
tDblLinkList *pList = &pMac->roam.roamCmdPendingList;
tListElem *pEntry, *pNext;
tSmeCmd *pCommand;
tDblLinkList localList;
vos_mem_zero(&localList, sizeof(tDblLinkList));
if(!HAL_STATUS_SUCCESS(csrLLOpen(pMac->hHdd, &localList)))
{
smsLog(pMac, LOGE, FL(" failed to open list"));
return;
}
csrLLLock(pList);
pEntry = csrLLPeekHead(pList, LL_ACCESS_NOLOCK);
while(pEntry != NULL)
{
pNext = csrLLNext(pList, pEntry, LL_ACCESS_NOLOCK);
pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link );
if (!flush_all &&
csr_is_disconnect_full_power_cmd(pCommand)) {
smsLog(pMac, LOGW, FL(" Ignore disconnect"));
pEntry = pNext;
continue;
}
if(pCommand->sessionId == sessionId)
{
if(csrLLRemoveEntry(pList, pEntry, LL_ACCESS_NOLOCK))
{
csrLLInsertTail(&localList, pEntry, LL_ACCESS_NOLOCK);
}
}
pEntry = pNext;
}
csrLLUnlock(pList);
while( (pEntry = csrLLRemoveHead(&localList, LL_ACCESS_NOLOCK)) )
{
pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link );
csrAbortCommand(pMac, pCommand, eANI_BOOLEAN_TRUE);
}
csrLLClose(&localList);
}
void csrCleanupSession(tpAniSirGlobal pMac, tANI_U32 sessionId)
{
if( CSR_IS_SESSION_VALID( pMac, sessionId ) )
{
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
csrRoamStop(pMac, sessionId);
csrFreeConnectBssDesc(pMac, sessionId);
csrRoamFreeConnectProfile( pMac, &pSession->connectedProfile );
csrRoamFreeConnectedInfo ( pMac, &pSession->connectedInfo);
vos_timer_destroy(&pSession->hTimerRoaming);
#ifdef FEATURE_WLAN_BTAMP_UT_RF
vos_timer_destroy(&pSession->hTimerJoinRetry);
#endif
csrPurgeSmeCmdList(pMac, sessionId, true);
csrInitSession(pMac, sessionId);
}
}
void csrPurgeSmeCmdList(tpAniSirGlobal pMac, tANI_U32 sessionId,
bool flush_all)
{
purgeSmeSessionCmdList(pMac, sessionId,
&pMac->sme.smeCmdPendingList,
flush_all);
if (pMac->fScanOffload)
{
purgeSmeSessionCmdList(pMac, sessionId,
&pMac->sme.smeScanCmdPendingList,
flush_all);
}
purgeCsrSessionCmdList(pMac, sessionId,
flush_all);
}
eHalStatus csrRoamCloseSession( tpAniSirGlobal pMac, tANI_U32 sessionId,
tANI_BOOLEAN fSync, tANI_U8 bPurgeList,
csrRoamSessionCloseCallback callback,
void *pContext )
{
eHalStatus status = eHAL_STATUS_SUCCESS;
if( CSR_IS_SESSION_VALID( pMac, sessionId ) )
{
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
if(fSync)
{
csrCleanupSession(pMac, sessionId);
}
else
{
csrPurgeSmeCmdList(pMac, sessionId, bPurgeList);
/* If bPurgeList is FALSE, it means HDD already free all the
* cmd and later queue few essential cmd. Now sme should process
* the cmd in pending queue order only.Hence we should
* avoid DEL_SELF_STA as high priority cmd.
*/
status = csrIssueDelStaForSessionReq( pMac, sessionId, bPurgeList,
pSession->selfMacAddr, callback, pContext);
}
}
else
{
status = eHAL_STATUS_INVALID_PARAMETER;
}
return ( status );
}
static void csrInitSession( tpAniSirGlobal pMac, tANI_U32 sessionId )
{
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return;
}
pSession->sessionActive = eANI_BOOLEAN_FALSE;
pSession->sessionId = CSR_SESSION_ID_INVALID;
pSession->callback = NULL;
pSession->pContext = NULL;
pSession->connectState = eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED;
// TODO : Confirm pMac->roam.fReadyForPowerSave = eANI_BOOLEAN_FALSE;
csrFreeRoamProfile( pMac, sessionId );
csrRoamFreeConnectProfile(pMac, &pSession->connectedProfile);
csrRoamFreeConnectedInfo( pMac, &pSession->connectedInfo );
csrFreeConnectBssDesc(pMac, sessionId);
csrScanEnable(pMac);
vos_mem_set(&pSession->selfMacAddr, sizeof(tCsrBssid), 0);
if (pSession->pWpaRsnReqIE)
{
vos_mem_free(pSession->pWpaRsnReqIE);
pSession->pWpaRsnReqIE = NULL;
}
pSession->nWpaRsnReqIeLength = 0;
if (pSession->pWpaRsnRspIE)
{
vos_mem_free(pSession->pWpaRsnRspIE);
pSession->pWpaRsnRspIE = NULL;
}
pSession->nWpaRsnRspIeLength = 0;
#ifdef FEATURE_WLAN_WAPI
if (pSession->pWapiReqIE)
{
vos_mem_free(pSession->pWapiReqIE);
pSession->pWapiReqIE = NULL;
}
pSession->nWapiReqIeLength = 0;
if (pSession->pWapiRspIE)
{
vos_mem_free(pSession->pWapiRspIE);
pSession->pWapiRspIE = NULL;
}
pSession->nWapiRspIeLength = 0;
#endif /* FEATURE_WLAN_WAPI */
if (pSession->nAddIEScanLength)
{
memset(pSession->addIEScan, 0 , SIR_MAC_MAX_ADD_IE_LENGTH);
}
pSession->nAddIEScanLength = 0;
if (pSession->pAddIEAssoc)
{
vos_mem_free(pSession->pAddIEAssoc);
pSession->pAddIEAssoc = NULL;
}
pSession->nAddIEAssocLength = 0;
}
eHalStatus csrRoamGetSessionIdFromBSSID( tpAniSirGlobal pMac, tCsrBssid *bssid, tANI_U32 *pSessionId )
{
eHalStatus status = eHAL_STATUS_FAILURE;
tANI_U32 i;
for( i = 0; i < CSR_ROAM_SESSION_MAX; i++ )
{
if( CSR_IS_SESSION_VALID( pMac, i ) )
{
if( csrIsMacAddressEqual( pMac, bssid, &pMac->roam.roamSession[i].connectedProfile.bssid ) )
{
//Found it
status = eHAL_STATUS_SUCCESS;
*pSessionId = i;
break;
}
}
}
return( status );
}
//This function assumes that we only support one IBSS session. We cannot use BSSID to identify
//session because for IBSS, the bssid changes.
static tANI_U32 csrFindIbssSession( tpAniSirGlobal pMac )
{
tANI_U32 i, nRet = CSR_SESSION_ID_INVALID;
tCsrRoamSession *pSession;
for( i = 0; i < CSR_ROAM_SESSION_MAX; i++ )
{
if( CSR_IS_SESSION_VALID( pMac, i ) )
{
pSession = CSR_GET_SESSION( pMac, i );
if( pSession->pCurRoamProfile && ( csrIsBssTypeIBSS( pSession->connectedProfile.BSSType ) ) )
{
//Found it
nRet = i;
break;
}
}
}
return (nRet);
}
void csrRoamLinkUp(tpAniSirGlobal pMac, tCsrBssid bssid)
{
VOS_STATUS status = VOS_STATUS_SUCCESS;
/* Update the current BSS info in ho control block based on connected
profile info from pmac global structure */
smsLog(pMac, LOGW, " csrRoamLinkUp: WLAN link UP with AP= "MAC_ADDRESS_STR,
MAC_ADDR_ARRAY(bssid));
/* Check for user misconfig of RSSI trigger threshold */
pMac->roam.configParam.vccRssiThreshold =
( 0 == pMac->roam.configParam.vccRssiThreshold ) ?
CSR_VCC_RSSI_THRESHOLD : pMac->roam.configParam.vccRssiThreshold;
pMac->roam.vccLinkQuality = eCSR_ROAM_LINK_QUAL_POOR_IND;
/* Check for user misconfig of UL MAC Loss trigger threshold */
pMac->roam.configParam.vccUlMacLossThreshold =
( 0 == pMac->roam.configParam.vccUlMacLossThreshold ) ?
CSR_VCC_UL_MAC_LOSS_THRESHOLD : pMac->roam.configParam.vccUlMacLossThreshold;
#if defined WLAN_FEATURE_NEIGHBOR_ROAMING
{
tANI_U32 sessionId = 0;
tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo;
/* Indicate the neighbor roal algorithm about the connect indication */
csrRoamGetSessionIdFromBSSID(pMac, (tCsrBssid *)bssid, &sessionId);
csrNeighborRoamIndicateConnect(pMac, sessionId, VOS_STATUS_SUCCESS);
/* Making sure we are roaming force fully to 5GHz AP only once and
* only when we connected to 2.4GH AP only during initial association.
*/
if(pNeighborRoamInfo->cfgParams.neighborInitialForcedRoamTo5GhEnable &&
(GetRFBand(pNeighborRoamInfo->currAPoperationChannel) ==
SIR_BAND_2_4_GHZ)
)
{
status = vos_timer_start(
&pNeighborRoamInfo->forcedInitialRoamTo5GHTimer,
INITIAL_FORCED_ROAM_TO_5G_TIMER_PERIOD);
if ( status != VOS_STATUS_SUCCESS )
{
smsLog(pMac, LOGE,
FL("forcedInitialRoamTo5GHTimer start failed status %d"),
status);
//Send RSO start because in case 5G roaming
//host have not enabled at initial connection
csrRoamOffloadScan(pMac,ROAM_SCAN_OFFLOAD_START,REASON_CONNECT);
}
else
{
smsLog(pMac, LOG1, FL("%s: Forced roam to 5G started Timer"),
__func__);
}
}
/*
* Making ini value to false here only so we just roam to
* only once for whole driver load to unload tenure
* This feature is only applicable for first connection only
*/
if(pNeighborRoamInfo->cfgParams.neighborInitialForcedRoamTo5GhEnable)
{
pNeighborRoamInfo->cfgParams.neighborInitialForcedRoamTo5GhEnable
= VOS_FALSE;
}
}
#endif
}
static void csrRoamLinkDown(tpAniSirGlobal pMac, tANI_U32 sessionId)
{
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
if(!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return;
}
//Only to handle the case for Handover on infra link
if( eCSR_BSS_TYPE_INFRASTRUCTURE != pSession->connectedProfile.BSSType )
{
return;
}
/* deregister the clients requesting stats from PE/TL & also stop the corresponding timers*/
csrRoamDeregStatisticsReq(pMac);
pMac->roam.vccLinkQuality = eCSR_ROAM_LINK_QUAL_POOR_IND;
#if defined WLAN_FEATURE_NEIGHBOR_ROAMING
/* Indicate the neighbor roal algorithm about the disconnect indication */
csrNeighborRoamIndicateDisconnect(pMac, sessionId);
#endif
//Remove this code once SLM_Sessionization is supported
//BMPS_WORKAROUND_NOT_NEEDED
if(!IS_FEATURE_SUPPORTED_BY_FW(SLM_SESSIONIZATION) &&
csrIsInfraApStarted( pMac ) &&
pMac->roam.configParam.doBMPSWorkaround)
{
pMac->roam.configParam.doBMPSWorkaround = 0;
}
}
void csrRoamTlStatsTimerHandler(void *pv)
{
tpAniSirGlobal pMac = PMAC_STRUCT( pv );
eHalStatus status;
pMac->roam.tlStatsReqInfo.timerRunning = FALSE;
smsLog(pMac, LOG1, FL(" TL stat timer is no-op. It needs to support multiple stations"));
#if 0
// TODO Persession .???
//req TL for stats
if(WLANTL_GetStatistics(pMac->roam.gVosContext, &tlStats, pMac->roam.connectedInfo.staId))
{
smsLog(pMac, LOGE, FL("csrRoamTlStatsTimerHandler:couldn't get the stats from TL"));
}
else
{
//save in SME
csrRoamSaveStatsFromTl(pMac, tlStats);
}
#endif
if(!pMac->roam.tlStatsReqInfo.timerRunning)
{
if(pMac->roam.tlStatsReqInfo.periodicity)
{
//start timer
status = vos_timer_start(&pMac->roam.tlStatsReqInfo.hTlStatsTimer,
pMac->roam.tlStatsReqInfo.periodicity);
if (!HAL_STATUS_SUCCESS(status))
{
smsLog(pMac, LOGE, FL("csrRoamTlStatsTimerHandler:cannot start TlStatsTimer timer"));
return;
}
pMac->roam.tlStatsReqInfo.timerRunning = TRUE;
}
}
}
void csrRoamPeStatsTimerHandler(void *pv)
{
tCsrPeStatsReqInfo *pPeStatsReqListEntry = (tCsrPeStatsReqInfo *)pv;
eHalStatus status;
tpAniSirGlobal pMac = pPeStatsReqListEntry->pMac;
VOS_STATUS vosStatus;
tPmcPowerState powerState;
pPeStatsReqListEntry->timerRunning = FALSE;
if( pPeStatsReqListEntry->timerStopFailed == TRUE )
{
// If we entered here, meaning the timer could not be successfully
// stopped in csrRoamRemoveEntryFromPeStatsReqList(). So do it here.
/* Destroy the timer */
vosStatus = vos_timer_destroy( &pPeStatsReqListEntry->hPeStatsTimer );
if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
{
smsLog(pMac, LOGE, FL("csrRoamPeStatsTimerHandler:failed to destroy hPeStatsTimer timer"));
}
// Free the entry
vos_mem_free(pPeStatsReqListEntry);
pPeStatsReqListEntry = NULL;
}
else
{
if(!pPeStatsReqListEntry->rspPending)
{
status = csrSendMBStatsReqMsg(pMac, pPeStatsReqListEntry->statsMask & ~(1 << eCsrGlobalClassDStats),
pPeStatsReqListEntry->staId);
if(!HAL_STATUS_SUCCESS(status))
{
smsLog(pMac, LOGE, FL("csrRoamPeStatsTimerHandler:failed to send down stats req to PE"));
}
else
{
pPeStatsReqListEntry->rspPending = TRUE;
}
}
//send down a req
if(pPeStatsReqListEntry->periodicity &&
(VOS_TIMER_STATE_STOPPED == vos_timer_getCurrentState(&pPeStatsReqListEntry->hPeStatsTimer)))
{
pmcQueryPowerState(pMac, &powerState, NULL, NULL);
if(ePMC_FULL_POWER == powerState)
{
if(pPeStatsReqListEntry->periodicity < pMac->roam.configParam.statsReqPeriodicity)
{
pPeStatsReqListEntry->periodicity = pMac->roam.configParam.statsReqPeriodicity;
}
}
else
{
if(pPeStatsReqListEntry->periodicity < pMac->roam.configParam.statsReqPeriodicityInPS)
{
pPeStatsReqListEntry->periodicity = pMac->roam.configParam.statsReqPeriodicityInPS;
}
}
//start timer
vosStatus = vos_timer_start( &pPeStatsReqListEntry->hPeStatsTimer, pPeStatsReqListEntry->periodicity );
if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
{
smsLog(pMac, LOGE, FL("csrRoamPeStatsTimerHandler:cannot start hPeStatsTimer timer"));
return;
}
pPeStatsReqListEntry->timerRunning = TRUE;
}
}
}
void csrRoamStatsClientTimerHandler(void *pv)
{
tCsrStatsClientReqInfo *pStaEntry = (tCsrStatsClientReqInfo *)pv;
if(VOS_TIMER_STATE_STOPPED == vos_timer_getCurrentState(&pStaEntry->timer))
{
#if 0
// TODO Stats fix for multisession
//start the timer
vosStatus = vos_timer_start( &pStaEntry->timer, pStaEntry->periodicity );
if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
{
smsLog(pStaEntry->pMac, LOGE, FL("csrGetStatistics:cannot start StatsClient timer"));
}
#endif
}
#if 0
//send up the stats report
csrRoamReportStatistics(pStaEntry->pMac, pStaEntry->statsMask, pStaEntry->callback,
pStaEntry->staId, pStaEntry->pContext);
#endif
}
eHalStatus csrSendMBStatsReqMsg( tpAniSirGlobal pMac, tANI_U32 statsMask, tANI_U8 staId)
{
tAniGetPEStatsReq *pMsg;
eHalStatus status = eHAL_STATUS_SUCCESS;
tSirMsgQ msgQ;
pMsg = vos_mem_malloc(sizeof(tAniGetPEStatsReq));
if ( NULL == pMsg )
{
smsLog(pMac, LOGE, FL( "Failed to allocate mem for stats req "));
return eHAL_STATUS_FAILURE;
}
// need to initiate a stats request to PE
pMsg->msgType = pal_cpu_to_be16((tANI_U16)WDA_GET_STATISTICS_REQ);
pMsg->msgLen = (tANI_U16)sizeof(tAniGetPEStatsReq);
pMsg->staId = staId;
pMsg->statsMask = statsMask;
msgQ.type = WDA_GET_STATISTICS_REQ;
msgQ.reserved = 0;
msgQ.bodyptr = pMsg;
msgQ.bodyval = 0;
status = wdaPostCtrlMsg(pMac, &msgQ);
if(!HAL_STATUS_SUCCESS(status))
{
smsLog(pMac, LOG1, FL("Failed to send down the stats req "));
vos_mem_free(pMsg);
}
return status;
}
void csrRoamStatsRspProcessor(tpAniSirGlobal pMac, tSirSmeRsp *pSirMsg)
{
tAniGetPEStatsRsp *pSmeStatsRsp;
eHalStatus status = eHAL_STATUS_FAILURE;
tListElem *pEntry = NULL;
tCsrStatsClientReqInfo *pTempStaEntry = NULL;
tCsrPeStatsReqInfo *pPeStaEntry = NULL;
tANI_U32 tempMask = 0;
tANI_U8 counter = 0;
tANI_U8 *pStats = NULL;
tANI_U32 length = 0;
v_PVOID_t pvosGCtx;
v_S7_t rssi = 0, snr = 0;
tANI_U32 *pRssi = NULL, *pSnr = NULL;
tAniPerTxPktStatsInfo * txPacketInfo;
tANI_U32 linkCapacity;
pSmeStatsRsp = (tAniGetPEStatsRsp *)pSirMsg;
if(pSmeStatsRsp->rc)
{
smsLog( pMac, LOGW, FL("csrRoamStatsRspProcessor:stats rsp from PE shows failure"));
goto post_update;
}
tempMask = pSmeStatsRsp->statsMask;
pStats = ((tANI_U8 *)&pSmeStatsRsp->statsMask) + sizeof(pSmeStatsRsp->statsMask);
/* subtract all statistics from this length, and after processing the entire
* 'stat' part of the message, if the length is not zero, then rssi is piggy packed
* in this 'stats' message.
*/
length = pSmeStatsRsp->msgLen - sizeof(tAniGetPEStatsRsp);
//new stats info from PE, fill up the stats strucutres in PMAC
while(tempMask)
{
if(tempMask & 1)
{
switch(counter)
{
case eCsrSummaryStats:
smsLog( pMac, LOG2, FL("csrRoamStatsRspProcessor:summary stats"));
vos_mem_copy((tANI_U8 *)&pMac->roam.summaryStatsInfo,
pStats, sizeof(tCsrSummaryStatsInfo));
pStats += sizeof(tCsrSummaryStatsInfo);
length -= sizeof(tCsrSummaryStatsInfo);
break;
case eCsrGlobalClassAStats:
smsLog( pMac, LOG2, FL("csrRoamStatsRspProcessor:ClassA stats"));
vos_mem_copy((tANI_U8 *)&pMac->roam.classAStatsInfo,
pStats, sizeof(tCsrGlobalClassAStatsInfo));
pStats += sizeof(tCsrGlobalClassAStatsInfo);
length -= sizeof(tCsrGlobalClassAStatsInfo);
break;
case eCsrGlobalClassBStats:
smsLog( pMac, LOG2, FL("csrRoamStatsRspProcessor:ClassB stats"));
vos_mem_copy((tANI_U8 *)&pMac->roam.classBStatsInfo,
pStats, sizeof(tCsrGlobalClassBStatsInfo));
pStats += sizeof(tCsrGlobalClassBStatsInfo);
length -= sizeof(tCsrGlobalClassBStatsInfo);
break;
case eCsrGlobalClassCStats:
smsLog( pMac, LOG2, FL("csrRoamStatsRspProcessor:ClassC stats"));
vos_mem_copy((tANI_U8 *)&pMac->roam.classCStatsInfo,
pStats, sizeof(tCsrGlobalClassCStatsInfo));
pStats += sizeof(tCsrGlobalClassCStatsInfo);
length -= sizeof(tCsrGlobalClassCStatsInfo);
break;
case eCsrPerStaStats:
smsLog( pMac, LOG2, FL("csrRoamStatsRspProcessor:PerSta stats"));
if( CSR_MAX_STA > pSmeStatsRsp->staId )
{
status = eHAL_STATUS_SUCCESS;
vos_mem_copy((tANI_U8 *)&pMac->roam.perStaStatsInfo[pSmeStatsRsp->staId],
pStats, sizeof(tCsrPerStaStatsInfo));
}
else
{
status = eHAL_STATUS_FAILURE;
smsLog( pMac, LOGE, FL("csrRoamStatsRspProcessor:out bound staId:%d"), pSmeStatsRsp->staId);
VOS_ASSERT( 0 );
}
if(!HAL_STATUS_SUCCESS(status))
{
smsLog( pMac, LOGW, FL("csrRoamStatsRspProcessor:failed to copy PerSta stats"));
}
pStats += sizeof(tCsrPerStaStatsInfo);
length -= sizeof(tCsrPerStaStatsInfo);
break;
case eCsrPerPktStats:
smsLog( pMac, LOG2, FL("csrRoamStatsRspProcessor:PerPkt stats"));
vos_mem_zero(&pMac->roam.perPktStatsInfo, sizeof(tPerTxPacketFrmFw));
if (IS_FEATURE_SUPPORTED_BY_FW(PER_PKT_STATS_SUPPORTED))
{
txPacketInfo = (tAniPerTxPktStatsInfo *)pStats;
pMac->roam.perPktStatsInfo.lastTxRate = txPacketInfo->lastTxRate;
pMac->roam.perPktStatsInfo.txAvgRetry = txPacketInfo->txAvgRetry;
/* for reserved bytes */
pStats += (sizeof(tAniPerTxPktStatsInfo) + 2*sizeof(tANI_U32));
length -= (sizeof(tAniPerTxPktStatsInfo) + 2*sizeof(tANI_U32));
}
break;
default:
smsLog( pMac, LOGW, FL("csrRoamStatsRspProcessor:unknown stats type"));
break;
}
}
tempMask >>=1;
counter++;
}
pvosGCtx = vos_get_global_context(VOS_MODULE_ID_SME, pMac);
if (length != 0)
{
pRssi = (tANI_U32*)pStats;
rssi = (v_S7_t)*pRssi;
pStats += sizeof(tANI_U32);
length -= sizeof(tANI_U32);
}
else
{
/* If riva is not sending rssi, continue to use the hack */
rssi = RSSI_HACK_BMPS;
}
/* send positive value of rssi to wifi_hal */
pMac->roam.perPktStatsInfo.avgRssi = (-1)*rssi;
vos_updatePktStatsInfo(&pMac->roam.perPktStatsInfo);
WDA_UpdateRssiBmps(pvosGCtx, pSmeStatsRsp->staId, rssi);
if (length != 0)
{
linkCapacity = *(tANI_U32*)pStats;
pStats += sizeof(tANI_U32);
length -= sizeof(tANI_U32);
}
else
{
linkCapacity = 0;
}
WDA_UpdateLinkCapacity(pvosGCtx, pSmeStatsRsp->staId, linkCapacity);
if (length != 0)
{
pSnr = (tANI_U32*)pStats;
snr = (v_S7_t)*pSnr;
}
else
{
snr = SNR_HACK_BMPS;
}
WDA_UpdateSnrBmps(pvosGCtx, pSmeStatsRsp->staId, snr);
post_update:
//make sure to update the pe stats req list
pEntry = csrRoamFindInPeStatsReqList(pMac, pSmeStatsRsp->statsMask);
if(pEntry)
{
pPeStaEntry = GET_BASE_ADDR( pEntry, tCsrPeStatsReqInfo, link );
pPeStaEntry->rspPending = FALSE;
}
//check the one timer cases
pEntry = csrRoamCheckClientReqList(pMac, pSmeStatsRsp->statsMask);
if(pEntry)
{
pTempStaEntry = GET_BASE_ADDR( pEntry, tCsrStatsClientReqInfo, link );
if(pTempStaEntry->timerExpired)
{
//send up the stats report
csrRoamReportStatistics(pMac, pTempStaEntry->statsMask, pTempStaEntry->callback,
pTempStaEntry->staId, pTempStaEntry->pContext);
//also remove from the client list
csrRoamRemoveStatListEntry(pMac, pEntry);
pTempStaEntry = NULL;
}
}
}
tListElem * csrRoamFindInPeStatsReqList(tpAniSirGlobal pMac, tANI_U32 statsMask)
{
tListElem *pEntry = NULL;
tCsrPeStatsReqInfo *pTempStaEntry = NULL;
pEntry = csrLLPeekHead( &pMac->roam.peStatsReqList, LL_ACCESS_LOCK );
if(!pEntry)
{
//list empty
smsLog(pMac, LOG2, "csrRoamFindInPeStatsReqList: List empty, no request to PE");
return NULL;
}
while( pEntry )
{
pTempStaEntry = GET_BASE_ADDR( pEntry, tCsrPeStatsReqInfo, link );
if(pTempStaEntry->statsMask == statsMask)
{
smsLog(pMac, LOG3, "csrRoamFindInPeStatsReqList: match found");
break;
}
pEntry = csrLLNext( &pMac->roam.peStatsReqList, pEntry, LL_ACCESS_NOLOCK );
}
return pEntry;
}
tListElem * csrRoamChecknUpdateClientReqList(tpAniSirGlobal pMac, tCsrStatsClientReqInfo *pStaEntry,
tANI_BOOLEAN update)
{
tListElem *pEntry;
tCsrStatsClientReqInfo *pTempStaEntry;
pEntry = csrLLPeekHead( &pMac->roam.statsClientReqList, LL_ACCESS_LOCK );
if(!pEntry)
{
//list empty
smsLog(pMac, LOG2, "csrRoamChecknUpdateClientReqList: List empty, no request from "
"upper layer client(s)");
return NULL;
}
while( pEntry )
{
pTempStaEntry = GET_BASE_ADDR( pEntry, tCsrStatsClientReqInfo, link );
if((pTempStaEntry->requesterId == pStaEntry->requesterId) &&
(pTempStaEntry->statsMask == pStaEntry->statsMask))
{
smsLog(pMac, LOG3, "csrRoamChecknUpdateClientReqList: match found");
if(update)
{
pTempStaEntry->periodicity = pStaEntry->periodicity;
pTempStaEntry->callback = pStaEntry->callback;
pTempStaEntry->pContext = pStaEntry->pContext;
}
break;
}
pEntry = csrLLNext( &pMac->roam.statsClientReqList, pEntry, LL_ACCESS_NOLOCK );
}
return pEntry;
}
tListElem * csrRoamCheckClientReqList(tpAniSirGlobal pMac, tANI_U32 statsMask)
{
tListElem *pEntry;
tCsrStatsClientReqInfo *pTempStaEntry;
pEntry = csrLLPeekHead( &pMac->roam.statsClientReqList, LL_ACCESS_LOCK );
if(!pEntry)
{
//list empty
smsLog(pMac, LOG2, "csrRoamCheckClientReqList: List empty, no request from "
"upper layer client(s)");
return NULL;
}
while( pEntry )
{
pTempStaEntry = GET_BASE_ADDR( pEntry, tCsrStatsClientReqInfo, link );
if((pTempStaEntry->statsMask & ~(1 << eCsrGlobalClassDStats)) == statsMask)
{
smsLog(pMac, LOG3, "csrRoamCheckClientReqList: match found");
break;
}
pEntry = csrLLNext( &pMac->roam.statsClientReqList, pEntry, LL_ACCESS_NOLOCK );
}
return pEntry;
}
eHalStatus csrRoamRegisterLinkQualityIndCallback(tpAniSirGlobal pMac,
csrRoamLinkQualityIndCallback callback,
void *pContext)
{
pMac->roam.linkQualityIndInfo.callback = callback;
pMac->roam.linkQualityIndInfo.context = pContext;
if( NULL == callback )
{
smsLog(pMac, LOGW, "csrRoamRegisterLinkQualityIndCallback: indication callback being deregistered");
}
else
{
smsLog(pMac, LOGW, "csrRoamRegisterLinkQualityIndCallback: indication callback being registered");
/* do we need to invoke the callback to notify client of initial value ?? */
}
return eHAL_STATUS_SUCCESS;
}
void csrRoamVccTrigger(tpAniSirGlobal pMac)
{
eCsrRoamLinkQualityInd newVccLinkQuality;
tANI_U32 ul_mac_loss = 0;
tANI_U32 ul_mac_loss_trigger_threshold;
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/*-------------------------------------------------------------------------
Link quality is currently binary based on OBIWAN recommended triggers
Check for a change in link quality and notify client if necessary
-------------------------------------------------------------------------*/
ul_mac_loss_trigger_threshold =
pMac->roam.configParam.vccUlMacLossThreshold;
VOS_ASSERT( ul_mac_loss_trigger_threshold != 0 );
smsLog(pMac, LOGW, "csrRoamVccTrigger: UL_MAC_LOSS_THRESHOLD is %d",
ul_mac_loss_trigger_threshold );
if(ul_mac_loss_trigger_threshold < ul_mac_loss)
{
smsLog(pMac, LOGW, "csrRoamVccTrigger: link quality is POOR ");
newVccLinkQuality = eCSR_ROAM_LINK_QUAL_POOR_IND;
}
else
{
smsLog(pMac, LOGW, "csrRoamVccTrigger: link quality is GOOD");
newVccLinkQuality = eCSR_ROAM_LINK_QUAL_GOOD_IND;
}
smsLog(pMac, LOGW, "csrRoamVccTrigger: link qual : *** UL_MAC_LOSS %d *** ",
ul_mac_loss);
if(newVccLinkQuality != pMac->roam.vccLinkQuality)
{
smsLog(pMac, LOGW, "csrRoamVccTrigger: link quality changed: trigger necessary");
if(NULL != pMac->roam.linkQualityIndInfo.callback)
{
smsLog(pMac, LOGW, "csrRoamVccTrigger: link quality indication %d",
newVccLinkQuality );
/* we now invoke the callback once to notify client of initial value */
pMac->roam.linkQualityIndInfo.callback( newVccLinkQuality,
pMac->roam.linkQualityIndInfo.context );
//event: EVENT_WLAN_VCC
}
}
pMac->roam.vccLinkQuality = newVccLinkQuality;
}
VOS_STATUS csrRoamVccTriggerRssiIndCallback(tHalHandle hHal,
v_U8_t rssiNotification,
void * context)
{
tpAniSirGlobal pMac = PMAC_STRUCT( context );
eCsrRoamLinkQualityInd newVccLinkQuality;
// TODO : Session info unavailable
tANI_U32 sessionId = 0;
VOS_STATUS status = VOS_STATUS_SUCCESS;
/*-------------------------------------------------------------------------
Link quality is currently binary based on OBIWAN recommended triggers
Check for a change in link quality and notify client if necessary
-------------------------------------------------------------------------*/
smsLog(pMac, LOGW, "csrRoamVccTriggerRssiIndCallback: RSSI trigger threshold is %d",
pMac->roam.configParam.vccRssiThreshold);
if(!csrIsConnStateConnectedInfra(pMac, sessionId))
{
smsLog(pMac, LOGW, "csrRoamVccTriggerRssiIndCallback: ignoring the indication as we are not connected");
return VOS_STATUS_SUCCESS;
}
if(WLANTL_HO_THRESHOLD_DOWN == rssiNotification)
{
smsLog(pMac, LOGW, "csrRoamVccTriggerRssiIndCallback: link quality is POOR");
newVccLinkQuality = eCSR_ROAM_LINK_QUAL_POOR_IND;
}
else if(WLANTL_HO_THRESHOLD_UP == rssiNotification)
{
smsLog(pMac, LOGW, "csrRoamVccTriggerRssiIndCallback: link quality is GOOD ");
newVccLinkQuality = eCSR_ROAM_LINK_QUAL_GOOD_IND;
}
else
{
smsLog(pMac, LOGW, "csrRoamVccTriggerRssiIndCallback: unknown rssi notification %d", rssiNotification);
//Set to this so the code below won't do anything
newVccLinkQuality = pMac->roam.vccLinkQuality;
VOS_ASSERT(0);
}
if(newVccLinkQuality != pMac->roam.vccLinkQuality)
{
smsLog(pMac, LOGW, "csrRoamVccTriggerRssiIndCallback: link quality changed: trigger necessary");
if(NULL != pMac->roam.linkQualityIndInfo.callback)
{
smsLog(pMac, LOGW, "csrRoamVccTriggerRssiIndCallback: link quality indication %d",
newVccLinkQuality);
/* we now invoke the callback once to notify client of initial value */
pMac->roam.linkQualityIndInfo.callback( newVccLinkQuality,
pMac->roam.linkQualityIndInfo.context );
//event: EVENT_WLAN_VCC
}
}
pMac->roam.vccLinkQuality = newVccLinkQuality;
return status;
}
tCsrStatsClientReqInfo * csrRoamInsertEntryIntoList( tpAniSirGlobal pMac,
tDblLinkList *pStaList,
tCsrStatsClientReqInfo *pStaEntry)
{
tCsrStatsClientReqInfo *pNewStaEntry = NULL;
//if same entity requested for same set of stats with different periodicity &
// callback update it
if(NULL == csrRoamChecknUpdateClientReqList(pMac, pStaEntry, TRUE))
{
pNewStaEntry = vos_mem_malloc(sizeof(tCsrStatsClientReqInfo));
if (NULL == pNewStaEntry)
{
smsLog(pMac, LOGW, "csrRoamInsertEntryIntoList: couldn't allocate memory for the "
"entry");
return NULL;
}
pNewStaEntry->callback = pStaEntry->callback;
pNewStaEntry->pContext = pStaEntry->pContext;
pNewStaEntry->periodicity = pStaEntry->periodicity;
pNewStaEntry->requesterId = pStaEntry->requesterId;
pNewStaEntry->statsMask = pStaEntry->statsMask;
pNewStaEntry->pPeStaEntry = pStaEntry->pPeStaEntry;
pNewStaEntry->pMac = pStaEntry->pMac;
pNewStaEntry->staId = pStaEntry->staId;
pNewStaEntry->timerExpired = pStaEntry->timerExpired;
csrLLInsertTail( pStaList, &pNewStaEntry->link, LL_ACCESS_LOCK );
}
return pNewStaEntry;
}
tCsrPeStatsReqInfo * csrRoamInsertEntryIntoPeStatsReqList( tpAniSirGlobal pMac,
tDblLinkList *pStaList,
tCsrPeStatsReqInfo *pStaEntry)
{
tCsrPeStatsReqInfo *pNewStaEntry = NULL;
pNewStaEntry = vos_mem_malloc(sizeof(tCsrPeStatsReqInfo));
if (NULL == pNewStaEntry)
{
smsLog(pMac, LOGW, "csrRoamInsertEntryIntoPeStatsReqList: couldn't allocate memory for the "
"entry");
return NULL;
}
pNewStaEntry->hPeStatsTimer = pStaEntry->hPeStatsTimer;
pNewStaEntry->numClient = pStaEntry->numClient;
pNewStaEntry->periodicity = pStaEntry->periodicity;
pNewStaEntry->statsMask = pStaEntry->statsMask;
pNewStaEntry->pMac = pStaEntry->pMac;
pNewStaEntry->staId = pStaEntry->staId;
pNewStaEntry->timerRunning = pStaEntry->timerRunning;
pNewStaEntry->rspPending = pStaEntry->rspPending;
csrLLInsertTail( pStaList, &pNewStaEntry->link, LL_ACCESS_LOCK );
return pNewStaEntry;
}
eHalStatus csrGetRssi(tpAniSirGlobal pMac,
tCsrRssiCallback callback,
tANI_U8 staId, tCsrBssid bssId, void *pContext, void* pVosContext)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
vos_msg_t msg;
tANI_U32 sessionId;
tAniGetRssiReq *pMsg;
smsLog(pMac, LOG2, FL("called"));
pMsg = vos_mem_malloc(sizeof(tAniGetRssiReq));
if ( NULL == pMsg )
{
smsLog(pMac, LOGE, " csrGetRssi: failed to allocate mem for req ");
return eHAL_STATUS_FAILURE;
}
csrRoamGetSessionIdFromBSSID(pMac, (tCsrBssid *)bssId, &sessionId);
pMsg->msgType = pal_cpu_to_be16((tANI_U16)eWNI_SME_GET_RSSI_REQ);
pMsg->msgLen = (tANI_U16)sizeof(tAniGetRssiReq);
pMsg->sessionId = sessionId;
pMsg->staId = staId;
pMsg->rssiCallback = callback;
pMsg->pDevContext = pContext;
pMsg->pVosContext = pVosContext;
msg.type = eWNI_SME_GET_RSSI_REQ;
msg.bodyptr = pMsg;
msg.reserved = 0;
if(VOS_STATUS_SUCCESS != vos_mq_post_message(VOS_MQ_ID_SME, &msg))
{
smsLog(pMac, LOGE, " csrGetRssi failed to post msg to self ");
vos_mem_free((void *)pMsg);
status = eHAL_STATUS_FAILURE;
}
smsLog(pMac, LOG2, FL("returned"));
return status;
}
eHalStatus csrGetSnr(tpAniSirGlobal pMac,
tCsrSnrCallback callback,
tANI_U8 staId, tCsrBssid bssId,
void *pContext)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
vos_msg_t msg;
tANI_U32 sessionId;
tAniGetSnrReq *pMsg;
smsLog(pMac, LOG2, FL("called"));
pMsg =(tAniGetSnrReq *)vos_mem_malloc(sizeof(tAniGetSnrReq));
if (NULL == pMsg )
{
smsLog(pMac, LOGE, "%s: failed to allocate mem for req",__func__);
return status;
}
csrRoamGetSessionIdFromBSSID(pMac, (tCsrBssid *)bssId, &sessionId);
pMsg->msgType = pal_cpu_to_be16((tANI_U16)eWNI_SME_GET_SNR_REQ);
pMsg->msgLen = (tANI_U16)sizeof(tAniGetSnrReq);
pMsg->sessionId = sessionId;
pMsg->staId = staId;
pMsg->snrCallback = callback;
pMsg->pDevContext = pContext;
msg.type = eWNI_SME_GET_SNR_REQ;
msg.bodyptr = pMsg;
msg.reserved = 0;
if (VOS_STATUS_SUCCESS != vos_mq_post_message(VOS_MQ_ID_SME, &msg))
{
smsLog(pMac, LOGE, "%s failed to post msg to self", __func__);
vos_mem_free((v_VOID_t *)pMsg);
status = eHAL_STATUS_FAILURE;
}
smsLog(pMac, LOG2, FL("returned"));
return status;
}
#if defined WLAN_FEATURE_VOWIFI_11R || defined FEATURE_WLAN_ESE || defined(FEATURE_WLAN_LFR)
eHalStatus csrGetRoamRssi(tpAniSirGlobal pMac,
tCsrRssiCallback callback,
tANI_U8 staId, tCsrBssid bssId, void *pContext, void* pVosContext)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tAniGetRssiReq *pMsg;
pMsg = vos_mem_malloc(sizeof(tAniGetRssiReq));
if ( NULL == pMsg )
{
smsLog(pMac, LOGE, FL("Failed to allocate mem for req"));
return eHAL_STATUS_FAILURE;
}
// need to initiate a stats request to PE
pMsg->msgType = pal_cpu_to_be16((tANI_U16)eWNI_SME_GET_ROAM_RSSI_REQ);
pMsg->msgLen = (tANI_U16)sizeof(tAniGetRssiReq);
pMsg->staId = staId;
pMsg->rssiCallback = callback;
pMsg->pDevContext = pContext;
pMsg->pVosContext = pVosContext;
status = palSendMBMessage(pMac->hHdd, pMsg );
if(!HAL_STATUS_SUCCESS(status))
{
smsLog(pMac, LOGE, FL(" Failed to send down get rssi req"));
//pMsg is freed by palSendMBMessage
status = eHAL_STATUS_FAILURE;
}
return status;
}
#endif
#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
eHalStatus csrGetTsmStats(tpAniSirGlobal pMac,
tCsrTsmStatsCallback callback,
tANI_U8 staId,
tCsrBssid bssId,
void *pContext,
void* pVosContext,
tANI_U8 tid)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tAniGetTsmStatsReq *pMsg = NULL;
pMsg = (tAniGetTsmStatsReq*)vos_mem_malloc(sizeof(tAniGetTsmStatsReq));
if (NULL == pMsg)
{
smsLog(pMac, LOGE, "csrGetTsmStats: failed to allocate mem for req");
return eHAL_STATUS_FAILED_ALLOC;
}
// need to initiate a stats request to PE
pMsg->msgType = pal_cpu_to_be16((tANI_U16)eWNI_SME_GET_TSM_STATS_REQ);
pMsg->msgLen = (tANI_U16)sizeof(tAniGetTsmStatsReq);
pMsg->staId = staId;
pMsg->tid = tid;
vos_mem_copy(pMsg->bssId, bssId, sizeof(tSirMacAddr));
pMsg->tsmStatsCallback = callback;
pMsg->pDevContext = pContext;
pMsg->pVosContext = pVosContext;
status = palSendMBMessage(pMac->hHdd, pMsg );
if(!HAL_STATUS_SUCCESS(status))
{
smsLog(pMac, LOG1, " csrGetTsmStats: failed to send down the rssi req");
//pMsg is freed by palSendMBMessage
status = eHAL_STATUS_FAILURE;
}
return status;
}
#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
/* ---------------------------------------------------------------------------
\fn csrGetTLSTAState
\helper function to get teh TL STA State whenever the function is called.
\param staId - The staID to be passed to the TL
to get the relevant TL STA State
\return the state as tANI_U16
---------------------------------------------------------------------------*/
tANI_U16 csrGetTLSTAState(tpAniSirGlobal pMac, tANI_U8 staId)
{
WLANTL_STAStateType tlSTAState;
tlSTAState = WLANTL_STA_INIT;
//request TL for STA State
if ( !VOS_IS_STATUS_SUCCESS(WLANTL_GetSTAState(pMac->roam.gVosContext, staId, &tlSTAState)) )
{
smsLog(pMac, LOGE, FL("csrGetTLSTAState:couldn't get the STA state from TL"));
}
return tlSTAState;
}
eHalStatus csrGetStatistics(tpAniSirGlobal pMac, eCsrStatsRequesterType requesterId,
tANI_U32 statsMask,
tCsrStatsCallback callback,
tANI_U32 periodicity, tANI_BOOLEAN cache,
tANI_U8 staId, void *pContext)
{
tCsrStatsClientReqInfo staEntry;
tCsrStatsClientReqInfo *pStaEntry = NULL;
tCsrPeStatsReqInfo *pPeStaEntry = NULL;
tListElem *pEntry = NULL;
tANI_BOOLEAN found = FALSE;
eHalStatus status = eHAL_STATUS_SUCCESS;
tANI_BOOLEAN insertInClientList = FALSE;
VOS_STATUS vosStatus;
WLANTL_TRANSFER_STA_TYPE *pTlStats;
if( csrIsAllSessionDisconnected(pMac) )
{
//smsLog(pMac, LOGW, "csrGetStatistics: wrong state curState(%d) not connected", pMac->roam.curState);
return eHAL_STATUS_FAILURE;
}
if (csrNeighborMiddleOfRoaming((tHalHandle)pMac))
{
smsLog(pMac, LOG1, FL("in the middle of roaming states"));
return eHAL_STATUS_FAILURE;
}
if((!statsMask) && (!callback))
{
//msg
smsLog(pMac, LOGW, "csrGetStatistics: statsMask & callback empty in the request");
return eHAL_STATUS_FAILURE;
}
//for the search list method for deregister
staEntry.requesterId = requesterId;
staEntry.statsMask = statsMask;
//requester wants to deregister or just an error
if((statsMask) && (!callback))
{
pEntry = csrRoamChecknUpdateClientReqList(pMac, &staEntry, FALSE);
if(!pEntry)
{
//msg
smsLog(pMac, LOGW, "csrGetStatistics: callback is empty in the request & couldn't "
"find any existing request in statsClientReqList");
return eHAL_STATUS_FAILURE;
}
else
{
//clean up & return
pStaEntry = GET_BASE_ADDR( pEntry, tCsrStatsClientReqInfo, link );
if(NULL != pStaEntry->pPeStaEntry)
{
pStaEntry->pPeStaEntry->numClient--;
//check if we need to delete the entry from peStatsReqList too
if(!pStaEntry->pPeStaEntry->numClient)
{
csrRoamRemoveEntryFromPeStatsReqList(pMac, pStaEntry->pPeStaEntry);
}
}
//check if we need to stop the tl stats timer too
pMac->roam.tlStatsReqInfo.numClient--;
if(!pMac->roam.tlStatsReqInfo.numClient)
{
if(pMac->roam.tlStatsReqInfo.timerRunning)
{
status = vos_timer_stop(&pMac->roam.tlStatsReqInfo.hTlStatsTimer);
if (!HAL_STATUS_SUCCESS(status))
{
smsLog(pMac, LOGE, FL("csrGetStatistics:cannot stop TlStatsTimer timer"));
return eHAL_STATUS_FAILURE;
}
}
pMac->roam.tlStatsReqInfo.periodicity = 0;
pMac->roam.tlStatsReqInfo.timerRunning = FALSE;
}
if (periodicity)
{
vos_timer_stop(&pStaEntry->timer);
// Destroy the vos timer
vosStatus = vos_timer_destroy(&pStaEntry->timer);
if (!VOS_IS_STATUS_SUCCESS(vosStatus))
{
smsLog(pMac, LOGE, FL("Failed to destroy Client req timer"));
}
}
csrRoamRemoveStatListEntry(pMac, pEntry);
pStaEntry = NULL;
return eHAL_STATUS_SUCCESS;
}
}
if(cache && !periodicity)
{
//return the cached stats
csrRoamReportStatistics(pMac, statsMask, callback, staId, pContext);
}
else
{
//add the request in the client req list
staEntry.callback = callback;
staEntry.pContext = pContext;
staEntry.periodicity = periodicity;
staEntry.pPeStaEntry = NULL;
staEntry.staId = staId;
staEntry.pMac = pMac;
staEntry.timerExpired = FALSE;
//if periodic report requested with non cached result from PE/TL
if(periodicity)
{
//if looking for stats from PE
if(statsMask & ~(1 << eCsrGlobalClassDStats))
{
//check if same request made already & waiting for rsp
pPeStaEntry = csrRoamCheckPeStatsReqList(pMac, statsMask & ~(1 << eCsrGlobalClassDStats),
periodicity, &found, staId);
if(!pPeStaEntry)
{
//bail out, maxed out on number of req for PE
return eHAL_STATUS_FAILURE;
}
else
{
staEntry.pPeStaEntry = pPeStaEntry;
}
}
//request stats from TL rightaway if requested by client, update tlStatsReqInfo if needed
if(statsMask & (1 << eCsrGlobalClassDStats))
{
if(cache && pMac->roam.tlStatsReqInfo.numClient)
{
smsLog(pMac, LOGE, FL("csrGetStatistics:Looking for cached stats from TL"));
}
else
{
//update periodicity
if(pMac->roam.tlStatsReqInfo.periodicity)
{
pMac->roam.tlStatsReqInfo.periodicity =
CSR_ROAM_MIN(periodicity, pMac->roam.tlStatsReqInfo.periodicity);
}
else
{
pMac->roam.tlStatsReqInfo.periodicity = periodicity;
}
if(pMac->roam.tlStatsReqInfo.periodicity < CSR_MIN_TL_STAT_QUERY_PERIOD)
{
pMac->roam.tlStatsReqInfo.periodicity = CSR_MIN_TL_STAT_QUERY_PERIOD;
}
if(!pMac->roam.tlStatsReqInfo.timerRunning)
{
pTlStats = (WLANTL_TRANSFER_STA_TYPE *)vos_mem_malloc(sizeof(WLANTL_TRANSFER_STA_TYPE));
if (NULL != pTlStats)
{
//req TL for class D stats
if(WLANTL_GetStatistics(pMac->roam.gVosContext, pTlStats, staId))
{
smsLog(pMac, LOGE, FL("csrGetStatistics:couldn't get the stats from TL"));
}
else
{
//save in SME
csrRoamSaveStatsFromTl(pMac, pTlStats);
}
vos_mem_free(pTlStats);
pTlStats = NULL;
}
else
{
smsLog(pMac, LOGE, FL("cannot allocate memory for TL stat"));
}
if(pMac->roam.tlStatsReqInfo.periodicity)
{
//start timer
status = vos_timer_start(&pMac->roam.tlStatsReqInfo.hTlStatsTimer,
pMac->roam.tlStatsReqInfo.periodicity);
if (!HAL_STATUS_SUCCESS(status))
{
smsLog(pMac, LOGE, FL("csrGetStatistics:cannot start TlStatsTimer timer"));
return eHAL_STATUS_FAILURE;
}
pMac->roam.tlStatsReqInfo.timerRunning = TRUE;
}
}
}
pMac->roam.tlStatsReqInfo.numClient++;
}
insertInClientList = TRUE;
}
//if one time report requested with non cached result from PE/TL
else if(!cache && !periodicity)
{
if(statsMask & ~(1 << eCsrGlobalClassDStats))
{
//send down a req
status = csrSendMBStatsReqMsg(pMac, statsMask & ~(1 << eCsrGlobalClassDStats), staId);
if(!HAL_STATUS_SUCCESS(status))
{
smsLog(pMac, LOGE, FL("csrGetStatistics:failed to send down stats req to PE"));
}
//so that when the stats rsp comes back from PE we respond to upper layer
//right away
staEntry.timerExpired = TRUE;
insertInClientList = TRUE;
}
if(statsMask & (1 << eCsrGlobalClassDStats))
{
pTlStats = (WLANTL_TRANSFER_STA_TYPE *)vos_mem_malloc(sizeof(WLANTL_TRANSFER_STA_TYPE));
if (NULL != pTlStats)
{
//req TL for class D stats
if(!VOS_IS_STATUS_SUCCESS(WLANTL_GetStatistics(pMac->roam.gVosContext, pTlStats, staId)))
{
smsLog(pMac, LOGE, FL("csrGetStatistics:couldn't get the stats from TL"));
}
else
{
//save in SME
csrRoamSaveStatsFromTl(pMac, pTlStats);
}
vos_mem_free(pTlStats);
pTlStats = NULL;
}
else
{
smsLog(pMac, LOGE, FL("cannot allocate memory for TL stat"));
}
}
//if looking for stats from TL only
if(!insertInClientList)
{
//return the stats
csrRoamReportStatistics(pMac, statsMask, callback, staId, pContext);
}
}
if(insertInClientList)
{
pStaEntry = csrRoamInsertEntryIntoList(pMac, &pMac->roam.statsClientReqList, &staEntry);
if(!pStaEntry)
{
//msg
smsLog(pMac, LOGW, "csrGetStatistics: Failed to insert req in statsClientReqList");
return eHAL_STATUS_FAILURE;
}
pStaEntry->periodicity = periodicity;
//Init & start timer if needed
if(periodicity)
{
vosStatus = vos_timer_init( &pStaEntry->timer, VOS_TIMER_TYPE_SW,
csrRoamStatsClientTimerHandler, pStaEntry );
if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
{
smsLog(pMac, LOGE, FL("csrGetStatistics:cannot init StatsClient timer"));
return eHAL_STATUS_FAILURE;
}
vosStatus = vos_timer_start( &pStaEntry->timer, periodicity );
if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
{
smsLog(pMac, LOGE, FL("csrGetStatistics:cannot start StatsClient timer"));
return eHAL_STATUS_FAILURE;
}
}
}
}
return eHAL_STATUS_SUCCESS;
}
#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
static tSirRetStatus
csrRoamScanOffloadPopulateMacHeader(tpAniSirGlobal pMac,
tANI_U8* pBD,
tANI_U8 type,
tANI_U8 subType,
tSirMacAddr peerAddr,
tSirMacAddr selfMacAddr)
{
tSirRetStatus statusCode = eSIR_SUCCESS;
tpSirMacMgmtHdr pMacHdr;
/* Prepare MAC management header */
pMacHdr = (tpSirMacMgmtHdr) (pBD);
/* Prepare FC */
pMacHdr->fc.protVer = SIR_MAC_PROTOCOL_VERSION;
pMacHdr->fc.type = type;
pMacHdr->fc.subType = subType;
/* Prepare Address 1 */
vos_mem_copy((tANI_U8 *) pMacHdr->da, (tANI_U8 *) peerAddr,
sizeof( tSirMacAddr ));
sirCopyMacAddr(pMacHdr->sa,selfMacAddr);
/* Prepare Address 3 */
vos_mem_copy((tANI_U8 *) pMacHdr->bssId, (tANI_U8 *) peerAddr,
sizeof( tSirMacAddr ));
return statusCode;
} /*** csrRoamScanOffloadPopulateMacHeader() ***/
static tSirRetStatus
csrRoamScanOffloadPrepareProbeReqTemplate(tpAniSirGlobal pMac,
tANI_U8 nChannelNum,
tANI_U32 dot11mode,
tSirMacAddr selfMacAddr,
tANI_U8 *pFrame,
tANI_U16 *pusLen)
{
tDot11fProbeRequest pr;
tANI_U32 nStatus, nBytes, nPayload;
tSirRetStatus nSirStatus;
/*Bcast tx*/
tSirMacAddr bssId = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
vos_mem_set(( tANI_U8* )&pr, sizeof( pr ), 0);
PopulateDot11fSuppRates( pMac, nChannelNum, &pr.SuppRates,NULL);
if ( WNI_CFG_DOT11_MODE_11B != dot11mode )
{
PopulateDot11fExtSuppRates1( pMac, nChannelNum, &pr.ExtSuppRates );
}
if (IS_DOT11_MODE_HT(dot11mode))
{
PopulateDot11fHTCaps( pMac, NULL, &pr.HTCaps );
}
nStatus = dot11fGetPackedProbeRequestSize( pMac, &pr, &nPayload );
if ( DOT11F_FAILED( nStatus ) )
{
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
"Failed to calculate the packed size f"
"or a Probe Request (0x%08x).\n", nStatus );
nPayload = sizeof( tDot11fProbeRequest );
}
else if ( DOT11F_WARNED( nStatus ) )
{
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
"There were warnings while calculating"
"the packed size for a Probe Request ("
"0x%08x).\n", nStatus );
}
nBytes = nPayload + sizeof( tSirMacMgmtHdr );
/* Prepare outgoing frame*/
vos_mem_set(pFrame, nBytes , 0);
nSirStatus = csrRoamScanOffloadPopulateMacHeader( pMac, pFrame, SIR_MAC_MGMT_FRAME,
SIR_MAC_MGMT_PROBE_REQ, bssId,selfMacAddr);
if ( eSIR_SUCCESS != nSirStatus )
{
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
"Failed to populate the buffer descriptor for a Probe Request (%d).\n",
nSirStatus );
return nSirStatus;
}
nStatus = dot11fPackProbeRequest( pMac, &pr, pFrame +
sizeof( tSirMacMgmtHdr ),
nPayload, &nPayload );
if ( DOT11F_FAILED( nStatus ) )
{
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
"Failed to pack a Probe Request (0x%08x).\n", nStatus );
return eSIR_FAILURE;
}
else if ( DOT11F_WARNED( nStatus ) )
{
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
"There were warnings while packing a Probe Request (0x%08x).\n",
nStatus );
}
*pusLen = nPayload + sizeof(tSirMacMgmtHdr);
return eSIR_SUCCESS;
}
/*
* Below Table describe whether RSO command can be send down to fimrware or not.
* Host check it on the basis of previous RSO command sent down to firmware.
||===========================================================================||
|| New cmd | LAST SENT COMMAND ---> ||
||====|======================================================================||
|| V | RSO_START | RSO_STOP | RSO_RESTART | RSO_UPDATE_CFG ||
|| --------------------------------------------------------------------------||
|| RSO_START | NO | YES | NO | NO ||
|| RSO_STOP | YES | NO | YES | YES ||
|| RSO_RESTART | YES | NO | YES | YES ||
|| RSO_UPDATE_CFG | YES | NO | YES | YES ||
||===========================================================================||
*/
#define RSO_START_BIT (1<<ROAM_SCAN_OFFLOAD_START)
#define RSO_STOP_BIT (1<<ROAM_SCAN_OFFLOAD_STOP)
#define RSO_RESTART_BIT (1<<ROAM_SCAN_OFFLOAD_RESTART)
#define RSO_UPDATE_CFG_BIT (1<<ROAM_SCAN_OFFLOAD_UPDATE_CFG)
#define RSO_START_ALLOW_MASK ( RSO_STOP_BIT )
#define RSO_STOP_ALLOW_MASK ( RSO_UPDATE_CFG_BIT | RSO_RESTART_BIT | \
RSO_START_BIT )
#define RSO_RESTART_ALLOW_MASK ( RSO_UPDATE_CFG_BIT | RSO_START_BIT | \
RSO_RESTART_BIT )
#define RSO_UPDATE_CFG_ALLOW_MASK (RSO_UPDATE_CFG_BIT | RSO_RESTART_BIT | \
RSO_START_BIT)
tANI_BOOLEAN CsrIsRSOCommandAllowed(tpAniSirGlobal pMac, tANI_U8 command)
{
tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo;
tANI_U8 desiredMask = 0;
switch(command)
{
case ROAM_SCAN_OFFLOAD_START:
desiredMask = RSO_START_ALLOW_MASK;
break;
case ROAM_SCAN_OFFLOAD_STOP:
desiredMask = RSO_STOP_ALLOW_MASK;
break;
case ROAM_SCAN_OFFLOAD_RESTART:
desiredMask = RSO_RESTART_ALLOW_MASK;
break;
case ROAM_SCAN_OFFLOAD_UPDATE_CFG:
desiredMask = RSO_UPDATE_CFG_ALLOW_MASK;
break;
default:
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
FL("Wrong RSO command %d, not allowed"), command);
return 0;/*Cmd Not allowed*/
}
return ( desiredMask & ( 1 << pNeighborRoamInfo->lastSentCmd) );
}
eCsrBand GetCurrentBand(tANI_U8 channel)
{
tSirRFBand Rfband;
eCsrBand band;
Rfband = GetRFBand(channel);
if (Rfband == SIR_BAND_5_GHZ)
band = eCSR_BAND_5G;
else if (Rfband == SIR_BAND_2_4_GHZ)
band = eCSR_BAND_24;
else if (Rfband == SIR_BAND_UNKNOWN)
band = eCSR_BAND_MAX;
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
"channel %d Rfband %d band %d", channel, Rfband, band);
return band;
}
eHalStatus csrRoamOffloadScan(tpAniSirGlobal pMac, tANI_U8 command, tANI_U8 reason)
{
vos_msg_t msg;
vos_msg_t PERroamScanConfigMsg = {0};
tSirRoamOffloadScanReq *pRequestBuf;
tSirPERRoamOffloadScanReq *PERRoamReqBuf;
tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo;
tCsrRoamSession *pSession = NULL;
tANI_U8 i,j,num_channels = 0, ucDot11Mode;
tANI_U8 *ChannelList = NULL;
tANI_U32 sessionId = 0;
eHalStatus status = eHAL_STATUS_SUCCESS;
tpCsrChannelInfo currChannelListInfo;
tANI_U32 host_channels = 0;
tANI_U8 ChannelCacheStr[128] = {0};
eCsrBand eBand, Rfband = eCSR_BAND_ALL;
tSirBssDescription *pBssDesc = NULL;
tDot11fBeaconIEs *pIes = NULL;
tANI_U8 minRate = 0, dataRate;
tANI_U8 operationChannel = 0;
currChannelListInfo = &pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo;
if (0 == csrRoamIsRoamOffloadScanEnabled(pMac))
{
smsLog( pMac, LOGE,"isRoamOffloadScanEnabled not set");
return eHAL_STATUS_FAILURE;
}
if ((VOS_TRUE == bRoamScanOffloadStarted) && (ROAM_SCAN_OFFLOAD_START == command))
{
smsLog( pMac, LOGE,"Roam Scan Offload is already started");
return eHAL_STATUS_FAILURE;
}
/*The Dynamic Config Items Update may happen even if the state is in INIT.
* It is important to ensure that the command is passed down to the FW only
* if the Infra Station is in a connected state.A connected station could also be
* in a PREAUTH or REASSOC states.So, consider not sending the command down in INIT state.
* We also have to ensure that if there is a STOP command we always have to inform Riva,
* irrespective of whichever state we are in.*/
if ((pMac->roam.neighborRoamInfo.neighborRoamState == eCSR_NEIGHBOR_ROAM_STATE_INIT) &&
(command != ROAM_SCAN_OFFLOAD_STOP))
{
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
FL("Scan Command not sent to FW with state = %s and cmd=%d\n"),
macTraceGetNeighbourRoamState(
pMac->roam.neighborRoamInfo.neighborRoamState), command);
return eHAL_STATUS_FAILURE;
}
if (!CsrIsRSOCommandAllowed(pMac, command))
{
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
FL("RSO command %d lastSentCmd %d, RSO is out of sync in HOST-FWR"),
command, pNeighborRoamInfo->lastSentCmd);
return eHAL_STATUS_FAILURE;
}
/* We dont need psession during ROAM_SCAN_OFFLOAD_STOP
* Also there are cases where pNeighborRoamInfo->currAPbssid
* is set to 0 during disconnect and so we might return without stopping
* the roam scan. So no need to find the session if command is
* ROAM_SCAN_OFFLOAD_STOP.
*/
status = csrRoamGetSessionIdFromBSSID(pMac,
(tCsrBssid *)pNeighborRoamInfo->currAPbssid,
&sessionId);
if( ROAM_SCAN_OFFLOAD_STOP != command )
{
if ( !HAL_STATUS_SUCCESS( status ) )
{
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
"%s: Not able to find the sessionId for Roam Offload scan request", __func__);
return eHAL_STATUS_FAILURE;
}
pSession = CSR_GET_SESSION( pMac, sessionId );
if (NULL == pSession)
{
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
"%s:pSession is null", __func__);
return eHAL_STATUS_FAILURE;
}
pBssDesc = pSession->pConnectBssDesc;
if (pBssDesc == NULL)
{
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
"%s: pBssDesc not found for current session", __func__);
return eHAL_STATUS_FAILURE;
}
operationChannel = pSession->connectedProfile.operationChannel;
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
"operationChannel %d", operationChannel);
}
pRequestBuf = vos_mem_malloc(sizeof(tSirRoamOffloadScanReq));
if (NULL == pRequestBuf)
{
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
"%s: Not able to allocate memory for Roam Offload scan request", __func__);
return eHAL_STATUS_FAILED_ALLOC;
}
#ifdef FEATURE_WLAN_DIAG_SUPPORT
limDiagEventReport(pMac, WLAN_PE_DIAG_ROAM_REQUESTED, NULL,
eSIR_SUCCESS, eSIR_SUCCESS);
#endif
vos_mem_zero(pRequestBuf, sizeof(tSirRoamOffloadScanReq));
/* If command is STOP, then pass down ScanOffloadEnabled as Zero.This will handle the case of
* host driver reloads, but Riva still up and running*/
pRequestBuf->Command = command;
if(command == ROAM_SCAN_OFFLOAD_STOP)
{
pRequestBuf->RoamScanOffloadEnabled = 0;
pRequestBuf->StartScanReason = reason;
/*For a STOP Command, there is no need to
* go through filling up all the below parameters
* since they are not required for the STOP command*/
goto send_roam_scan_offload_cmd;
}
else
pRequestBuf->RoamScanOffloadEnabled = pMac->roam.configParam.isRoamOffloadScanEnabled;
vos_mem_copy(pRequestBuf->ConnectedNetwork.currAPbssid,
pNeighborRoamInfo->currAPbssid,
sizeof(tCsrBssid));
pRequestBuf->ConnectedNetwork.ssId.length =
pMac->roam.roamSession[sessionId].connectedProfile.SSID.length;
vos_mem_copy(pRequestBuf->ConnectedNetwork.ssId.ssId,
pMac->roam.roamSession[sessionId].connectedProfile.SSID.ssId,
pRequestBuf->ConnectedNetwork.ssId.length);
pRequestBuf->ConnectedNetwork.authentication =
pMac->roam.roamSession[sessionId].connectedProfile.AuthType;
pRequestBuf->ConnectedNetwork.encryption =
pMac->roam.roamSession[sessionId].connectedProfile.EncryptionType;
pRequestBuf->ConnectedNetwork.mcencryption =
pMac->roam.roamSession[sessionId].connectedProfile.mcEncryptionType;
if (pNeighborRoamInfo->cfgParams.neighborLookupThreshold)
{
pRequestBuf->LookupThreshold =
(v_S7_t)pNeighborRoamInfo->cfgParams.neighborLookupThreshold * (-1);
pRequestBuf->RxSensitivityThreshold = LFR_SENSITIVITY_THR_DEFAULT;
}
else
{
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "Calculate Adaptive Threshold");
if (!HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, pBssDesc, &pIes)))
{
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
"%s: csrGetParsedBssDescriptionIEs failed", __func__);
vos_mem_free(pRequestBuf);
return eHAL_STATUS_FAILURE;
}
if(NULL == pIes)
{
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
"%s : pIes is Null", __func__);
vos_mem_free(pRequestBuf);
return eHAL_STATUS_FAILURE;
}
if (pIes->SuppRates.present)
{
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "Number \t Rate");
/*Check for both basic rates and extended rates.*/
for (i = 0; i < pIes->SuppRates.num_rates; i++)
{
/*Check if the Rate is Mandatory or Not*/
if (csrRatesIsDot11RateSupported(pMac, pIes->SuppRates.rates[i])
&& (pIes->SuppRates.rates[i] & 0x80))
{
/*Retrieve the actual data rate*/
dataRate = (pIes->SuppRates.rates[i] & 0x7F)/2;
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%d \t\t %d", i, dataRate);
if (minRate == 0)
minRate = dataRate;
else
minRate = (minRate < dataRate) ? minRate:dataRate;
}
}
if (pIes->ExtSuppRates.present)
{
for (i = 0; i < pIes->ExtSuppRates.num_rates; i++)
{
/*Check if the Rate is Mandatory or Not*/
if (csrRatesIsDot11RateSupported(pMac, pIes->ExtSuppRates.rates[i])
&& (pIes->ExtSuppRates.rates[i] & 0x80))
{
/*Retrieve the actual data rate*/
dataRate = (pIes->ExtSuppRates.rates[i] & 0x7F)/2;
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%d \t\t %d", i, dataRate);
if (minRate == 0)
minRate = dataRate;
else
minRate = (minRate < dataRate) ? minRate:dataRate;
}
}
}
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, "MinRate = %d", minRate);
}
else
{
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
"%s: Supp Rates not present in pIes", __func__);
vos_mem_free(pRequestBuf);
return eHAL_STATUS_FAILURE;
}
if (NULL != pIes)
{
vos_mem_free(pIes);
pIes = NULL;
}
switch (minRate)
{
case 1:
pRequestBuf->RxSensitivityThreshold = LFR_SENSITIVITY_THR_1MBPS;
pRequestBuf->LookupThreshold = LFR_LOOKUP_THR_1MBPS;
break;
case 2:
pRequestBuf->RxSensitivityThreshold = LFR_SENSITIVITY_THR_2MBPS;
pRequestBuf->LookupThreshold = LFR_LOOKUP_THR_2MBPS;
break;
case 5:
pRequestBuf->RxSensitivityThreshold = LFR_SENSITIVITY_THR_5_5MBPS;
pRequestBuf->LookupThreshold = LFR_LOOKUP_THR_5_5MBPS;
break;
case 6:
if (CSR_IS_CHANNEL_24GHZ(operationChannel))
{
pRequestBuf->RxSensitivityThreshold = LFR_SENSITIVITY_THR_6MBPS_2G;
pRequestBuf->LookupThreshold = LFR_LOOKUP_THR_6MBPS_2G;
}
else
{
pRequestBuf->RxSensitivityThreshold = LFR_SENSITIVITY_THR_6MBPS_5G;
pRequestBuf->LookupThreshold = LFR_LOOKUP_THR_6MBPS_5G;
}
break;
case 11:
pRequestBuf->RxSensitivityThreshold = LFR_SENSITIVITY_THR_11MBPS;
pRequestBuf->LookupThreshold = LFR_LOOKUP_THR_11MBPS;
break;
case 12:
if (CSR_IS_CHANNEL_24GHZ(operationChannel))
{
pRequestBuf->RxSensitivityThreshold = LFR_SENSITIVITY_THR_12MBPS_2G;
pRequestBuf->LookupThreshold = LFR_LOOKUP_THR_12MBPS_2G;
}
else
{
pRequestBuf->RxSensitivityThreshold = LFR_SENSITIVITY_THR_12MBPS_5G;
pRequestBuf->LookupThreshold = LFR_LOOKUP_THR_12MBPS_5G;
}
break;
case 24:
if (CSR_IS_CHANNEL_24GHZ(operationChannel))
{
pRequestBuf->RxSensitivityThreshold = LFR_SENSITIVITY_THR_24MBPS_2G;
pRequestBuf->LookupThreshold = LFR_LOOKUP_THR_24MBPS_2G;
}
else
{
pRequestBuf->RxSensitivityThreshold = LFR_SENSITIVITY_THR_24MBPS_5G;
pRequestBuf->LookupThreshold = LFR_LOOKUP_THR_24MBPS_5G;
}
break;
default:
pRequestBuf->LookupThreshold = LFR_LOOKUP_THR_DEFAULT;
pRequestBuf->RxSensitivityThreshold = LFR_SENSITIVITY_THR_DEFAULT;
break;
}
}
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG,
"Chnl=%d,MinRate=%d,RxSenThr=%d,LookupThr=%d",
operationChannel, minRate,
pRequestBuf->RxSensitivityThreshold,
pRequestBuf->LookupThreshold);
pRequestBuf->RoamRssiDiff =
pMac->roam.configParam.RoamRssiDiff;
pRequestBuf->StartScanReason = reason;
pRequestBuf->NeighborScanTimerPeriod =
pNeighborRoamInfo->cfgParams.neighborScanPeriod;
pRequestBuf->NeighborRoamScanRefreshPeriod =
pNeighborRoamInfo->cfgParams.neighborResultsRefreshPeriod;
pRequestBuf->NeighborScanChannelMinTime =
pNeighborRoamInfo->cfgParams.minChannelScanTime;
pRequestBuf->NeighborScanChannelMaxTime =
pNeighborRoamInfo->cfgParams.maxChannelScanTime;
pRequestBuf->EmptyRefreshScanPeriod =
pNeighborRoamInfo->cfgParams.emptyScanRefreshPeriod;
/* MAWC feature */
pRequestBuf->MAWCEnabled =
pMac->roam.configParam.MAWCEnabled;
#ifdef FEATURE_WLAN_ESE
pRequestBuf->IsESEEnabled = pMac->roam.configParam.isEseIniFeatureEnabled;
#endif
if (
#ifdef FEATURE_WLAN_ESE
((pNeighborRoamInfo->isESEAssoc) &&
(pNeighborRoamInfo->roamChannelInfo.IAPPNeighborListReceived ==
eANI_BOOLEAN_FALSE)) ||
(pNeighborRoamInfo->isESEAssoc == eANI_BOOLEAN_FALSE) ||
#endif // ESE
currChannelListInfo->numOfChannels == 0)
{
/*Retrieve the Channel Cache either from ini or from the Occupied Channels list.
* Give Preference to INI Channels.*/
if (pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels)
{
ChannelList = pNeighborRoamInfo->cfgParams.channelInfo.ChannelList;
/*The INI channels need to be filtered with respect to the current
* band that is supported.*/
eBand = pMac->roam.configParam.bandCapability;
if ((eCSR_BAND_24 != eBand) && (eCSR_BAND_5G != eBand) && (eCSR_BAND_ALL != eBand))
{
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
"Invalid band, No operation carried out (Band %d)", eBand);
vos_mem_free(pRequestBuf);
return eHAL_STATUS_FAILURE;
}
if (pMac->roam.configParam.nRoamIntraBand)
{
eBand = GetCurrentBand(operationChannel);
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
"Current Band %d", eBand);
}
for (i=0; i<pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels; i++)
{
if(((eCSR_BAND_24 == eBand) && CSR_IS_CHANNEL_24GHZ(*ChannelList)) ||
((eCSR_BAND_5G == eBand) && CSR_IS_CHANNEL_5GHZ(*ChannelList)) ||
(eCSR_BAND_ALL == eBand))
{
if(*ChannelList && csrRoamIsChannelValid(pMac, *ChannelList) &&
((pMac->roam.configParam.allowDFSChannelRoam) ||
(!CSR_IS_CHANNEL_DFS(*ChannelList))) &&
(num_channels < SIR_ROAM_MAX_CHANNELS))
{
pRequestBuf->ConnectedNetwork.ChannelCache[num_channels++] = *ChannelList;
}
}
ChannelList++;
}
pRequestBuf->ConnectedNetwork.ChannelCount = num_channels;
pRequestBuf->ChannelCacheType = CHANNEL_LIST_STATIC;
}
else
{
ChannelList = pMac->scan.occupiedChannels.channelList;
if (pMac->roam.configParam.nRoamIntraBand)
{
Rfband = GetCurrentBand(operationChannel);
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
"Current Band %d", Rfband);
}
for(i=0; i<pMac->scan.occupiedChannels.numChannels; i++)
{
if(((eCSR_BAND_24 == Rfband) &&
CSR_IS_CHANNEL_24GHZ(*ChannelList)) ||
((eCSR_BAND_5G == Rfband) && CSR_IS_CHANNEL_5GHZ(*ChannelList))
|| (eCSR_BAND_ALL == Rfband))
{
/* Allow DFS channels only if the DFS channel roam flag is
* enabled
*/
if(*ChannelList && ((pMac->roam.configParam.
allowDFSChannelRoam) || (!CSR_IS_CHANNEL_DFS(*ChannelList)))
&& (num_channels < SIR_ROAM_MAX_CHANNELS))
{
pRequestBuf->ConnectedNetwork.ChannelCache[num_channels++]
= *ChannelList;
}
}
ChannelList++;
}
pRequestBuf->ConnectedNetwork.ChannelCount = num_channels;
/* If the profile changes as to what it was earlier, inform the FW through
* FLUSH as ChannelCacheType in which case, the FW will flush the occupied channels
* for the earlier profile and try to learn them afresh.*/
if (reason == REASON_FLUSH_CHANNEL_LIST)
pRequestBuf->ChannelCacheType = CHANNEL_LIST_DYNAMIC_FLUSH;
else {
if ((csrNeighborRoamIsNewConnectedProfile(pMac)) ||
(pMac->roam.configParam.nRoamIntraBand))
pRequestBuf->ChannelCacheType =
CHANNEL_LIST_DYNAMIC_INIT;
else
pRequestBuf->ChannelCacheType =
CHANNEL_LIST_DYNAMIC_UPDATE;
}
}
}
#ifdef FEATURE_WLAN_ESE
else
{
/* If ESE is enabled, and a neighbor Report is received,then
* Ignore the INI Channels or the Occupied Channel List. Consider
* the channels in the neighbor list sent by the ESE AP.*/
if (currChannelListInfo->numOfChannels != 0)
{
ChannelList = currChannelListInfo->ChannelList;
if (pMac->roam.configParam.nRoamIntraBand)
{
Rfband = GetCurrentBand(operationChannel);
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
"Current Band %d", Rfband);
}
for (i=0;i<currChannelListInfo->numOfChannels;i++)
{
if(((eCSR_BAND_24 == Rfband) &&
CSR_IS_CHANNEL_24GHZ(*ChannelList)) ||
((eCSR_BAND_5G == Rfband) && CSR_IS_CHANNEL_5GHZ(*ChannelList))
|| (eCSR_BAND_ALL == Rfband))
{
if(*ChannelList && ((pMac->roam.configParam.
allowDFSChannelRoam) || (!CSR_IS_CHANNEL_DFS(*ChannelList))))
{
pRequestBuf->ConnectedNetwork.ChannelCache[num_channels++] =
*ChannelList;
}
}
ChannelList++;
}
pRequestBuf->ConnectedNetwork.ChannelCount = num_channels;
if (pMac->roam.configParam.nRoamIntraBand)
pRequestBuf->ChannelCacheType = CHANNEL_LIST_DYNAMIC_INIT;
else
pRequestBuf->ChannelCacheType = CHANNEL_LIST_DYNAMIC_UPDATE;
}
}
#endif
for (i = 0, j = 0;j < (sizeof(ChannelCacheStr)/sizeof(ChannelCacheStr[0]))
&& i < pRequestBuf->ConnectedNetwork.ChannelCount; i++)
{
if (j < sizeof(ChannelCacheStr))
{
j += snprintf(ChannelCacheStr + j, sizeof(ChannelCacheStr) - j," %d",
pRequestBuf->ConnectedNetwork.ChannelCache[i]);
}
else
{
break;
}
}
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG,
"ChnlCacheType:%d, No of Chnls:%d,Channels: %s",
pRequestBuf->ChannelCacheType,
pRequestBuf->ConnectedNetwork.ChannelCount,
ChannelCacheStr);
num_channels = 0;
ChannelList = NULL;
/* Maintain the Valid Channels List*/
host_channels = sizeof(pMac->roam.validChannelList);
if (HAL_STATUS_SUCCESS(csrGetCfgValidChannels(pMac, pMac->roam.validChannelList, &host_channels)))
{
ChannelList = pMac->roam.validChannelList;
pMac->roam.numValidChannels = host_channels;
}
else
{
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
"%s:Failed to get the valid channel list", __func__);
vos_mem_free(pRequestBuf);
return eHAL_STATUS_FAILURE;
}
if (pMac->roam.configParam.nRoamIntraBand)
{
Rfband = GetCurrentBand(operationChannel);
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "Current Band %d",
Rfband);
}
for(i=0; i<pMac->roam.numValidChannels; i++)
{
if(((eCSR_BAND_24 == Rfband) && CSR_IS_CHANNEL_24GHZ(*ChannelList)) ||
((eCSR_BAND_5G == Rfband) && CSR_IS_CHANNEL_5GHZ(*ChannelList)) ||
(eCSR_BAND_ALL == Rfband))
{
if(*ChannelList && ((pMac->roam.configParam.allowDFSChannelRoam) ||
(!CSR_IS_CHANNEL_DFS(*ChannelList))))
{
pRequestBuf->ValidChannelList[num_channels++] = *ChannelList;
}
}
ChannelList++;
}
pRequestBuf->ValidChannelCount = num_channels;
pRequestBuf->MDID.mdiePresent =
pMac->roam.roamSession[sessionId].connectedProfile.MDID.mdiePresent;
pRequestBuf->MDID.mobilityDomain =
pMac->roam.roamSession[sessionId].connectedProfile.MDID.mobilityDomain;
pRequestBuf->nProbes = pMac->roam.configParam.nProbes;
pRequestBuf->HomeAwayTime = pMac->roam.configParam.nRoamScanHomeAwayTime;
/* Home Away Time should be at least equal to (MaxDwell time + (2*RFS)),
* where RFS is the RF Switching time. It is twice RFS to consider the
* time to go off channel and return to the home channel. */
if (pRequestBuf->HomeAwayTime < (pRequestBuf->NeighborScanChannelMaxTime + (2 * CSR_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
{
VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_WARN,
"%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)"
" Hence enforcing home away time to disable (0)",
__func__, pRequestBuf->HomeAwayTime,
(pRequestBuf->NeighborScanChannelMaxTime + (2 * CSR_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
pRequestBuf->HomeAwayTime = 0;
}
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG,"HomeAwayTime:%d",pRequestBuf->HomeAwayTime);
pRequestBuf->WeakZoneRssiThresholdForRoam =
pMac->roam.configParam.neighborRoamConfig.nWeakZoneRssiThresholdForRoam;
/*Prepare a probe request for 2.4GHz band and one for 5GHz band*/
ucDot11Mode = (tANI_U8) csrTranslateToWNICfgDot11Mode(pMac,
csrFindBestPhyMode( pMac, pMac->roam.configParam.phyMode ));
csrRoamScanOffloadPrepareProbeReqTemplate(pMac,SIR_ROAM_SCAN_24G_DEFAULT_CH, ucDot11Mode, pSession->selfMacAddr,
pRequestBuf->p24GProbeTemplate, &pRequestBuf->us24GProbeTemplateLen);
csrRoamScanOffloadPrepareProbeReqTemplate(pMac,SIR_ROAM_SCAN_5G_DEFAULT_CH, ucDot11Mode, pSession->selfMacAddr,
pRequestBuf->p5GProbeTemplate, &pRequestBuf->us5GProbeTemplateLen);
send_roam_scan_offload_cmd:
msg.type = WDA_ROAM_SCAN_OFFLOAD_REQ;
msg.reserved = 0;
msg.bodyptr = pRequestBuf;
MTRACE(vos_trace(VOS_MODULE_ID_SME,
TRACE_CODE_SME_TX_WDA_MSG, sessionId, msg.type));
if (!VOS_IS_STATUS_SUCCESS(vos_mq_post_message(VOS_MODULE_ID_WDA, &msg)))
{
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to post WDA_ROAM_SCAN_OFFLOAD_REQ message to WDA", __func__);
vos_mem_free(pRequestBuf);
return eHAL_STATUS_FAILURE;
}
else
{
if (ROAM_SCAN_OFFLOAD_START == command)
bRoamScanOffloadStarted = VOS_TRUE;
else if (ROAM_SCAN_OFFLOAD_STOP == command)
bRoamScanOffloadStarted = VOS_FALSE;
/*update the last sent cmd*/
pNeighborRoamInfo->lastSentCmd = command;
}
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, "Roam Scan Offload Command %d, Reason %d", command, reason);
if (sme_IsFeatureSupportedByFW(PER_BASED_ROAMING) &&
(command != ROAM_SCAN_OFFLOAD_STOP) &&
pMac->roam.configParam.isPERRoamEnabled)
{
/* PER ROAM SCAN */
PERRoamReqBuf = vos_mem_malloc(sizeof(*PERRoamReqBuf));
if (!PERRoamReqBuf)
{
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
"%s: Not able to allocate mem for PERRoamReqBuf", __func__);
return eHAL_STATUS_FAILURE;
}
/* PER Roam Config */
PERRoamReqBuf->rateUpThreshold =
pMac->roam.configParam.rateUpThreshold;
PERRoamReqBuf->rateDownThreshold =
pMac->roam.configParam.rateDownThreshold;
PERRoamReqBuf->waitPeriodForNextPERScan =
pMac->roam.configParam.waitPeriodForNextPERScan;
PERRoamReqBuf->PERtimerThreshold =
pMac->roam.configParam.PERtimerThreshold;
PERRoamReqBuf->isPERRoamCCAEnabled =
pMac->roam.configParam.isPERRoamCCAEnabled;
PERRoamReqBuf->PERRoamFullScanThreshold =
pMac->roam.configParam.PERRoamFullScanThreshold;
PERRoamReqBuf->PERroamTriggerPercent =
pMac->roam.configParam.PERroamTriggerPercent;
PERRoamReqBuf->sessionId = sessionId;
PERroamScanConfigMsg.type = WDA_PER_ROAM_SCAN_OFFLOAD_REQ;
PERroamScanConfigMsg.reserved = 0;
PERroamScanConfigMsg.bodyptr = PERRoamReqBuf;
if (!VOS_IS_STATUS_SUCCESS(vos_mq_post_message(VOS_MODULE_ID_WDA,
&PERroamScanConfigMsg))) {
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
FL("Not able to post WDA_PER_ROAM_SCAN_OFFLOAD_REQ msg to WDA"));
vos_mem_free(PERRoamReqBuf);
return eHAL_STATUS_FAILURE;
}
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG,
FL("rateUpThreshold =%x rateDownThreshold =%x waitPeriodForNextPERScan=%u PERtimerThreshold=%u"),
PERRoamReqBuf->rateUpThreshold,
PERRoamReqBuf->rateDownThreshold,
PERRoamReqBuf->waitPeriodForNextPERScan,
PERRoamReqBuf->PERtimerThreshold);
}
return status;
}
eHalStatus csrRoamOffloadScanRspHdlr(tpAniSirGlobal pMac, tANI_U8 reason)
{
switch(reason)
{
case 0:
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, "Rsp for Roam Scan Offload with failure status");
break;
case REASON_OS_REQUESTED_ROAMING_NOW:
csrNeighborRoamProceedWithHandoffReq(pMac);
break;
case REASON_INITIAL_FORCED_ROAM_TO_5G:
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, "%s recevied REASON_INITIAL_FORCED_ROAM_TO_5G", __func__);
break;
default:
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "Rsp for Roam Scan Offload with reason %d", reason);
}
return eHAL_STATUS_SUCCESS;
}
#endif
tCsrPeStatsReqInfo * csrRoamCheckPeStatsReqList(tpAniSirGlobal pMac, tANI_U32 statsMask,
tANI_U32 periodicity, tANI_BOOLEAN *pFound, tANI_U8 staId)
{
tANI_BOOLEAN found = FALSE;
eHalStatus status = eHAL_STATUS_SUCCESS;
tCsrPeStatsReqInfo staEntry;
tCsrPeStatsReqInfo *pTempStaEntry = NULL;
tListElem *pStaEntry = NULL;
VOS_STATUS vosStatus;
tPmcPowerState powerState;
*pFound = FALSE;
pStaEntry = csrRoamFindInPeStatsReqList(pMac, statsMask);
if(pStaEntry)
{
pTempStaEntry = GET_BASE_ADDR( pStaEntry, tCsrPeStatsReqInfo, link );
if(pTempStaEntry->periodicity)
{
pTempStaEntry->periodicity =
CSR_ROAM_MIN(periodicity, pTempStaEntry->periodicity);
}
else
{
pTempStaEntry->periodicity = periodicity;
}
pTempStaEntry->numClient++;
found = TRUE;
}
else
{
vos_mem_set(&staEntry, sizeof(tCsrPeStatsReqInfo), 0);
staEntry.numClient = 1;
staEntry.periodicity = periodicity;
staEntry.pMac = pMac;
staEntry.rspPending = FALSE;
staEntry.staId = staId;
staEntry.statsMask = statsMask;
staEntry.timerRunning = FALSE;
pTempStaEntry = csrRoamInsertEntryIntoPeStatsReqList(pMac, &pMac->roam.peStatsReqList, &staEntry);
if(!pTempStaEntry)
{
//msg
smsLog(pMac, LOGW, "csrRoamCheckPeStatsReqList: Failed to insert req in peStatsReqList");
return NULL;
}
}
pmcQueryPowerState(pMac, &powerState, NULL, NULL);
if(ePMC_FULL_POWER == powerState)
{
if(pTempStaEntry->periodicity < pMac->roam.configParam.statsReqPeriodicity)
{
pTempStaEntry->periodicity = pMac->roam.configParam.statsReqPeriodicity;
}
}
else
{
if(pTempStaEntry->periodicity < pMac->roam.configParam.statsReqPeriodicityInPS)
{
pTempStaEntry->periodicity = pMac->roam.configParam.statsReqPeriodicityInPS;
}
}
if(!pTempStaEntry->timerRunning)
{
//send down a req in case of one time req, for periodic ones wait for timer to expire
if(!pTempStaEntry->rspPending &&
!pTempStaEntry->periodicity)
{
status = csrSendMBStatsReqMsg(pMac, statsMask & ~(1 << eCsrGlobalClassDStats), staId);
if(!HAL_STATUS_SUCCESS(status))
{
smsLog(pMac, LOGE, FL("csrRoamCheckPeStatsReqList:failed to send down stats req to PE"));
}
else
{
pTempStaEntry->rspPending = TRUE;
}
}
if(pTempStaEntry->periodicity)
{
if(!found)
{
vosStatus = vos_timer_init( &pTempStaEntry->hPeStatsTimer, VOS_TIMER_TYPE_SW,
csrRoamPeStatsTimerHandler, pTempStaEntry );
if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
{
smsLog(pMac, LOGE, FL("csrRoamCheckPeStatsReqList:cannot init hPeStatsTimer timer"));
return NULL;
}
}
//start timer
smsLog(pMac, LOG1, "csrRoamCheckPeStatsReqList:peStatsTimer period %d", pTempStaEntry->periodicity);
vosStatus = vos_timer_start( &pTempStaEntry->hPeStatsTimer, pTempStaEntry->periodicity );
if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
{
smsLog(pMac, LOGE, FL("csrRoamCheckPeStatsReqList:cannot start hPeStatsTimer timer"));
return NULL;
}
pTempStaEntry->timerRunning = TRUE;
}
}
*pFound = found;
return pTempStaEntry;
}
/*
pStaEntry is no longer invalid upon the return of this function.
*/
static void csrRoamRemoveStatListEntry(tpAniSirGlobal pMac, tListElem *pEntry)
{
if(pEntry)
{
if(csrLLRemoveEntry(&pMac->roam.statsClientReqList, pEntry, LL_ACCESS_LOCK))
{
vos_mem_free(GET_BASE_ADDR( pEntry, tCsrStatsClientReqInfo, link ));
}
}
}
void csrRoamRemoveEntryFromPeStatsReqList(tpAniSirGlobal pMac, tCsrPeStatsReqInfo *pPeStaEntry)
{
tListElem *pEntry;
tCsrPeStatsReqInfo *pTempStaEntry;
VOS_STATUS vosStatus;
pEntry = csrLLPeekHead( &pMac->roam.peStatsReqList, LL_ACCESS_LOCK );
if(!pEntry)
{
//list empty
smsLog(pMac, LOGE, FL(" List empty, no stats req for PE"));
return;
}
while( pEntry )
{
pTempStaEntry = GET_BASE_ADDR( pEntry, tCsrPeStatsReqInfo, link );
if( pTempStaEntry && pTempStaEntry->statsMask == pPeStaEntry->statsMask)
{
smsLog(pMac, LOGW, FL("Match found"));
if(pTempStaEntry->timerRunning)
{
vosStatus = vos_timer_stop( &pTempStaEntry->hPeStatsTimer );
/* If we are not able to stop the timer here, just remove
* the entry from the linked list. Destroy the timer object
* and free the memory in the timer CB
*/
if ( vosStatus == VOS_STATUS_SUCCESS )
{
/* the timer is successfully stopped */
pTempStaEntry->timerRunning = FALSE;
/* Destroy the timer */
vosStatus = vos_timer_destroy( &pTempStaEntry->hPeStatsTimer );
if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
{
smsLog(pMac, LOGE, FL("csrRoamRemoveEntryFromPeStatsReqList:failed to destroy hPeStatsTimer timer"));
}
}
else
{
// the timer could not be stopped. Hence destroy and free the
// memory for the PE stat entry in the timer CB.
pTempStaEntry->timerStopFailed = TRUE;
}
}
if(csrLLRemoveEntry(&pMac->roam.peStatsReqList, pEntry, LL_ACCESS_LOCK))
{
// Only free the memory if we could stop the timer successfully
if(!pTempStaEntry->timerStopFailed)
{
vos_mem_free(pTempStaEntry);
pTempStaEntry = NULL;
}
break;
}
pEntry = csrLLNext( &pMac->roam.peStatsReqList, pEntry, LL_ACCESS_NOLOCK );
}
}
return;
}
void csrRoamSaveStatsFromTl(tpAniSirGlobal pMac, WLANTL_TRANSFER_STA_TYPE *pTlStats)
{
pMac->roam.classDStatsInfo.num_rx_bytes_crc_ok = pTlStats->rxBcntCRCok;
pMac->roam.classDStatsInfo.rx_bc_byte_cnt = pTlStats->rxBCBcnt;
pMac->roam.classDStatsInfo.rx_bc_frm_cnt = pTlStats->rxBCFcnt;
pMac->roam.classDStatsInfo.rx_byte_cnt = pTlStats->rxBcnt;
pMac->roam.classDStatsInfo.rx_mc_byte_cnt = pTlStats->rxMCBcnt;
pMac->roam.classDStatsInfo.rx_mc_frm_cnt = pTlStats->rxMCFcnt;
pMac->roam.classDStatsInfo.rx_rate = pTlStats->rxRate;
//?? need per AC
pMac->roam.classDStatsInfo.rx_uc_byte_cnt[0] = pTlStats->rxUCBcnt;
pMac->roam.classDStatsInfo.rx_uc_frm_cnt = pTlStats->rxUCFcnt;
pMac->roam.classDStatsInfo.tx_bc_byte_cnt = pTlStats->txBCBcnt;
pMac->roam.classDStatsInfo.tx_bc_frm_cnt = pTlStats->txBCFcnt;
pMac->roam.classDStatsInfo.tx_mc_byte_cnt = pTlStats->txMCBcnt;
pMac->roam.classDStatsInfo.tx_mc_frm_cnt = pTlStats->txMCFcnt;
//?? need per AC
pMac->roam.classDStatsInfo.tx_uc_byte_cnt[0] = pTlStats->txUCBcnt;
pMac->roam.classDStatsInfo.tx_uc_frm_cnt = pTlStats->txUCFcnt;
}
void csrRoamReportStatistics(tpAniSirGlobal pMac, tANI_U32 statsMask,
tCsrStatsCallback callback, tANI_U8 staId, void *pContext)
{
tANI_U8 stats[500];
tANI_U8 *pStats = NULL;
tANI_U32 tempMask = 0;
tANI_U8 counter = 0;
if(!callback)
{
smsLog(pMac, LOGE, FL("Cannot report callback NULL"));
return;
}
if(!statsMask)
{
smsLog(pMac, LOGE, FL("Cannot report statsMask is 0"));
return;
}
pStats = stats;
tempMask = statsMask;
while(tempMask)
{
if(tempMask & 1)
{
//new stats info from PE, fill up the stats strucutres in PMAC
switch(counter)
{
case eCsrSummaryStats:
smsLog( pMac, LOG2, FL("Summary stats"));
vos_mem_copy( pStats, (tANI_U8 *)&pMac->roam.summaryStatsInfo,
sizeof(tCsrSummaryStatsInfo));
pStats += sizeof(tCsrSummaryStatsInfo);
break;
case eCsrGlobalClassAStats:
smsLog( pMac, LOG2, FL("ClassA stats"));
vos_mem_copy( pStats, (tANI_U8 *)&pMac->roam.classAStatsInfo,
sizeof(tCsrGlobalClassAStatsInfo));
pStats += sizeof(tCsrGlobalClassAStatsInfo);
break;
case eCsrGlobalClassBStats:
smsLog( pMac, LOG2, FL("ClassB stats"));
vos_mem_copy( pStats, (tANI_U8 *)&pMac->roam.classBStatsInfo,
sizeof(tCsrGlobalClassBStatsInfo));
pStats += sizeof(tCsrGlobalClassBStatsInfo);
break;
case eCsrGlobalClassCStats:
smsLog( pMac, LOG2, FL("ClassC stats"));
vos_mem_copy( pStats, (tANI_U8 *)&pMac->roam.classCStatsInfo,
sizeof(tCsrGlobalClassCStatsInfo));
pStats += sizeof(tCsrGlobalClassCStatsInfo);
break;
case eCsrGlobalClassDStats:
smsLog( pMac, LOG2, FL("ClassD stats"));
vos_mem_copy( pStats, (tANI_U8 *)&pMac->roam.classDStatsInfo,
sizeof(tCsrGlobalClassDStatsInfo));
pStats += sizeof(tCsrGlobalClassDStatsInfo);
break;
case eCsrPerStaStats:
smsLog( pMac, LOG2, FL("PerSta stats"));
vos_mem_copy( pStats, (tANI_U8 *)&pMac->roam.perStaStatsInfo[staId],
sizeof(tCsrPerStaStatsInfo));
pStats += sizeof(tCsrPerStaStatsInfo);
break;
case eCsrPerPktStats:
smsLog( pMac, LOG2, FL("PerPkt stats"));
vos_mem_copy( pStats, (tANI_U8 *)&pMac->roam.perPktStatsInfo,
sizeof(tPerTxPacketFrmFw));
pStats += sizeof(tPerTxPacketFrmFw);
break;
default:
smsLog( pMac, LOGE, FL("Unknown stats type and counter %d"), counter);
break;
}
}
tempMask >>=1;
counter++;
}
callback(stats, pContext );
}
eHalStatus csrRoamDeregStatisticsReq(tpAniSirGlobal pMac)
{
tListElem *pEntry = NULL;
tListElem *pPrevEntry = NULL;
tCsrStatsClientReqInfo *pTempStaEntry = NULL;
eHalStatus status = eHAL_STATUS_SUCCESS;
VOS_STATUS vosStatus;
pEntry = csrLLPeekHead( &pMac->roam.statsClientReqList, LL_ACCESS_LOCK );
if(!pEntry)
{
//list empty
smsLog(pMac, LOGW, "csrRoamDeregStatisticsReq: List empty, no request from "
"upper layer client(s)");
return status;
}
while( pEntry )
{
if(pPrevEntry)
{
pTempStaEntry = GET_BASE_ADDR( pPrevEntry, tCsrStatsClientReqInfo, link );
//send up the stats report
csrRoamReportStatistics(pMac, pTempStaEntry->statsMask, pTempStaEntry->callback,
pTempStaEntry->staId, pTempStaEntry->pContext);
csrRoamRemoveStatListEntry(pMac, pPrevEntry);
}
pTempStaEntry = GET_BASE_ADDR( pEntry, tCsrStatsClientReqInfo, link );
if (pTempStaEntry->pPeStaEntry) //pPeStaEntry can be NULL
{
pTempStaEntry->pPeStaEntry->numClient--;
//check if we need to delete the entry from peStatsReqList too
if(!pTempStaEntry->pPeStaEntry->numClient)
{
csrRoamRemoveEntryFromPeStatsReqList(pMac, pTempStaEntry->pPeStaEntry);
}
}
//check if we need to stop the tl stats timer too
pMac->roam.tlStatsReqInfo.numClient--;
if(!pMac->roam.tlStatsReqInfo.numClient)
{
if(pMac->roam.tlStatsReqInfo.timerRunning)
{
status = vos_timer_stop(&pMac->roam.tlStatsReqInfo.hTlStatsTimer);
if (!HAL_STATUS_SUCCESS(status))
{
smsLog(pMac, LOGE, FL("csrRoamDeregStatisticsReq:cannot stop TlStatsTimer timer"));
//we will continue
}
}
pMac->roam.tlStatsReqInfo.periodicity = 0;
pMac->roam.tlStatsReqInfo.timerRunning = FALSE;
}
if (pTempStaEntry->periodicity)
{
//While creating StaEntry in csrGetStatistics,
//Initializing and starting timer only when periodicity is set.
//So Stop and Destroy timer only when periodicity is set.
vos_timer_stop( &pTempStaEntry->timer );
// Destroy the vos timer...
vosStatus = vos_timer_destroy( &pTempStaEntry->timer );
if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
{
smsLog(pMac, LOGE, FL("csrRoamDeregStatisticsReq:failed to destroy Client req timer"));
}
}
pPrevEntry = pEntry;
pEntry = csrLLNext( &pMac->roam.statsClientReqList, pEntry, LL_ACCESS_NOLOCK );
}
//the last one
if(pPrevEntry)
{
pTempStaEntry = GET_BASE_ADDR( pPrevEntry, tCsrStatsClientReqInfo, link );
//send up the stats report
csrRoamReportStatistics(pMac, pTempStaEntry->statsMask, pTempStaEntry->callback,
pTempStaEntry->staId, pTempStaEntry->pContext);
csrRoamRemoveStatListEntry(pMac, pPrevEntry);
}
return status;
}
eHalStatus csrIsFullPowerNeeded( tpAniSirGlobal pMac, tSmeCmd *pCommand,
tRequestFullPowerReason *pReason,
tANI_BOOLEAN *pfNeedPower )
{
tANI_BOOLEAN fNeedFullPower = eANI_BOOLEAN_FALSE;
tRequestFullPowerReason reason = eSME_REASON_OTHER;
tPmcState pmcState;
eHalStatus status = eHAL_STATUS_SUCCESS;
// TODO : Session info unavailable
tANI_U32 sessionId = 0;
if( pfNeedPower )
{
*pfNeedPower = eANI_BOOLEAN_FALSE;
}
//We only handle CSR commands
if( !(eSmeCsrCommandMask & pCommand->command) )
{
return eHAL_STATUS_SUCCESS;
}
//Check PMC state first
pmcState = pmcGetPmcState( pMac );
switch( pmcState )
{
case REQUEST_IMPS:
case IMPS:
if( eSmeCommandScan == pCommand->command )
{
switch( pCommand->u.scanCmd.reason )
{
#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
case eCsrScanGetLfrResult:
#endif
case eCsrScanGetResult:
case eCsrScanBGScanAbort:
case eCsrScanBGScanEnable:
case eCsrScanGetScanChnInfo:
//Internal process, no need for full power
fNeedFullPower = eANI_BOOLEAN_FALSE;
break;
default:
//Other scans are real scan, ask for power
fNeedFullPower = eANI_BOOLEAN_TRUE;
break;
} //switch
}
else
{
//ask for power for roam and status change
fNeedFullPower = eANI_BOOLEAN_TRUE;
}
break;
case REQUEST_BMPS:
case BMPS:
case REQUEST_START_UAPSD:
case UAPSD:
//We treat WOWL same as BMPS
case REQUEST_ENTER_WOWL:
case WOWL:
if( eSmeCommandRoam == pCommand->command )
{
tScanResultList *pBSSList = (tScanResultList *)pCommand->u.roamCmd.hBSSList;
tCsrScanResult *pScanResult;
tListElem *pEntry;
switch ( pCommand->u.roamCmd.roamReason )
{
case eCsrForcedDisassoc:
case eCsrForcedDisassocMICFailure:
reason = eSME_LINK_DISCONNECTED_BY_HDD;
fNeedFullPower = eANI_BOOLEAN_TRUE;
break;
case eCsrSmeIssuedDisassocForHandoff:
case eCsrForcedDeauth:
case eCsrHddIssuedReassocToSameAP:
case eCsrSmeIssuedReassocToSameAP:
fNeedFullPower = eANI_BOOLEAN_TRUE;
break;
case eCsrCapsChange:
fNeedFullPower = eANI_BOOLEAN_TRUE;
break;
case eCsrForcedDisassocSta:
case eCsrForcedDeauthSta:
fNeedFullPower = eANI_BOOLEAN_FALSE;
break;
default:
//Check whether the profile is already connected. If so, no need for full power
//Note: IBSS is ignored for now because we don't support powersave in IBSS
if ( csrIsConnStateConnectedInfra(pMac, sessionId) && pBSSList )
{
//Only need to check the first one
pEntry = csrLLPeekHead(&pBSSList->List, LL_ACCESS_LOCK);
if( pEntry )
{
pScanResult = GET_BASE_ADDR(pEntry, tCsrScanResult, Link);
#if 0
// TODO : Session Specific info pConnectBssDesc
if( csrIsBssIdEqual( pMac, &pScanResult->Result.BssDescriptor, pMac->roam.pConnectBssDesc ) &&
csrIsSsidEqual( pMac, pMac->roam.pConnectBssDesc,
&pScanResult->Result.BssDescriptor, (tDot11fBeaconIEs *)( pScanResult->Result.pvIes ) ) )
{
// Check to see if the Auth type has changed in the Profile. If so, we don't want to Reassociate
// with Authenticating first. To force this, stop the current association (Disassociate) and
// then re 'Join' the AP, wihch will force an Authentication (with the new Auth type) followed by
// a new Association.
if(csrIsSameProfile(pMac, &pMac->roam.connectedProfile, pProfile))
{
if(csrRoamIsSameProfileKeys(pMac, &pMac->roam.connectedProfile, pProfile))
{
//Done, eventually, the command reaches eCsrReassocToSelfNoCapChange;
//No need for full power
//Set the flag so the code later can avoid to do the above
//check again.
pCommand->u.roamCmd.fReassocToSelfNoCapChange = eANI_BOOLEAN_TRUE;
break;
}
}
}
#endif
}
}
//If we are here, full power is needed
fNeedFullPower = eANI_BOOLEAN_TRUE;
break;
}
}
else if( eSmeCommandWmStatusChange == pCommand->command )
{
//need full power for all
fNeedFullPower = eANI_BOOLEAN_TRUE;
reason = eSME_LINK_DISCONNECTED_BY_OTHER;
}
#ifdef FEATURE_WLAN_TDLS
else if( eSmeCommandTdlsAddPeer == pCommand->command )
{
//TDLS link is getting established. need full power
fNeedFullPower = eANI_BOOLEAN_TRUE;
reason = eSME_FULL_PWR_NEEDED_BY_TDLS_PEER_SETUP;
}
#endif
else if (eSmeCommandDelStaSession == pCommand->command)
{
//need full power for all
fNeedFullPower = eANI_BOOLEAN_TRUE;
}
break;
case REQUEST_STOP_UAPSD:
case REQUEST_EXIT_WOWL:
if( eSmeCommandRoam == pCommand->command )
{
fNeedFullPower = eANI_BOOLEAN_TRUE;
switch ( pCommand->u.roamCmd.roamReason )
{
case eCsrForcedDisassoc:
case eCsrForcedDisassocMICFailure:
reason = eSME_LINK_DISCONNECTED_BY_HDD;
break;
default:
break;
}
}
break;
case STOPPED:
case REQUEST_STANDBY:
case STANDBY:
case LOW_POWER:
//We are not supposed to do anything
smsLog( pMac, LOGE, FL( "cannot process because PMC is in"
" stopped/standby state %s (%d)" ),
sme_PmcStatetoString(pmcState), pmcState );
status = eHAL_STATUS_FAILURE;
break;
case FULL_POWER:
case REQUEST_FULL_POWER:
default:
//No need to ask for full power. This has to be FULL_POWER state
break;
} //switch
if( pReason )
{
*pReason = reason;
}
if( pfNeedPower )
{
*pfNeedPower = fNeedFullPower;
}
return ( status );
}
static eHalStatus csrRequestFullPower( tpAniSirGlobal pMac, tSmeCmd *pCommand )
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tANI_BOOLEAN fNeedFullPower = eANI_BOOLEAN_FALSE;
tRequestFullPowerReason reason = eSME_REASON_OTHER;
status = csrIsFullPowerNeeded( pMac, pCommand, &reason, &fNeedFullPower );
if( fNeedFullPower && HAL_STATUS_SUCCESS( status ) )
{
status = pmcRequestFullPower(pMac, csrFullPowerCallback, pMac, reason);
}
return ( status );
}
tSmeCmd *csrGetCommandBuffer( tpAniSirGlobal pMac )
{
tSmeCmd *pCmd = smeGetCommandBuffer( pMac );
if( pCmd )
{
pMac->roam.sPendingCommands++;
}
return ( pCmd );
}
void csrReleaseCommand(tpAniSirGlobal pMac, tSmeCmd *pCommand)
{
if (pMac->roam.sPendingCommands > 0)
{
//All command allocated through csrGetCommandBuffer need to
//decrement the pending count when releasing.
pMac->roam.sPendingCommands--;
smeReleaseCommand( pMac, pCommand );
}
else
{
smsLog(pMac, LOGE, FL( "no pending commands"));
VOS_ASSERT(0);
}
}
//Return SUCCESS is the command is queued, failed
eHalStatus csrQueueSmeCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand, tANI_BOOLEAN fHighPriority )
{
eHalStatus status;
if (!SME_IS_START(pMac))
{
smsLog( pMac, LOGE, FL("Sme in stop state"));
return eHAL_STATUS_FAILURE;
}
if( (eSmeCommandScan == pCommand->command) && pMac->scan.fDropScanCmd )
{
smsLog(pMac, LOGW, FL(" drop scan (scan reason %d) command"),
pCommand->u.scanCmd.reason);
return eHAL_STATUS_CSR_WRONG_STATE;
}
if ((pMac->fScanOffload) && (pCommand->command == eSmeCommandScan))
{
csrLLInsertTail(&pMac->sme.smeScanCmdPendingList,
&pCommand->Link, LL_ACCESS_LOCK);
// process the command queue...
smeProcessPendingQueue(pMac);
status = eHAL_STATUS_SUCCESS;
goto end;
}
//We can call request full power first before putting the command into pending Q
//because we are holding SME lock at this point.
status = csrRequestFullPower( pMac, pCommand );
if( HAL_STATUS_SUCCESS( status ) )
{
tANI_BOOLEAN fNoCmdPending;
//make sure roamCmdPendingList is not empty first
fNoCmdPending = csrLLIsListEmpty( &pMac->roam.roamCmdPendingList, eANI_BOOLEAN_FALSE );
if( fNoCmdPending )
{
smePushCommand( pMac, pCommand, fHighPriority );
}
else
{
//Other commands are waiting for PMC callback, queue the new command to the pending Q
//no list lock is needed since SME lock is held
if( !fHighPriority )
{
csrLLInsertTail( &pMac->roam.roamCmdPendingList, &pCommand->Link, eANI_BOOLEAN_FALSE );
}
else {
csrLLInsertHead( &pMac->roam.roamCmdPendingList, &pCommand->Link, eANI_BOOLEAN_FALSE );
}
}
}
else if( eHAL_STATUS_PMC_PENDING == status )
{
//no list lock is needed since SME lock is held
if( !fHighPriority )
{
csrLLInsertTail( &pMac->roam.roamCmdPendingList, &pCommand->Link, eANI_BOOLEAN_FALSE );
}
else {
csrLLInsertHead( &pMac->roam.roamCmdPendingList, &pCommand->Link, eANI_BOOLEAN_FALSE );
}
//Let caller know the command is queue
status = eHAL_STATUS_SUCCESS;
}
else
{
//Not to decrease pMac->roam.sPendingCommands here. Caller will decrease it when it
//release the command.
smsLog( pMac, LOGE, FL( " cannot queue command %d" ), pCommand->command );
}
end:
return ( status );
}
eHalStatus csrRoamUpdateAPWPSIE( tpAniSirGlobal pMac, tANI_U32 sessionId, tSirAPWPSIEs* pAPWPSIES )
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tSirUpdateAPWPSIEsReq *pMsg;
tANI_U8 *pBuf = NULL, *wTmpBuf = NULL;
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
if (NULL == pSession)
{
smsLog( pMac, LOGE, FL( " Session does not exist for session id %d" ), sessionId);
return eHAL_STATUS_FAILURE;
}
do
{
pMsg = vos_mem_malloc(sizeof(tSirUpdateAPWPSIEsReq));
if ( NULL == pMsg ) return eHAL_STATUS_FAILURE;
vos_mem_set(pMsg, sizeof(tSirUpdateAPWPSIEsReq), 0);
pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_UPDATE_APWPSIE_REQ);
pBuf = (tANI_U8 *)&pMsg->transactionId;
VOS_ASSERT(pBuf);
wTmpBuf = pBuf;
// transactionId
*pBuf = 0;
*( pBuf + 1 ) = 0;
pBuf += sizeof(tANI_U16);
// bssId
vos_mem_copy((tSirMacAddr *)pBuf, &pSession->selfMacAddr,
sizeof(tSirMacAddr) );
pBuf += sizeof(tSirMacAddr);
//sessionId
*pBuf++ = (tANI_U8)sessionId;
// APWPSIEs
vos_mem_copy((tSirAPWPSIEs *)pBuf, pAPWPSIES, sizeof(tSirAPWPSIEs));
pBuf += sizeof(tSirAPWPSIEs);
pMsg->length = pal_cpu_to_be16((tANI_U16)(sizeof(tANI_U32) + (pBuf - wTmpBuf))); //msg_header + msg
status = palSendMBMessage(pMac->hHdd, pMsg);
} while( 0 );
return ( status );
}
eHalStatus csrRoamUpdateWPARSNIEs( tpAniSirGlobal pMac, tANI_U32 sessionId, tSirRSNie * pAPSirRSNie)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tSirUpdateAPWPARSNIEsReq *pMsg;
tANI_U8 *pBuf = NULL, *wTmpBuf = NULL;
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
if (NULL == pSession)
{
smsLog( pMac, LOGE, FL( " Session does not exist for session id %d" ), sessionId);
return eHAL_STATUS_FAILURE;
}
do
{
pMsg = vos_mem_malloc(sizeof(tSirUpdateAPWPARSNIEsReq));
if ( NULL == pMsg ) return eHAL_STATUS_FAILURE;
vos_mem_set(pMsg, sizeof( tSirUpdateAPWPARSNIEsReq ), 0);
pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_SET_APWPARSNIEs_REQ);
pBuf = (tANI_U8 *)&pMsg->transactionId;
wTmpBuf = pBuf;
// transactionId
*pBuf = 0;
*( pBuf + 1 ) = 0;
pBuf += sizeof(tANI_U16);
VOS_ASSERT(pBuf);
// bssId
vos_mem_copy((tSirMacAddr *)pBuf, &pSession->selfMacAddr,
sizeof(tSirMacAddr));
pBuf += sizeof(tSirMacAddr);
// sessionId
*pBuf++ = (tANI_U8)sessionId;
// APWPARSNIEs
vos_mem_copy((tSirRSNie *)pBuf, pAPSirRSNie, sizeof(tSirRSNie));
pBuf += sizeof(tSirRSNie);
pMsg->length = pal_cpu_to_be16((tANI_U16)(sizeof(tANI_U32 ) + (pBuf - wTmpBuf))); //msg_header + msg
status = palSendMBMessage(pMac->hHdd, pMsg);
} while( 0 );
return ( status );
}
tANI_U32 csrGetdot11Mode(tHalHandle hHal, tANI_U32 sessionId,
tpSirBssDescription pBssDescription)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId);
eCsrCfgDot11Mode uCfgDot11Mode, cfgDot11Mode;
eHalStatus status;
tDot11fBeaconIEs *ies_local = NULL;
tANI_U32 dot11mode = 0;
smsLog(pMac, LOG1, FL("phyMode %d"), pSession->pCurRoamProfile->phyMode);
/* Get IE's */
status = csrGetParsedBssDescriptionIEs(pMac, pBssDescription, &ies_local);
if (!HAL_STATUS_SUCCESS(status)) {
smsLog(pMac, LOGE,
FL("csrGetParsedBssDescriptionIEs failed"));
return 0;
}
if(ies_local == NULL) {
smsLog(pMac, LOGE,
FL("ies_local is NULL"));
return 0;
}
if(csrIsPhyModeMatch(pMac, pSession->pCurRoamProfile->phyMode,
pBssDescription, pSession->pCurRoamProfile, &cfgDot11Mode, ies_local))
uCfgDot11Mode = cfgDot11Mode;
else
{
smsLog(pMac, LOGE, "Can not find match phy mode");
if(CSR_IS_CHANNEL_5GHZ(pBssDescription->channelId))
uCfgDot11Mode = eCSR_CFG_DOT11_MODE_11A;
else
uCfgDot11Mode = eCSR_CFG_DOT11_MODE_11G;
}
/* dot11mode */
dot11mode = csrTranslateToWNICfgDot11Mode(pMac, uCfgDot11Mode);
smsLog(pMac, LOG1,
FL("dot11mode %d uCfgDot11Mode %d"), dot11mode, uCfgDot11Mode);
if (pBssDescription->channelId <= 14 &&
FALSE == pMac->roam.configParam.enableVhtFor24GHz &&
WNI_CFG_DOT11_MODE_11AC == dot11mode)
{
/* Need to disable VHT operation in 2.4 GHz band */
dot11mode = WNI_CFG_DOT11_MODE_11N;
}
vos_mem_free(ies_local);
return dot11mode;
}
#ifdef WLAN_FEATURE_VOWIFI_11R
//eHalStatus csrRoamIssueFTPreauthReq(tHalHandle hHal, tANI_U32 sessionId, tCsrBssid preAuthBssid, tANI_U8 channelId)
eHalStatus csrRoamIssueFTPreauthReq(tHalHandle hHal, tANI_U32 sessionId, tpSirBssDescription pBssDescription)
{
tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
tpSirFTPreAuthReq pftPreAuthReq;
tANI_U16 auth_req_len = 0;
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
auth_req_len = sizeof(tSirFTPreAuthReq);
pftPreAuthReq = (tpSirFTPreAuthReq)vos_mem_malloc(auth_req_len);
if (NULL == pftPreAuthReq)
{
smsLog(pMac, LOGE, FL("Memory allocation for FT Preauth request failed"));
return eHAL_STATUS_RESOURCES;
}
// Save the SME Session ID here. We need it while processing the preauth response
pMac->ft.ftSmeContext.smeSessionId = sessionId;
vos_mem_zero(pftPreAuthReq, auth_req_len);
pftPreAuthReq->pbssDescription = (tpSirBssDescription)vos_mem_malloc(
sizeof(pBssDescription->length) + pBssDescription->length);
pftPreAuthReq->messageType = pal_cpu_to_be16(eWNI_SME_FT_PRE_AUTH_REQ);
pftPreAuthReq->preAuthchannelNum = pBssDescription->channelId;
pftPreAuthReq->dot11mode =
csrGetdot11Mode(hHal, sessionId, pBssDescription);
if (!pftPreAuthReq->dot11mode)
{
smsLog(pMac, LOGE, FL("pftPreAuthReq->dot11mode is zero"));
vos_mem_free(pftPreAuthReq);
return eHAL_STATUS_FAILURE;
}
vos_mem_copy((void *)&pftPreAuthReq->currbssId,
(void *)pSession->connectedProfile.bssid, sizeof(tSirMacAddr));
vos_mem_copy((void *)&pftPreAuthReq->preAuthbssId,
(void *)pBssDescription->bssId, sizeof(tSirMacAddr));
#ifdef WLAN_FEATURE_VOWIFI_11R
if (csrRoamIs11rAssoc(pMac) &&
(pMac->roam.roamSession[sessionId].connectedProfile.AuthType != eCSR_AUTH_TYPE_OPEN_SYSTEM))
{
pftPreAuthReq->ft_ies_length = (tANI_U16)pMac->ft.ftSmeContext.auth_ft_ies_length;
vos_mem_copy(pftPreAuthReq->ft_ies, pMac->ft.ftSmeContext.auth_ft_ies,
pMac->ft.ftSmeContext.auth_ft_ies_length);
}
else
#endif
{
pftPreAuthReq->ft_ies_length = 0;
}
vos_mem_copy(pftPreAuthReq->pbssDescription, pBssDescription,
sizeof(pBssDescription->length) + pBssDescription->length);
pftPreAuthReq->length = pal_cpu_to_be16(auth_req_len);
return palSendMBMessage(pMac->hHdd, pftPreAuthReq);
}
/*--------------------------------------------------------------------------
* This will receive and process the FT Pre Auth Rsp from the current
* associated ap.
*
* This will invoke the hdd call back. This is so that hdd can now
* send the FTIEs from the Auth Rsp (Auth Seq 2) to the supplicant.
------------------------------------------------------------------------*/
void csrRoamFTPreAuthRspProcessor( tHalHandle hHal, tpSirFTPreAuthRsp pFTPreAuthRsp )
{
tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
eHalStatus status = eHAL_STATUS_SUCCESS;
#if defined(FEATURE_WLAN_LFR) || defined(FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_ESE_UPLOAD)
tCsrRoamInfo roamInfo;
#endif
eCsrAuthType conn_Auth_type;
#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
status = csrNeighborRoamPreauthRspHandler(pMac, pFTPreAuthRsp->status);
if (status != eHAL_STATUS_SUCCESS) {
/*
* Bail out if pre-auth was not even processed.
*/
smsLog(pMac, LOGE,FL("Preauth was not processed: %d SessionID: %d"),
status, pFTPreAuthRsp->smeSessionId);
return;
}
#endif
/* The below function calls/timers should be invoked only if the pre-auth is successful */
if (VOS_STATUS_SUCCESS != (VOS_STATUS)pFTPreAuthRsp->status)
return;
// Implies a success
pMac->ft.ftSmeContext.FTState = eFT_AUTH_COMPLETE;
// Indicate SME QoS module the completion of Preauth success. This will trigger the creation of RIC IEs
pMac->ft.ftSmeContext.psavedFTPreAuthRsp = pFTPreAuthRsp;
/* No need to notify qos module if this is a non 11r & ESE roam*/
if (csrRoamIs11rAssoc(pMac)
#if defined(FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_ESE_UPLOAD)
|| csrRoamIsESEAssoc(pMac)
#endif
)
{
sme_QosCsrEventInd(pMac, pMac->ft.ftSmeContext.smeSessionId, SME_QOS_CSR_PREAUTH_SUCCESS_IND, NULL);
}
if (pMac->roam.configParam.roamDelayStatsEnabled)
{
vos_record_roam_event(e_CACHE_ROAM_DELAY_DATA, NULL, 0);
}
/* Start the pre-auth reassoc interval timer with a period of 400ms. When this expires,
* actual transition from the current to handoff AP is triggered */
status = vos_timer_start(&pMac->ft.ftSmeContext.preAuthReassocIntvlTimer,
60);
if (pMac->roam.configParam.roamDelayStatsEnabled)
{
vos_record_roam_event(e_SME_PREAUTH_REASSOC_START, NULL, 0);
}
if (eHAL_STATUS_SUCCESS != status)
{
smsLog(pMac, LOGE, FL("Preauth reassoc interval timer start failed to start with status %d"), status);
return;
}
// Save the received response
vos_mem_copy((void *)&pMac->ft.ftSmeContext.preAuthbssId,
(void *)pFTPreAuthRsp->preAuthbssId, sizeof(tCsrBssid));
if (csrRoamIs11rAssoc(pMac))
csrRoamCallCallback(pMac, pFTPreAuthRsp->smeSessionId, NULL, 0,
eCSR_ROAM_FT_RESPONSE, eCSR_ROAM_RESULT_NONE);
#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
if (csrRoamIsESEAssoc(pMac))
{
/* read TSF */
csrRoamReadTSF(pMac, (tANI_U8 *)roamInfo.timestamp);
// Save the bssid from the received response
vos_mem_copy((void *)&roamInfo.bssid, (void *)pFTPreAuthRsp->preAuthbssId, sizeof(tCsrBssid));
csrRoamCallCallback(pMac, pFTPreAuthRsp->smeSessionId, &roamInfo, 0, eCSR_ROAM_CCKM_PREAUTH_NOTIFY, 0);
}
#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
#ifdef FEATURE_WLAN_LFR
// If Legacy Fast Roaming is enabled, signal the supplicant
// So he can send us a PMK-ID for this candidate AP.
if (csrRoamIsFastRoamEnabled(pMac, CSR_SESSION_ID_INVALID))
{
// Save the bssid from the received response
vos_mem_copy((void *)&roamInfo.bssid,
(void *)pFTPreAuthRsp->preAuthbssId, sizeof(tCsrBssid));
csrRoamCallCallback(pMac, pFTPreAuthRsp->smeSessionId, &roamInfo, 0, eCSR_ROAM_PMK_NOTIFY, 0);
}
#endif
// If its an Open Auth, FT IEs are not provided by supplicant
// Hence populate them here
conn_Auth_type = pMac->roam.roamSession[pMac->ft.ftSmeContext.smeSessionId].connectedProfile.AuthType;
pMac->ft.ftSmeContext.addMDIE = FALSE;
if( csrRoamIs11rAssoc(pMac) &&
(conn_Auth_type == eCSR_AUTH_TYPE_OPEN_SYSTEM))
{
tANI_U16 ft_ies_length;
ft_ies_length = pFTPreAuthRsp->ric_ies_length;
if (pMac->roam.roamSession[pMac->ft.ftSmeContext.smeSessionId].
connectedProfile.MDID.mdiePresent)
pMac->ft.ftSmeContext.addMDIE = TRUE;
if ( (pMac->ft.ftSmeContext.reassoc_ft_ies) &&
(pMac->ft.ftSmeContext.reassoc_ft_ies_length))
{
vos_mem_free(pMac->ft.ftSmeContext.reassoc_ft_ies);
pMac->ft.ftSmeContext.reassoc_ft_ies_length = 0;
}
if (!ft_ies_length)
{
pMac->ft.ftSmeContext.psavedFTPreAuthRsp = NULL;
return;
}
pMac->ft.ftSmeContext.reassoc_ft_ies = vos_mem_malloc(ft_ies_length);
if ( NULL == pMac->ft.ftSmeContext.reassoc_ft_ies )
{
smsLog( pMac, LOGE, FL("Memory allocation failed for ft_ies"));
}
else
{
// Copy the RIC IEs to reassoc IEs
vos_mem_copy(((tANI_U8 *)pMac->ft.ftSmeContext.reassoc_ft_ies),
(tANI_U8 *)pFTPreAuthRsp->ric_ies,
pFTPreAuthRsp->ric_ies_length);
pMac->ft.ftSmeContext.reassoc_ft_ies_length = ft_ies_length;
pMac->ft.ftSmeContext.addMDIE = TRUE;
}
}
// Done with it, init it.
pMac->ft.ftSmeContext.psavedFTPreAuthRsp = NULL;
}
#endif
#ifdef FEATURE_WLAN_BTAMP_UT_RF
void csrRoamJoinRetryTimerHandler(void *pv)
{
tCsrTimerInfo *pInfo = (tCsrTimerInfo *)pv;
tpAniSirGlobal pMac = pInfo->pMac;
tANI_U32 sessionId = pInfo->sessionId;
tCsrRoamSession *pSession;
if( CSR_IS_SESSION_VALID(pMac, sessionId) )
{
smsLog( pMac, LOGE, FL( " retrying the last roam profile on session %d" ), sessionId );
pSession = CSR_GET_SESSION( pMac, sessionId );
if(pSession->pCurRoamProfile && csrIsConnStateDisconnected(pMac, sessionId))
{
if( !HAL_STATUS_SUCCESS(csrRoamJoinLastProfile(pMac, sessionId)) )
{
smsLog( pMac, LOGE, FL( " fail to retry the last roam profile" ) );
}
}
}
}
eHalStatus csrRoamStartJoinRetryTimer(tpAniSirGlobal pMac, tANI_U32 sessionId, tANI_U32 interval)
{
eHalStatus status = eHAL_STATUS_FAILURE;
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId );
if(pSession->pCurRoamProfile && pSession->maxRetryCount)
{
smsLog(pMac, LOGE, FL(" call sessionId %d retry count %d left"), sessionId, pSession->maxRetryCount);
pSession->maxRetryCount--;
pSession->joinRetryTimerInfo.pMac = pMac;
pSession->joinRetryTimerInfo.sessionId = (tANI_U8)sessionId;
status = vos_timer_start(&pSession->hTimerJoinRetry, interval/PAL_TIMER_TO_MS_UNIT);
if (!HAL_STATUS_SUCCESS(status))
{
smsLog(pMac, LOGE, FL(" fail to start timer status %s"), status);
}
}
else
{
smsLog(pMac, LOGE, FL(" not to start timer due to no profile or reach mac ret (%d)"),
pSession->maxRetryCount);
}
return (status);
}
eHalStatus csrRoamStopJoinRetryTimer(tpAniSirGlobal pMac, tANI_U32 sessionId)
{
smsLog(pMac, LOGE, " csrRoamStopJoinRetryTimer");
if( CSR_IS_SESSION_VALID(pMac, sessionId) )
{
return (vos_timer_stop(&pMac->roam.roamSession[sessionId].hTimerJoinRetry));
}
return eHAL_STATUS_SUCCESS;
}
#endif
/*
pBuf points to the beginning of the message
LIM packs disassoc rsp as below,
messageType - 2 bytes
messageLength - 2 bytes
sessionId - 1 byte
transactionId - 2 bytes (tANI_U16)
reasonCode - 4 bytes (sizeof(tSirResultCodes))
peerMacAddr - 6 bytes
The rest is conditionally defined of (WNI_POLARIS_FW_PRODUCT == AP) and not used
*/
static void csrSerDesUnpackDiassocRsp(tANI_U8 *pBuf, tSirSmeDisassocRsp *pRsp)
{
if(pBuf && pRsp)
{
pBuf += 4; //skip type and length
pRsp->sessionId = *pBuf++;
pal_get_U16( pBuf, (tANI_U16 *)&pRsp->transactionId );
pBuf += 2;
pal_get_U32( pBuf, (tANI_U32 *)&pRsp->statusCode );
pBuf += 4;
vos_mem_copy(pRsp->peerMacAddr, pBuf, 6);
}
}
eHalStatus csrGetDefaultCountryCodeFrmNv(tpAniSirGlobal pMac, tANI_U8 *pCountry)
{
static uNvTables nvTables;
eHalStatus status = eHAL_STATUS_SUCCESS;
VOS_STATUS vosStatus = vos_nv_readDefaultCountryTable( &nvTables );
/* read the country code from NV and use it */
if ( VOS_IS_STATUS_SUCCESS(vosStatus) )
{
vos_mem_copy(pCountry, nvTables.defaultCountryTable.countryCode,
WNI_CFG_COUNTRY_CODE_LEN);
return status;
}
else
{
vos_mem_copy(pCountry, "XXX", WNI_CFG_COUNTRY_CODE_LEN);
status = eHAL_STATUS_FAILURE;
return status;
}
}
eHalStatus csrGetCurrentCountryCode(tpAniSirGlobal pMac, tANI_U8 *pCountry)
{
vos_mem_copy(pCountry, pMac->scan.countryCode11d, WNI_CFG_COUNTRY_CODE_LEN);
return eHAL_STATUS_SUCCESS;
}
eHalStatus csrSetTxPower(tpAniSirGlobal pMac, v_U8_t sessionId, v_U8_t mW)
{
tSirSetTxPowerReq *pMsg = NULL;
eHalStatus status = eHAL_STATUS_SUCCESS;
tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId);
if (!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return eHAL_STATUS_FAILURE;
}
pMsg = vos_mem_malloc(sizeof(tSirSetTxPowerReq));
if ( NULL == pMsg ) return eHAL_STATUS_FAILURE;
vos_mem_set((void *)pMsg, sizeof(tSirSetTxPowerReq), 0);
pMsg->messageType = eWNI_SME_SET_TX_POWER_REQ;
pMsg->length = sizeof(tSirSetTxPowerReq);
pMsg->mwPower = mW;
vos_mem_copy((tSirMacAddr *)pMsg->bssId, &pSession->selfMacAddr,
sizeof(tSirMacAddr));
status = palSendMBMessage(pMac->hHdd, pMsg);
if (!HAL_STATUS_SUCCESS(status))
{
smsLog(pMac, LOGE, FL(" csr set TX Power Post MSG Fail %d "), status);
//pMsg is freed by palSendMBMessage
}
return status;
}
eHalStatus csrHT40StopOBSSScan(tpAniSirGlobal pMac, v_U8_t sessionId)
{
tSirSmeHT40OBSSStopScanInd *pMsg = NULL;
eHalStatus status = eHAL_STATUS_SUCCESS;
tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId);
if (!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return eHAL_STATUS_FAILURE;
}
if(IS_HT40_OBSS_SCAN_FEATURE_ENABLE)
{
pMsg = vos_mem_malloc(sizeof(tSirSmeHT40OBSSStopScanInd));
if( NULL == pMsg )
{
smsLog(pMac, LOGE, FL("PMsg is NULL "));
return eHAL_STATUS_FAILURE;
}
vos_mem_zero((void *)pMsg, sizeof(tSirSmeHT40OBSSStopScanInd));
pMsg->messageType = eWNI_SME_HT40_STOP_OBSS_SCAN_IND;
pMsg->length =
pal_cpu_to_be16(sizeof(tSirSmeHT40OBSSStopScanInd));
pMsg->seesionId = sessionId;
vos_mem_copy(pMsg->bssid, pSession->connectedProfile.bssid,
sizeof(tSirMacAddr));
status = palSendMBMessage(pMac->hHdd, pMsg);
if (!HAL_STATUS_SUCCESS(status))
{
smsLog(pMac, LOGE, FL(" csr STOP OBSS SCAN Fail %d "), status);
//pMsg is freed by palSendMBMessage
}
}
else
{
smsLog(pMac, LOGE, FL(" OBSS STOP OBSS SCAN is not supported"));
status = eHAL_STATUS_FAILURE;
}
return status;
}
/* Returns whether a session is in VOS_STA_MODE...or not */
tANI_BOOLEAN csrRoamIsStaMode(tpAniSirGlobal pMac, tANI_U32 sessionId)
{
tCsrRoamSession *pSession = NULL;
pSession = CSR_GET_SESSION ( pMac, sessionId );
if(!pSession)
{
smsLog(pMac, LOGE, FL(" %s: session %d not found "), __func__, sessionId);
return eANI_BOOLEAN_FALSE;
}
if ( !CSR_IS_SESSION_VALID ( pMac, sessionId ) )
{
smsLog(pMac, LOGE, FL(" %s: Inactive session"), __func__);
return eANI_BOOLEAN_FALSE;
}
if ( eCSR_BSS_TYPE_INFRASTRUCTURE != pSession->connectedProfile.BSSType )
{
return eANI_BOOLEAN_FALSE;
}
/* There is a possibility that the above check may fail,because
* P2P CLI also uses the same BSSType (eCSR_BSS_TYPE_INFRASTRUCTURE)
* when it is connected.So,we may sneak through the above check even
* if we are not a STA mode INFRA station. So, if we sneak through
* the above condition, we can use the following check if we are
* really in STA Mode.*/
if ( NULL != pSession->pCurRoamProfile )
{
if ( pSession->pCurRoamProfile->csrPersona == VOS_STA_MODE )
{
return eANI_BOOLEAN_TRUE;
} else {
smsLog(pMac, LOGE, FL(" %s: pCurRoamProfile is NULL\n"), __func__);
return eANI_BOOLEAN_FALSE;
}
}
return eANI_BOOLEAN_FALSE;
}
/**
* csr_set_src_handoff_request() - Set handoff source to
* SME handoff request
* @pHandoffInfo: Pointer to Handoff info
* @pMsg: Pointer to SME handoff request message
*
* Return: None
*/
#ifndef QCA_WIFI_ISOC
static inline void csr_set_src_handoff_request(tAniHandoffReq *pMsg,
tCsrHandoffRequest *pHandoffInfo)
{
pMsg->handoff_src = pHandoffInfo->src;
}
#else
static inline void csr_set_src_handoff_request(tAniHandoffReq *pMsg,
tCsrHandoffRequest *pHandoffInfo)
{
}
#endif
#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
eHalStatus csrHandoffRequest(tpAniSirGlobal pMac,
tCsrHandoffRequest *pHandoffInfo)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
vos_msg_t msg;
tAniHandoffReq *pMsg;
pMsg = vos_mem_malloc(sizeof(tAniHandoffReq));
if ( NULL == pMsg )
{
smsLog(pMac, LOGE, " csrHandoffRequest: failed to allocate mem for req ");
return eHAL_STATUS_FAILURE;
}
pMsg->msgType = pal_cpu_to_be16((tANI_U16)eWNI_SME_HANDOFF_REQ);
pMsg->msgLen = (tANI_U16)sizeof(tAniHandoffReq);
pMsg->sessionId = pMac->roam.neighborRoamInfo.csrSessionId;
pMsg->channel = pHandoffInfo->channel;
csr_set_src_handoff_request(pMsg, pHandoffInfo);
vos_mem_copy(pMsg->bssid,
pHandoffInfo->bssid,
6);
msg.type = eWNI_SME_HANDOFF_REQ;
msg.bodyptr = pMsg;
msg.reserved = 0;
if(VOS_STATUS_SUCCESS != vos_mq_post_message(VOS_MQ_ID_SME, &msg))
{
smsLog(pMac, LOGE, " csrHandoffRequest failed to post msg to self ");
vos_mem_free((void *)pMsg);
status = eHAL_STATUS_FAILURE;
}
return status;
}
#endif /* WLAN_FEATURE_ROAM_SCAN_OFFLOAD */
#ifdef WLAN_FEATURE_RMC
eHalStatus csrEnableRMC(tpAniSirGlobal pMac, tANI_U32 sessionId)
{
tSirSetRMCReq *pMsg = NULL;
eHalStatus status = eHAL_STATUS_SUCCESS;
tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId);
if (!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return eHAL_STATUS_FAILURE;
}
pMsg = vos_mem_malloc(sizeof(tSirSetRMCReq));
if (NULL != pMsg)
{
vos_mem_set((void *)pMsg, sizeof(tSirSetRMCReq), 0);
pMsg->msgType = eWNI_SME_ENABLE_RMC_REQ;
pMsg->msgLen = sizeof(tSirSetRMCReq);
vos_mem_copy((v_U8_t *)pMsg->mcastTransmitter,
&pSession->selfMacAddr, sizeof(tSirMacAddr));
status = palSendMBMessage(pMac->hHdd, pMsg);
if (!HAL_STATUS_SUCCESS(status))
{
smsLog(pMac, LOGE, FL(" csr enable RMC Post MSG Fail %d "), status);
//pMsg is freed by palSendMBMessage
}
}
else
{
return eHAL_STATUS_FAILURE;
}
return status;
}
eHalStatus csrDisableRMC(tpAniSirGlobal pMac, tANI_U32 sessionId)
{
tSirSetRMCReq *pMsg = NULL;
eHalStatus status = eHAL_STATUS_SUCCESS;
tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId);
if (!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return eHAL_STATUS_FAILURE;
}
pMsg = vos_mem_malloc(sizeof(tSirSetRMCReq));
if (NULL != pMsg)
{
vos_mem_set((void *)pMsg, sizeof(tSirSetRMCReq), 0);
pMsg->msgType = eWNI_SME_DISABLE_RMC_REQ;
pMsg->msgLen = sizeof(tSirSetRMCReq);
vos_mem_copy((v_U8_t *)pMsg->mcastTransmitter,
&pSession->selfMacAddr, sizeof(tSirMacAddr));
status = palSendMBMessage(pMac->hHdd, pMsg);
if (!HAL_STATUS_SUCCESS(status))
{
smsLog(pMac, LOGE, FL(" csr disable RMC Post MSG Fail %d "), status);
//pMsg is freed by palSendMBMessage
}
}
else
{
return eHAL_STATUS_FAILURE;
}
return status;
}
#endif /* WLAN_FEATURE_RMC */
#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
/* ---------------------------------------------------------------------------
\fn csrSetCCKMIe
\brief This function stores the CCKM IE passed by the supplicant in a place holder
data structure and this IE will be packed inside reassociation request
\param pMac - pMac global structure
\param sessionId - Current session id
\param pCckmIe - pointer to CCKM IE data
\param ccKmIeLen - length of the CCKM IE
\- return Success or failure
-------------------------------------------------------------------------*/
VOS_STATUS csrSetCCKMIe(tpAniSirGlobal pMac, const tANI_U8 sessionId,
const tANI_U8 *pCckmIe,
const tANI_U8 ccKmIeLen)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId);
if (!pSession)
{
smsLog(pMac, LOGE, FL(" session %d not found "), sessionId);
return eHAL_STATUS_FAILURE;
}
vos_mem_copy(pSession->suppCckmIeInfo.cckmIe, pCckmIe, ccKmIeLen);
pSession->suppCckmIeInfo.cckmIeLen = ccKmIeLen;
return status;
}
/* ---------------------------------------------------------------------------
\fn csrRoamReadTSF
\brief This function reads the TSF; and also add the time elapsed since last beacon or
probe response reception from the hand off AP to arrive at the latest TSF value.
\param pMac - pMac global structure
\param pTimestamp - output TSF timestamp
\- return Success or failure
-------------------------------------------------------------------------*/
VOS_STATUS csrRoamReadTSF(tpAniSirGlobal pMac, tANI_U8 *pTimestamp)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tCsrNeighborRoamBSSInfo handoffNode;
tANI_U32 timer_diff = 0;
tANI_U32 timeStamp[2];
tpSirBssDescription pBssDescription = NULL;
csrNeighborRoamGetHandoffAPInfo(pMac, &handoffNode);
pBssDescription = handoffNode.pBssDescription;
// Get the time diff in milli seconds
timer_diff = vos_timer_get_system_time() - pBssDescription->scanSysTimeMsec;
// Convert msec to micro sec timer
timer_diff = (tANI_U32)(timer_diff * SYSTEM_TIME_MSEC_TO_USEC);
timeStamp[0] = pBssDescription->timeStamp[0];
timeStamp[1] = pBssDescription->timeStamp[1];
UpdateCCKMTSF(&(timeStamp[0]), &(timeStamp[1]), &timer_diff);
vos_mem_copy(pTimestamp, (void *) &timeStamp[0],
sizeof (tANI_U32) * 2);
return status;
}
#endif /*FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
/* ---------------------------------------------------------------------------
\fn csrDisableDfsChannel
\brief This function will call csrApplyChannelPowerCountryInfo to
\ to trim the list on basis of NO_DFS flag.
\param pMac - pMac global structure
\- return void
-------------------------------------------------------------------------*/
void csrDisableDfsChannel(tpAniSirGlobal pMac)
{
csrApplyChannelPowerCountryInfo( pMac, &pMac->scan.base20MHzChannels,
pMac->scan.countryCodeCurrent, eANI_BOOLEAN_TRUE);
}
/* ---------------------------------------------------------------------------
\fn csrGetStaticUapsdMask
\brief This function will get the static uapsd settings for an existing
\ Infra session.
\param pMac - pMac global structure
\- return void
-------------------------------------------------------------------------*/
void csrGetStaticUapsdMask(tpAniSirGlobal pMac, tANI_U8 *staticUapsdMask)
{
tANI_S8 sessionId;
tCsrRoamSession *pSession = NULL;
*staticUapsdMask = 0;
sessionId = csrGetInfraSessionId(pMac);
if(sessionId == -1)
smsLog(pMac, LOGE, FL("Valid session not present."));
else
pSession = CSR_GET_SESSION(pMac, sessionId);
if(!pSession || !pSession->pCurRoamProfile)
smsLog(pMac, LOGE, FL("Either pSession or Roam profile is NULL,"
" pSession:%pK"), pSession);
else
*staticUapsdMask = pSession->pCurRoamProfile->uapsd_mask;
}
VOS_STATUS csr_roam_send_chan_sw_ie_request(tpAniSirGlobal mac_ctx,
tCsrBssid bssid, uint8_t new_chan, uint8_t cb_mode)
{
VOS_STATUS status = VOS_STATUS_SUCCESS;
struct sir_ecsa_ie_req *msg;
msg = vos_mem_malloc(sizeof(*msg));
if (!msg) {
smsLog(mac_ctx, LOGE, FL(" Memory alloc failed "));
return VOS_STATUS_E_NOMEM;
}
msg->type = eWNI_SME_SET_CHAN_SW_IE_REQ;
msg->len = sizeof(*msg);
msg->new_chan = new_chan;
msg->cb_mode = cb_mode;
vos_mem_copy(msg->bssid, bssid, VOS_MAC_ADDR_SIZE);
status = palSendMBMessage(mac_ctx->hHdd, msg);
if (!VOS_IS_STATUS_SUCCESS(status))
smsLog(mac_ctx, LOGE,
FL(" channel switch IE req failed status %d "), status);
return status;
}
VOS_STATUS csr_roam_channel_change_req(tpAniSirGlobal mac_ctx,
tCsrBssid bssid, uint8_t new_chan, uint8_t cb_mode, tCsrRoamProfile *profile)
{
VOS_STATUS status = VOS_STATUS_SUCCESS;
struct sir_channel_chanege_req *msg;
tCsrRoamStartBssParams param;
vos_mem_zero(&param, sizeof(tCsrRoamStartBssParams));
csrRoamGetBssStartParms(mac_ctx, profile, &param);
msg = vos_mem_malloc(sizeof(*msg));
if (!msg) {
smsLog(mac_ctx, LOGE, FL(" Memory alloc failed "));
return VOS_STATUS_E_NOMEM;
}
msg->type = eWNI_SME_ECSA_CHAN_CHANGE_REQ;
msg->len = sizeof(*msg);
msg->new_chan = new_chan;
msg->cb_mode = cb_mode;
vos_mem_copy(msg->bssid, bssid, VOS_MAC_ADDR_SIZE);
msg->dot11mode = csrTranslateToWNICfgDot11Mode(mac_ctx,
mac_ctx->roam.configParam.uCfgDot11Mode);
if (IS_24G_CH(msg->new_chan) &&
(false == mac_ctx->roam.configParam.enableVhtFor24GHz) &&
(WNI_CFG_DOT11_MODE_11AC == msg->dot11mode ||
WNI_CFG_DOT11_MODE_11AC_ONLY == msg->dot11mode))
msg->dot11mode = WNI_CFG_DOT11_MODE_11N;
vos_mem_copy(&msg->operational_rateset,
&param.operationalRateSet, sizeof(msg->operational_rateset));
vos_mem_copy(&msg->extended_rateset,
&param.extendedRateSet, sizeof(msg->extended_rateset));
status = palSendMBMessage(mac_ctx->hHdd, msg);
if (!VOS_IS_STATUS_SUCCESS(status))
smsLog(mac_ctx, LOGE,
FL(" channel switch req fauiled status %d "), status);
return status;
}